我们可以在层次结构中创建多个纯虚拟接口及其实现而不会代码爆炸吗?

can we create multiple pure virtual interfaces in hierarchy and their implementation without code explosion

本文关键字:实现 代码 接口 层次结构 创建 虚拟 我们      更新时间:2023-10-16

在纯虚拟类的实现(下面的B_Impl(中,我们需要定义对应于所有派生的纯虚拟类(A和B(的所有方法,即使我们也是从实现类(A_Impl(派生的。 我有以下纯虚拟类:

class A
{
public:
virtual bool M1() = 0;
virtual ~A() = default;
};
class A_Impl: public virtual A
{
public:
bool M1() override { return true;}
virtual ~A_Impl() = default;
};
class B : public virtual A
{
public:
virtual ~B()=default;
virtual bool M2() = 0;
};
class B_Impl : public B, public A_Impl
{
public:
virtual ~B_Impl() = default;
bool M2() override { return true; }
};
int main()
{
B_Impl bimpl();
return 0;
}

在编译时,我收到以下错误:

1.cpp: 在函数 'int main((' 中: 1.cpp:31:5:错误:无效的抽象返回类型"B_Impl" B_Impl bimpl((; ^~~~~~ 1.cpp:22:7:注意:因为以下虚函数在"B_Impl"中是纯的: B_Impl类:公共B类,公共A_Impl ^~~~~~ 1.cpp:4:14:注意:虚拟布尔值 A::M1(( 虚拟布尔值 M1(( = 0;

当我也从A_Impl 派生时,我也不想在 B_Impl 中定义 A 的所有方法。

您的代码缺少多个问题。

首先A_Impl不是从A派生出来的,这意味着它不能覆盖M1

我认为你的方法不是很详细,你应该考虑重新思考你的架构。

您的问题是B_Impl对象有两个A子对象,其中一个子对象没有覆盖其M1方法。

B_Impl对象如下所示:

+-------------------------+
| +---------+ +---------+ |
| | +-----+ | | +-----+ | |
| | |     | | | |     | | |
| | |  A  | | | |  A  | | |
| | |     | | | |     | | |
| | +-----+ | | +-----+ | |
| |  A_Impl | |  B      | |
| +---------+ +---------+ |
|         B_Impl          |
+-------------------------+

它有A_ImplB子对象,每个子对象都有自己的A子对象。

要解决此问题,您需要使用虚拟继承。 如果您声明A_ImplB实际上继承自A,那么B_Impl最终将如下所示:

+--------------------------+
| +-----+ +------+ +-----+ |
| |     | |      | |     | |
| |  A  | |A_Impl| |  B  | |
| |     | |      | |     | |
| +-----+ +------+ +-----+ |
|          B_Impl          |
+--------------------------+

它有一个由BA_Impl共享的Asubojbect。

为此,只需添加virtual关键字:

class A                               
{                                        
public:
virtual bool M1() = 0;
virtual ~A() = default;
};
class A_Impl : public virtual A
{
public:
bool M1() override { return true;}
virtual ~A_Impl() = default;
};
class B : public virtual A
{
public:
virtual bool M2() = 0;
virtual ~B()=default;
};
class B_Impl : public virtual B, public A_Impl
{
public:
virtual ~B_Impl() = default;
bool M2() override { return true; }
};

请注意,我还声明B_Impl实际上从B派生。 通常,最好从接口虚拟继承。 这样,如果您混合使用源自BC接口和源自CB_ImplC_Impl,您就不会遇到同样的问题。

请记住,初始化任何虚拟派生的类是派生最多的类,所以如果你要使A非默认可构造的,那么最终B_Impl将负责调用A的构造函数,而不是A_Impl隐藏该责任。