Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple inheritance: 2Classes1Method

Tags:

c++

I've just tried this piece of code:

struct FaceOfPast
{
    virtual void Smile() = 0;
};

struct FaceOfFuture
{
    virtual void Smile() = 0;
};

struct Janus : public FaceOfPast, public FaceOfFuture
{
    virtual void Smile() {printf(":) ");}
};

...

void main()
{
    Janus* j = new Janus();
    FaceOfFuture* future = j;
    FaceOfPast* past = j;

    future->Smile();
    past->Smile();

    delete j;
}

It works as intended (outputs two smiley faces), but I don't think it should even compile, redeclaration of Smile() in Janus being ambiguous.

How (and why) does it work?

like image 281
obamator Avatar asked Apr 24 '12 12:04

obamator


2 Answers

There's no ambiguity because you call Smile() on pointers to FaceOfFuture and FaceOfPast that only declare one method Smile().

Because calling the method on a base class pointer can't result in an ambiguity, let's treat the situations when you call the method directly on the child class pointer:

Janus* j = new Janus();
j->Smile();

The derived class, besides overriding, also hides the base classes' declaration of Smile(). You'd have an ambiguity only if you wouldn't be overriding the method in your derived class:

The following compiles:

struct FaceOfPast
{
    virtual void Smile() {printf(":) ");}
};
struct FaceOfFuture
{
    virtual void Smile() {printf(":) ");}
};
struct Janus : public FaceOfPast, public FaceOfFuture
{
   virtual void Smile() {printf(":) ");}
};
int main()
{
   Janus* j = new Janus();
   j->Smile();
}

Although you call Smile on a Janus, the base class declarations are hidden.

The following doesn't:

struct FaceOfPast
{
    virtual void Smile() {printf(":) ");}
};

struct FaceOfFuture
{
    virtual void Smile() {printf(":) ");}
};

struct Janus : public FaceOfPast, public FaceOfFuture
{
};

int main()
{
   Janus* j = new Janus();
   j->Smile();
}

Because of the ambiguity.

like image 93
Luchian Grigore Avatar answered Oct 15 '22 21:10

Luchian Grigore


According the C++ standard (10.3.2):

If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf [...] overrides Base::vf.

There doesn't seem to be any special treatment for multiple inheritance, so it most probably apply here too: void Janus::Smile() overrides both methods without any ambiguity, just because it has the exact same name and signature as both base class methods.

like image 27
alexisdm Avatar answered Oct 15 '22 20:10

alexisdm