2

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?

3
  • 5
    It's not very interesting in Python. It just tries to (dynamically) resolve the given property through a MRO (Method Resolution Order) tree (it's a bit more complicated than just looking for a property thanks to all the different rules, but it's about how it can be summed up). The tree MR (Method Resolution) always starts from the receiver which is the current object instance when self is used - this is also how Python allows overriding and polymorphism - and not the defining type of the method. To call a method on a particular type, see TheType.method(self, ..) Commented Jul 21, 2013 at 4:58
  • @user2246674: Is that true when the classes are not "new style" (i.e. derived from object)? If that's important then the answer should be edited. Commented Aug 7, 2013 at 17:46
  • Seems like I am quite late here....this can be done using "Type Traits" (C++ template programming concept). Idea is class B2 can either derive from a TypeTrait or contain a Templated Class as a param. The constructor of D can pass itself to set the instance variable and method f1 will be called on that. Commented Mar 30, 2022 at 2:57

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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(); }
};

Comments

0

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).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.