René Nyffenegger's collection of things on the web
René Nyffenegger on Oracle - Most wanted - Feedback -
 

Virtual base classes in C++

Note, the error codes (C2385) are those emmited by Visual Studio 6. They will be different on another compiler.
class B {
  protected:
    int b_;
};

class D1 : public B {
};

class D2 : public B {
};

class D1v : public virtual B {
};

class D2v : public virtual B {
};

class D : public D1, public D2 {
public:
  void f();
};

class Dvv : public virtual D1, public virtual D2 {
public:
  void f();
};

class D_vv : public D1v, public D2v {
public:
  void f();
};

void D::f() {
  // b_= 4;   // error C2385 D::b_ is ambigous,
              // could be the 'b_' in base 'B' of base 'D1' of class 'D'
              // or the 'b_' in base 'B' of base 'D2' of class 'D'

  D1::b_ = 5; // Ok
  D2::b_ = 6; // Ok
}

void Dvv::f() {
 //  b_ = 4;   // error C2385: 'Dvv::b_' is ambiguous
               // could be the 'b_' in base 'B' of base 'D1' of class 'Dvv'
               // or the 'b_' in base 'B' of base 'D2' of class 'Dvv'

  D1::b_ = 7;  // Ok
  D2::b_ = 8;  // Ok
}
Here is the implementation of D_vv::f. D_vv has to base classes: D1v and D2v which both have B as a virtual base class. Therefore, b_ is shared, and setting b_ is equivalent to setting D1v::b_ which is equivalent to setting D2v::b_.
void D_vv::f() {
  b_=4;  // Ok
  D1v::b_=5;
  D2v::b_=6;
  if (     b_ != D1v::b_ ||
           b_ != D2v::b_ ||
      D1v::b_ != D2v::b_) 
  {
    throw "Should not be thrown";
  }
}

int main() {
  D d;
  d.f();

  Dvv dvv;
  dvv.f();

  D_vv d_vv;
  d_vv.f();

  return 0;
}