2

这是一个 Python 和 C++ 问题。

我正在尝试多重继承,我遇到了这个例子。

B1 B2
 \ /
  D

假设我有两个(独立的?)父类B1, B2和一个子类D。我们只对 的对象感兴趣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

有趣的是(至少对我而言)是class B2不了解class B1f2可以毫无问题地调用self.f1()

我试图在 C++ 中复制这个确切的东西,但我无法让它工作,因为我不知道如何f1f2.

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

所以,我想知道 Python 如何/为什么可以处理这个问题,但 C++ 不能?

此外,我们可以对 C++ 代码进行哪些最小更改以使其表现得像 Python 代码?

4

3 回答 3

1

我们可以对 C++ 代码进行哪些最小更改以使其表现得像 Python 代码?

简短的回答: 你不能。 B2不知道它将成为子类的一部分,该子类也具有B1超类。

长答案:你可以,如果你使用一些糟糕的向下转换(基本上是转换this为 a D*)。但这可能不是一个好主意,因为*this不一定是D.

于 2013-07-21T04:57:27.253 回答
1

这在 python 中有效,因为f1类中的名称B2是在运行时解析的。这是“鸭子类型”——对象引用self只需要有一个有效f1的调用,当你以这种方式构造它时它就会这样做。

在 C++ 中获得类似行为的最类似于 C++ 的方法是Curiously recurring template pattern。您的 C++ 版本B2需要知道它是什么的一部分。使其成为其派生类型的模板为您提供了一种“干净”的方式来执行dynamic_cast其他人建议的操作。它更干净,因为B2<T>从它派生的每个类都会有一个新类。每个专业都有一个独特的f2,它使用正确的演员来获得正确的f1。它的工作原理与 python 版本非常相似,因为只需要存在一个可调用f1对象(尽管是在编译时而不是运行时)。

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(); }
};
于 2013-07-21T05:53:22.600 回答
0

我想知道 Python 如何/为什么可以处理这个问题,但 C++ 不能?

那是因为 Python 是动态类型的,而 C++ 是静态类型的。

我们可以对 C++ 代码进行哪些最小更改以使其表现得像 Python 代码?

如果你想用 Python 编程,你知道在哪里可以找到它。使用 Python 方式在 C++ 中编程是反惯用的,并且通常不受欢迎。也就是说,如果你想这样做,你可以使用dynamic_cast<B2*>(this).

于 2013-07-21T05:27:35.153 回答