多重继承和纯虚函数

HC4*_*ica 16 c++ virtual multiple-inheritance diamond-problem

以下代码:

struct interface_base
{
    virtual void foo() = 0;
};

struct interface : public interface_base
{
    virtual void bar() = 0;
};

struct implementation_base : public interface_base
{
    void foo();
};

struct implementation : public implementation_base, public interface
{   
    void bar();
};

int main()
{
    implementation x;
}
Run Code Online (Sandbox Code Playgroud)

无法编译时出现以下错误:

test.cpp: In function 'int main()':
test.cpp:23:20: error: cannot declare variable 'x' to be of abstract type 'implementation'
test.cpp:16:8: note:   because the following virtual functions are pure within 'implementation':
test.cpp:3:18: note:    virtual void interface_base::foo()
Run Code Online (Sandbox Code Playgroud)

我玩过它并想出让'interface - > interface_base'和'implementation_base - > interface_base'继承虚拟,修复问题,但我不明白为什么.有人可以解释一下发生了什么吗?

ps我故意省略了虚拟析构函数以缩短代码.请不要告诉我把它们放进去,我已经知道:)

bdo*_*lan 14

继承树中有两个 interface_base基类.这意味着您必须提供两个实现foo().调用它们中的任何一个都会非常尴尬,需要多个强制转换才能消除歧义.这通常不是你想要的.

要解决此问题,请使用虚拟继承:

struct interface_base
{
    virtual void foo() = 0;
};

struct interface : virtual public interface_base
{
    virtual void bar() = 0;
};

struct implementation_base : virtual public interface_base
{
    void foo();
};

struct implementation : public implementation_base, virtual public interface
{   
    void bar();
};

int main()
{
    implementation x;
}
Run Code Online (Sandbox Code Playgroud)

对于虚拟继承,在继承层次结构中只为所有虚拟提及创建了一个有问题的基类实例.因此,只有一个foo()可以满足implementation_base::foo().

有关更多信息,请参阅此先前的问题 - 答案提供了一些很好的图表,使这一切更加清晰.


cur*_*guy 11

通常的C++成语是:

  • 接口类的公共虚拟继承
  • 实现类的私有非虚拟继承

在这种情况下,我们将:

struct interface_base
{
    virtual void foo() = 0;
};

struct interface : virtual public interface_base
{
    virtual void bar() = 0;
};

struct implementation_base : virtual public interface_base
{
    void foo();
};

struct implementation : private implementation_base,
                        virtual public interface
{   
    void bar();
};
Run Code Online (Sandbox Code Playgroud)

implementation,独特的interface_base虚拟基础是:

  • 公开继承的interface:implementation- interface公共 - > - 公共 - >interface_base
  • 私人继承的implementation_base:implementation- implementation_base私人 - > - 公共 - >interface_base

当客户端代码执行其中一个派生到基本转换时:

  • 派生到基指针转换,
  • 基类型的引用绑定与派生的静态类型的初始化程序,
  • 通过派生静态类型的左值访问继承的基类成员,

重要的只是从派生类到给定的基类子对象至少有一个可访问的继承路径; 其他不可访问的路径被简单地忽略.因为基类的继承只在这里是虚拟的,所以只有一个基类主题,因此这些转换永远不会模糊.

在这里,转换implementationinterface_base,始终可以通过客户端代码来完成interface; 另一条无法进入的道路根本不重要.独特的interface_base虚拟基础是公开继承的implementation.

在许多情况下,实现类(implementation,implementation_base)将保持对客户端代码的隐藏:仅显示指针或对接口类(interface,interface_base)的引用.