c++ - C++接口(interface)多重继承中的歧义

标签 c++ inheritance interface multiple-inheritance virtual-inheritance

我做了一个测试代码如下:

#include <iostream>
using namespace std;

#ifndef interface
#define interface struct
#endif

interface Base
{
    virtual void funcBase() = 0;
};

interface Derived1 : public Base
{
    virtual void funcDerived1() = 0;
};

interface Derived2 : public Base
{
    virtual void funcDerived2() = 0;
};

interface DDerived : public Derived1, public Derived2
{
    virtual void funcDDerived() = 0;
};

class Implementation : public DDerived
{
public:
    void funcBase() { cout << "base" << endl; }
    void funcDerived1() { cout << "derived1" << endl; }
    void funcDerived2() { cout << "derived2" << endl; }
    void funcDDerived() { cout << "dderived" << endl; }
};

int main()
{
    DDerived *pObject = new Implementation;
    pObject->funcBase();

    return 0;
}

我写这段代码的原因是为了测试函数 funcBase() 是否可以在 DDerived 的实例中调用。当我尝试编译此代码时,我的 C++ 编译器 (Visual Studio 2010) 给了我一条编译错误消息。在我看来,这段代码没有问题,因为可以确定函数 funcBase() 将在接口(interface) DDerived 的某个派生类中实现(因此被覆盖) ,因为它是纯虚拟的。换句话说,Implementation * 类型的任何指针变量都应与派生 Implementation 并覆盖函数 funcBase() 的类的实例相关联。

我的问题是,为什么编译器给我这样的错误信息?为什么 C++ 语法是这样定义的;即,将这种情况视为错误?我怎样才能让代码运行?我想允许接口(interface)的多重继承。当然,如果我使用“虚拟公共(public)”或在 Implementation 中重新声明函数 funcBase() 就像

interface DDerived : public Derived1, public Derived2
{
    virtual void funcBase() = 0;
    virtual void funcDDerived() = 0;
};

然后一切正常运行。

但我不想那样做,正在寻找更方便的方法,因为虚拟继承可能会降低性能,如果类的继承关系非常复杂,重新声明又很繁琐。除了使用虚拟继承之外,还有什么方法可以在 C++ 中实现接口(interface)的多重继承吗?

最佳答案

正如您定义的那样,您的对象结构如下所示:

enter image description here

这里的重点是Implementation 的每个实例都包含两个完全独立的Base 实例。您正在提供 Base::funcBase 的覆盖,但它不知道您是否正在尝试覆盖 BasefuncBase您通过 Derived1 继承,或者您通过 Derived2 继承的 Base

是的,处理这个问题的干净方法是虚拟继承。这将更改您的结构,因此只有一个 Base 实例:

enter image description here

这几乎无疑是您真正想要的。是的,在原始编译器和 25 MHz 486 等时代,它因性能问题而闻名。使用现代编译器和处理器,您不太可能遇到问题。

另一种可能性是某种基于模板的替代方案,但这往往会渗透到您的代码的其余部分——即,您编写一个可以工作的模板,而不是传递 Base *使用任何提供函数 A、B 和 C 的东西,然后将(相当于)Implementation 作为模板参数传递。

关于c++ - C++接口(interface)多重继承中的歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10353053/

相关文章:

c++ - 使用具有特定搜索条件的 FindFirstFIleEx() 的示例

c++ - 为什么我们不能将浮点值与某些数值进行比较

c++ - 了解运算符查找;哪个编译器是正确的?

java - 如何正确使用class类型的参数?

java - 无法从实现接口(interface)的类中实现方法?

java - 接口(interface)是抽象的,不能实例化

c++ - 来自 C++ 的 QML 回调,自定义类型作为参数

c# - C#:测试是否在父类(super class)的实例中而不是子类中的一个类

c++ - 用 CRTP 替换非纯虚函数

Java - 确保一个对象实现了一个接口(interface)