3

Possible Duplicate:
gcc c++ virtual inheritance problem

Hi all,

I'm wondering about how the compiler would handle different initialization values when using multiple inheritance from a virtual base class. Consider the notorious 'diamond of dread' inheritance scheme:

     Base
     / \
    /   \
  D1     D2
    \   /
     \ /
     Join

In order to avoid having two copies of Base in Join, I use virtual inheritance for D1 and D2 (see e.g. here). Now, lets say Base is not abstract, but has a member field, which is initialized in its constructor:

class Base { 
public:
    Base(int x_) {x = x_;};
    virtual ~Base(){};

public:
    int x;
};

class D1 : public virtual Base {
public:
    D1() : Base(1) {};
    virtual ~D1(){};
};

class D2 : public virtual Base {
public:
    D2() : Base(2) {};
    virtual ~D2(){};
};

class Join : public D1, public D2 {
public:
    Join(){};
    ~Join(){};
};

int main()
{
   Join j;
   cout << j.x << endl;

   return 0;
}

Will the output be 1, 2, or is it compiler-dependent?

Community
  • 1
  • 1
bavaza
  • 10,319
  • 10
  • 64
  • 103
  • 1
    No need for new, the test case code is just as valid with `Join j; cout << j.x;`. – Fred Nurk Jan 31 '11 at 09:40
  • @Charles, this question isn't GCC-specific so it isn't strictly a duplicate. Although it does address the same issue and the answer is compiler-independent. – Sergei Tachenov Jan 31 '11 at 10:56
  • @SergeyTachenov: Neither is that question gcc specific, it just happens to have gcc in the title which is a little bit misleading. – CB Bailey Jan 31 '11 at 11:10

3 Answers3

6

It shoudn't compile. Virtual bases are initialized by the most derived class which is Join. Join doesn't explicitly initialize Base but Base has no accessible default constructor.

[It also won't compiler because definitions of classes need to be terminated with a ; but I've assumed that this is a typo. main should also return int and I've assumed that j.x is a typo for j->x.]

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
2

When you have virtual inheritance it is the final class that must initialise the virtual base class.

Therefore the constructor of Join must construct Base:

   class Join : public D1, public D2 
    {
    public:
        Join() : Base(3){} // or whatever value
        ~Join(){}
    };

It is the exception to the rule that classes only normally initialise their immediate base-classes.

(Aside from that main should return int and you would need to do j->x not j.x as j is a pointer, as well as the fact you must delete it as you called new)

CashCow
  • 30,981
  • 5
  • 61
  • 92
1

Since the Base does not have an implicit constructor and both C1 and C2 are virtual bases, you would have to change it like this (and also add semicolons after the rest of the class declarations as pointed out by Charles Bailey)

class Join : public D1, public D2 {
public:
    Join() : Base(3) {};
    ~Join(){};
};

int main()
{
   Join j;
   cout << j.x << endl;
}

Then it would print 3 to the standard output

Palmik
  • 2,675
  • 16
  • 13