Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Diamond-inheritance scenario compiles fine in G++, but produces warnings/errors in VC++/Eclipse

I have a base class 'Base', which is a pure virtual class:

class Base {

public:
    virtual void A() = 0;
    virtual void B() = 0;

    virtual ~Base() { } // Eclipse complains that a class with virtual members must have virtual destructor
};

I also have 2 other classes, one of them implements A() and the other one implements B():

class DerivedA : public virtual Base
{
public:
    virtual void A() {
        printf("Hello from A");
    }
};

class DerivedB : public virtual Base
{
public:
    virtual void B() {
        printf("Hello from B");
    }
};

The virtual keyword in the declaration should solve the diamond problem.

Now I would like to combine the two classes into another class, so that both A() and B() are implemented, like this:

class DerivedC: public DerivedA, public DerivedB {
     // Now DerivedA and DerivedB are combined
};

// Somewhere else in the code
DerivedC c;
c.A();
c.B();

The problem: Even though G++ compiles the code just fine, Eclipse gives an error: The type 'DerivedC' must implement the inherited pure virtual method 'Base::B'. When compiling with visual studio, I get 2 warnings:

warning C4250: 'DerivedC' : inherits 'DerivedB::DerivedB::B' via dominance
warning C4250: 'DerivedC' : inherits 'DerivedA::DerivedA::A' via dominance

So the question is: what is the correct way of doing this? Does the code above produce undefined behavior?

Note: The title may be a little misleading, I have no idea what a good title for this question would be.

like image 780
Tibi Avatar asked Aug 15 '12 07:08

Tibi


2 Answers

What is the correct way of doing this? Does the code above produce undefined behavior?

The code is perfectly valid. There is no Undefined Behavior here.
An unqualified call of A() through a DerivedC class object, will always call DerivedA::A(), while an unqualified call of B() through a DerivedC class object, will always call the DerivedB::B() instance.

Visual C++ gives you a warning because your code uses a less commonly known feature of virtual Inheritance which may not be obvious to most common users and might surprise them. In this case, the warning should be taken as an Informative Nitpick rather than a warning.

Note that the C++ Standard does not restrict compilers from emitting informative warnings for perfectly valid code. The documentation for warning C4250 gives an example which tells you why visual C++ chooses to give this warning.

like image 184
Alok Save Avatar answered Nov 14 '22 12:11

Alok Save


You might want to try this :

class DerivedC: public DerivedA, public DerivedB {
public:
    using DerivedA::A;
    using DerivedB::B;
};

I can't test with Eclipse or VC++ myself...

like image 20
BatchyX Avatar answered Nov 14 '22 11:11

BatchyX