简体   繁体   中英

Multiple inheritance method resolving: C++ vs Python

I'm seeing very different behavior in how C++ and Python handle the diamond inheritance scenario.

For the following two code snippets, the logic is the same but the output is different. I don't understand why. I'd really appreciate it if someone could offer some insight.

Python prints out "BB"

class A(object):
    def foo(self):
        print 'A'

class B(A):
    def foo(self):
        print 'B'
    def bar(self):
        self.foo()

class C(A):
    def foo(self):
        print 'C'
    def bar(self):
        self.foo()

class D(B, C):
    def bar(self):
        B.bar(self)
        C.bar(self)

D().bar()

But C++ prints out "BC"

struct A
{   
    virtual void foo() {
        cout << "A" << endl;
    }   
};  

struct B : public A
{   
    virtual void foo() {
        cout << "B" << endl;
    }   

    virtual void bar() { this->foo(); }
};  

struct C : public A
{   
    virtual void foo() {
        cout << "C" << endl;
    }   

    virtual void bar() { this->foo(); }
};  

struct D : public B, public C
{   
    virtual void bar() {
        B::bar();
        C::bar();
    }   
};  

int main()
{   
    D().bar();
} 

When I add the line cout << typeid(*this).name() << endl; to every bar() method above in C++, this is what gets printed out:

B 0x7fff803d9b70
C 0x7fff803d9b78
D 0x7fff803d9b70

It seems that B and D share the same address, but C is in a different vtable.

Edit

As suggested in the reply @JoranBeasley, I tried the following checks for the python code:

D.foo == B.foo
D.foo == C.foo
D.foo is B.foo
D.foo is C.foo

Python 2.7 prints out True False False False

Python 3.4 prints out True False True False

It seems that both B.foo and D.foo are the same method by value in both python 2 and 3, but python 2 makes a copy while python 3 doesn't.

I can only explain the python bits ...

C.bar(self)

passes the instance of D that you created in as self

so when it calls self.foo() it is no different than if you had said self.foo() inside of D.bar (ie self remains staticly the same thing)

since inheritance is done Right to Left B.foo shadows C.foo

D.foo is B.foo # should print True
D.foo is C.foo # should print false

you could of coarse always call

C.foo(self) #prints C as expected

this really has nothing to do with Python multiple inheritance method resolution order since that is handled with the super() call ... instead you are trying to explicitly call your parent class methods, rather than allowing python to resolve them for you implicitly

as far as why its different than C++ , its because it is two seperate languages that implemented inheritance and multiple inheritance in distinct ways...

as mentioned in the comments you could change D's definition to

class D(C,B):
     ...

then D().foo() will print C

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM