Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inheritance by dominance - is it really bad?

I'm one of those people that has to get their code to compile with 0 warnings. Normally I respect the compiler and if it issues me a warning I take it as a sign that I should touch up my code a little. If I have to tell a compiler to ignore a given warning, I twitch a little.

But this one I can't seem to get around, and from what I can tell I haven't done anything "bad". Does anyone think that this is a poor design? I can't see anything particularly nasty about it (except for the "evil diamond") but it's perfectly valid and useful code. But it generates (in MSVC) a level 2 warning!

class IFoo
{
public:
    virtual void foo() = 0;
};

class Bar : public virtual IFoo
{
public:
    virtual void foo() { std::cout << "Hello, world!"; }
};

class Baz : public virtual IFoo
{

};

class Quux : public Bar, public Baz
{

};

Now if I create a Quux object it should be expected to call the Bar::foo implementation. MSVC is very helpful: it warns me for not being ambiguous enough?

warning C4250: 'Quux' : inherits 'Bar::Bar::foo' via dominance

Now I recognize I can turn this warning off with a pragma, but that's not the question I'm trying to ask here. Is there a reason I should be listening to the compiler here, or is this just an extremely overzealous warning?

like image 767
Shirik Avatar asked Aug 15 '11 22:08

Shirik


3 Answers

When performing virtual inheritance, it is a bad idea to not explicitly override every member in the most derived class. Else, you are asking for your code to die a horrible death when someone changes one of your base classes that inherits from the virtual base. There's nothing actively wrong with this, your program won't crash or anysuch, but it's a maintainability bad idea. If you want to call the Bar::foo version, then you should just delegate to it in Quux::foo.

like image 136
Puppy Avatar answered Sep 27 '22 23:09

Puppy


As far as the runability of your code is concerned, it is just there to remind you that Bar is the dominant implementation of foo. It is just there to inform you, it's not really a warning, so that if you're debugging and think it's Baz you don't pull your hair out :).

like image 34
djhaskin987 Avatar answered Sep 27 '22 22:09

djhaskin987


Is there a reason you aren't writing:

class Quux : public Bar, public Baz
{
    using Bar::foo;
};

?

This gives you the same level of reuse, without the fragility.

like image 39
Ben Voigt Avatar answered Sep 27 '22 22:09

Ben Voigt