简体   繁体   中英

Multiple inheritance in python vs c++

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.

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