我想有一个接口IA和另一个扩展它IB。
然后A实现IA,B继承A,也实现IB。
但是,当编译B时出现错误,说明IA内容是未定义的,即使A定义了所有内容:(
class IA
{
public:
virtual ~IA(){}
virtual void foo()=0;
};
class IB : public IA
{
public:
virtual void bar()=0;
};
class A : public IA
{
public:
A();
void foo();
};
class B : public A, public IB
{
public:
B();
void bar();
};错误C2259:'B‘:无法实例化抽象类
由于下列成员:
'void::foo(Void)‘:是抽象的
发布于 2011-04-07 13:28:06
看一看C++常见问题,从以下几点开始:https://isocpp.org/wiki/faq/multiple-inheritance#mi-diamond
它详细解释了“可怕的钻石”和虚拟继承。
发布于 2011-04-07 13:27:35
(不,A没有定义任何东西。声明了A()和void foo(),但没有定义它们。)
真正的问题是你的多重继承。
B
/ \
A IB
/ \
IA IA如您所见,继承树中有两个IA“版本”,只有A实现了void IA::foo (不过,正如我前面提到的,这将给您一个链接器错误,因为您没有定义实现)。
void IB::IA::foo()仍未实现;因此,B本身“继承了抽象性”,您无法实例化它。
B也必须实现void foo(),或者您可以使用虚拟继承来攻击它。
发布于 2011-04-07 13:39:18
这是,对于虚拟继承而言,这是一个完全正确的案例,而这并不总是一种设计味道。
在并行层次结构接口/实现的情况下,表单“任意类->接口”的每个继承关系都应该标记为虚拟的:class A : public virtual IA;class B : public virtual IB, public A和class IB : public virtual IA。
这样,很可能(实现依赖但至少在概念上),在每个虚拟派生类中存储一个额外的指针,以知道它应该在哪里找到它的虚拟基。类A、B和IB将有指向IA的指针,而类B将有指向IB的指针。每个虚拟库也将有自己的vtable。
“可怕的钻石”的观点在图形上很好,但重点是派生类应该知道它们将使用的基类驻留在哪里,这就是虚拟继承的开始位置。显然,这里每个接口都需要一个vtable,而虚拟继承允许您这样做。
然后您可以继续并行,并添加额外的类C、IC等等,只需记住:
--无论何时继承接口,实际上都要继承。
顺便说一下,COM类也有类似的设计。
https://stackoverflow.com/questions/5581806
复制相似问题