C++中多接口继承的歧义

use*_*349 7 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;
}
Run Code Online (Sandbox Code Playgroud)

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

我的问题是,为什么编译器会给我这样的错误信息?为什么C++语法是这样定义的; 即,将此案件视为错误?如何让代码运行?我想允许接口的多重继承.当然,如果我使用"虚拟公共"或重新声明函数funcBase()Implementation

interface DDerived : public Derived1, public Derived2
{
    virtual void funcBase() = 0;
    virtual void funcDDerived() = 0;
};
Run Code Online (Sandbox Code Playgroud)

然后一切都运行没有问题.

但我不想这样做并寻找更方便的方法,因为虚拟继承可能会降低性能,如果类的继承关系非常复杂,则重新声明是如此繁琐.除了使用虚拟继承之外,是否有任何方法可以在C++中启用接口的多重继承?

Jer*_*fin 7

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

在此输入图像描述

这里重要的一点是每个实例都Implementation包含两个完全独立的实例Base.你提供的覆盖Base::funcBase,但它不知道你是否尝试覆盖funcBaseBase你继承了通过Derived1,或者Base你继承了通过Derived2.

是的,处理这个问题的干净方法是虚拟继承.这将改变你的结构,所以只有一个Base实例:

在此输入图像描述

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

另一种可能性是某种基于模板的替代方案,但这往往遍及代码的其余部分 - 也就是说Base *,您编写的模板可以与提供函数A,B和C的任何东西一起使用,而不是传递a ,然后传递(相当于)Implementation作为模板参数.


Mar*_*k B 3

C++ 语言的设计方式是,在第一种没有虚拟继承的方法中,该方法将有两个父副本,并且无法确定要调用哪一个。

虚拟继承是从多个基继承相同函数的 C++ 解决方案,因此我建议仅使用该方法。

或者,您是否考虑过不从多个基础继承相同的功能?您是否真的有一个派生类,您需要能够根据上下文将其视为Derived1or Derived2OR ?Base

在这种情况下,详细说明具体问题而不是人为的示例可能有助于提供更好的设计。