Reputation: 1557
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 "B B"
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 "B C"
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.
Upvotes: 3
Views: 353
Reputation: 114038
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
(i.e 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
Upvotes: 4