【问题标题】:Multiple inheritance in python vs c++python vs c++中的多重继承
【发布时间】:2013-07-21 04:53:14
【问题描述】:

这是一个 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++ 中复制这个确切的东西,但我无法让它工作,因为我不知道如何从 f2 调用 f1

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 代码?

【问题讨论】:

  • 在 Python 中不是很有趣。它只是尝试(动态地)通过 MRO(方法解析顺序)树解析给定的属性(由于所有不同的规则,它比仅仅查找属性要复杂一些,但它是关于如何总结它)。树 MR(方法解析)总是从接收者开始,接收者是使用 self 时的当前对象实例——这也是 Python 允许覆盖和多态的方式——而不是方法的定义类型。要调用特定类型的方法,请参阅TheType.method(self, ..)
  • @user2246674:当类不是“新样式”(即派生自object)时是这样吗?如果这很重要,那么应该编辑答案。
  • 看来我来晚了....这可以使用“类型特征”(C++ 模板编程概念)来完成。想法是 B2 类可以从 TypeTrait 派生或包含模板类作为参数。 D 的构造函数可以传递自己来设置实例变量,然后调用 f1 方法。

标签: c++ python multiple-inheritance virtual-functions


【解决方案1】:

我们可以对 C++ 代码进行哪些最小更改以使其行为类似于 Python 代码?

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

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

【讨论】:

    【解决方案2】:

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

    在 C++ 中获得类似行为的最类似于 C++ 的方法是 Curiously recurring template pattern。您的 C++ 版本的 B2 需要知道它是什么的一部分。使其成为其派生类型的模板为您提供了一种“干净”的方式来执行其他人建议的dynamic_cast。它更干净,因为从它派生的每个类都会有一个新类B2&lt;T&gt;。每个专业化都有一个独特的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(); }
    };
    

    【讨论】:

      【解决方案3】:

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

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

      我们可以对 C++ 代码进行哪些最小更改以使其行为类似于 Python 代码?

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-03-28
        • 2011-03-29
        • 2017-03-31
        • 2020-12-18
        • 2021-08-05
        • 1970-01-01
        相关资源
        最近更新 更多