This is a Python and C++ question.
I am experimenting with multiple inhertiance and I came across this example.
B1 B2
\ /
D
Say I have two (independent?) parent classes B1, B2
and one child class D
. We're only interested in objects of class D
.
class B1:
def f1(self):
print "In f1"
class B2:
def f2(self):
self.f1()
class D (B1, B2):
def fD(self):
self.f2()
d = D()
d.fD()
Output: In f1
What's interesting (at least to me) is that class B2
has no knowledge about class B1
and yet f2
can call self.f1()
with no problems.
I tried to replicate this exact thing in C++ and I couldn't make it work because I don't know how to call f1
from f2
.
class B1 {
public:
virtual ~B1() {}
virtual void f1() { cout << "In f1" << endl; }
};
class B2 {
public:
virtual ~B2() {}
virtual void f2() { /* What goes here?? */ }
};
class D : public B1, public B2 {
public:
void fD() { f2(); }
};
So, I want to know how/why Python can handle this but C++ cannot?
Also, what minimal changes can we make to the C++ code to make it behave like the Python code?
what minimal changes can we make to the C++ code to make it behave like the Python code?
Short answer: You can't. B2
has no idea that it's going to form part of a sub-class that also has B1
as super-class.
Long answer: You can, if you use some grotty downcasting (essentially casting this
to a D*
). But it's probably not a good idea, as *this
is not necessarily a D
.
This works in python because the name f1
in class B2
is being resolved at runtime. This is "duck typing" -- the object reference in self
just has to have a valid f1
to call, which it does when you construct it that way.
The most C++-like way to get similar behavior in C++ is the Curiously recurring template pattern . Your C++ version of B2
needs to know what it is a part of. Making it a template of its derived type gives you a "clean" way to do the dynamic_cast
that others have suggested. It's cleaner because there will be a new class B2<T>
for every class that derives from it. Each specialization will have a distinct f2
which uses the right cast to get to the right f1
. It will work much like the python version in that the existence of a callable f1
is all that is required (at compile time rather than runtime, though).
class B1 {
public:
virtual ~B1() {}
virtual void f1() { cout << "In f1" << endl; }
};
template <typename Derived>
class B2 {
public:
virtual ~B2() {}
virtual void f2() { dynamic_cast<Derived *>(this)->f1(); }
};
class D : public B1, public B2<D> {
public:
void fD() { f2(); }
};
I want to know how/why Python can handle this but C++ cannot?
That's because Python is dynamically typed and C++ is statically typed.
what minimal changes can we make to the C++ code to make it behave like the Python code?
If you want to program in Python you know where to find it. Programming in C++ using Python ways is counter-idiomatic and is generally frowned upon. That said, if you want to do it anyway, you use dynamic_cast<B2*>(this)
.
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.