多重(菱形)继承编译而不"virtual",但不使用
Multiple (diamond) inheritance compiles without "virtual", but doesn't with
给出以下代码(没有虚拟继承):
class A
{
public:
virtual void f() = 0;
};
class B : public A
{
public:
virtual void f() {}
};
class C : public A
{
public:
virtual void f() {}
};
class D : public B, public C
{
/* some code */
};
int main()
{
D d;
return 0;
}
代码编译。
另一方面,这里:
class A
{
public:
virtual void f() = 0;
};
class B : virtual public A
{
virtual void f() {}
};
class C : virtual public A
{
virtual void f() {}
};
class D : public B, public C
{
/* some code */
};
int main()
{
D d;
return 0;
}
编译器显示编译错误:
no unique final overrider for 'virtual void A::f()' in 'D' .
为什么第二段代码不同?
您的第一个场景层次结构对应于:
F() F()
A A
| |
F() B C F()
/
D
其中D不是抽象的,因为在D类型的对象中有两个A的子对象:一个是B通过B的晶格使其具体化的,另一个是通过c的晶格使其具体化的
除非你试图在D的对象上调用函数F(),否则不会有任何歧义。
第二个场景层次结构对应于:
F()
A
/
F() B C F()
/
D
在这个场景中,对象D有一个基类a子对象,它必须覆盖并提供该子对象中纯虚函数的实现。
Herb Sutter在《每周大师》(GOTW)上的文章是多继承的好读物:
- 多重继承第一部分
- 多重继承第二部分
- 多重继承第三部分
对于虚拟继承,D
对象只有一个A
子对象的基类。这个单独的子对象不能有一个虚函数的两个不同实现。相比之下,没有虚拟继承的D
对象有两个不同的基类A
子对象,每个子对象都有自己的函数实现(这是可以的,直到您尝试在D
对象上调用它,这时您需要指出您想要哪个)。
干杯,hth .
相关文章:
- 如何重构类层次结构以避免菱形问题
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 我应该如何修改此代码以使用给定字符串中的字母打印菱形图案
- 当我从下面的代码中删除关键字 virtual 时,它可以正常工作,否则会出现错误。在这里"virtual"字的意义是什么?
- 在基类中调用的 VIrtual 基函数,C++
- C++类:virtual和override,或者两者都没有
- 消除 C++ 中的菱形问题以访问顶级成员
- 我是否需要在虚拟继承类的构造函数中初始化基类以解决菱形继承问题?
- g++ [[noreturn]] on a virtual method
- 菱形调用所有父函数
- "virtual"对C++析构函数有何影响?
- 多重继承:跳过'virtual'关键字并拒绝菱形层次结构的使用?
- 错误"pure virtual method called",当此方法已被覆盖时
- 为什么C++尝试/捕获没有捕获"pure virtual call"异常?
- 防止 CRTP 特征码在"pure virtual"调用中堆栈溢出
- Protobuf 生成的C++类无法针对 iOS 进行编译,并显示错误"Only virtual member functions can be marked 'final'"
- 为什么必须将"virtual"放入基类中,而不是仅在子类中使用"override"?在C++
- 使用 -march 编译会导致线程说"pure virtual method called"
- 菱形层次结构中的虚函数重载在 clang 和 gcc 中产生不同的结果
- 多重(菱形)继承编译而不"virtual",但不使用