Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Virtual base class data members

Why it is recommended not to have data members in virtual base class?

What about function members? If I have a task common to all derived classes is it OK for virtual base class to do the task or should the derived inherit from two classed - from virtual interface and plain base that do the task?

Thanks.

like image 781
jackhab Avatar asked Jul 28 '09 10:07

jackhab


2 Answers

As a practice you should only use virtual inheritance to define interfaces as they are usually used with multiple inheritance to ensure that only one version of the class is present in the derived class. And pure interfaces are the safest form of multiple inheritance. Of course if you know what you are doing you can use multiple inheritance as you like, but it can result in brittle code if you are not careful.

The biggest drawback with virtual inheritance is if their constructors take parameters. If you have to pass parameters to the constructor of a virtual base class you force all derived classes to explicitly call the constructor (they cannot rely on a base class calling the constructor).

The only reason I can see for your explicit advise is that data in your virtual base class these might require constructor parameters.

Edit I did some home work after Martin's comment, thank Marin. The first line is not quite true:

As a practice you should only use virtual inheritance to define interfaces as they are usually used with multiple inheritance to ensure that only one version of the class is present in the derived class.

Virtual inheritance makes no difference if the base class is a pure interface (except for slightly different compiler errors, in vc8, if all the methods are not implemented). It only makes a real difference if the base class has data, in this case you end up with a diamond rather than a U shape

Non virtual    virtual
  A     A          A
  |     |        /   \
  B     C       B     C
   \   /         \   /
     D             D

In the virtual case B and C share the same copy of A.

However I still agree with everything else about pure interfaces being the safest form of multiple inheritance, even if they don't require virtual inheritance. And the fact that constructor parameters and virtual inheritance are a pain.

like image 130
iain Avatar answered Nov 06 '22 19:11

iain


The core advice is to have a default-constructor in the virtual base. If you don't, then every most-derived class (ie. any subclass) must call the virtual base ctor explicitly, and that leads to angry colleagues knocking on your office door...

class VirtualBase {
public:
    explicit VirtualBase( int i ) : m_i( i ) {}
    virtual ~VirtualBase() {}

private:
    int m_i;
};

class Derived : public virtual VirtualBase {
public:
    Derived() : VirtualBase( 0 ) {} // ok, this is to be expected
};

class DerivedDerived : public Derived { // no VirtualBase visible
public:
    DerivedDerived() : Derived() {} // ok? no: error: need to explicitly
                                    // call VirtualBase::VirtualBase!!
    DerivedDerived() : VirtualBase( 0 ), Derived() {} // ok
};
like image 37
Marc Mutz - mmutz Avatar answered Nov 06 '22 19:11

Marc Mutz - mmutz