我需要编写一个新手和经验丰富的C ++开发人员都会使用的编码约定。动态多态的继承规则如下:
- 对于动态多态,请考虑使用单继承(树状层次结构),可能具有抽象接口的多重继承
- 用于继承层次结构(基类等),默认,使用公共继承
- 用于继承抽象接口,默认,使用公共虚拟继承
此规则之后将提供有关实施,可能的例外情况等的详细信息。
所以,问题是:这个规则是否适合新手和有经验的C ++开发人员?(优点/缺点,以及欢迎来源和链接)
我看到的是:
注意:我已阅读以下在线消息来源:
注2:“抽象界面”这个名称的使用是在Sutter& Sons出售之后创造出来的。 Alexandrescu在“C ++编码标准”第36项中的使用
这是一个应该工作的案例(它的Java / C#等价使用接口只是工作),但如果接口继承不是虚拟的,那么在C ++中则不行:
class A
{
public :
virtual ~A() = 0 {}
} ;
class B : public A {} ; // should have been virtual to avoid the error
class C : public A {} ; // should have been virtual to avoid the error
class D : public B, public C
{
public :
virtual ~D() {}
} ;
void foo(A * c) {}
void bar(D * d)
{
foo(d) ; // Error: ambiguous conversions from 'D *' to 'A *
}
是的,显式转换以消除歧义是错误的解决方案(无论如何,显式转换通常是错误的解决方案)。
答案 0 :(得分:2)
我会回答你粗体问题:是,它适合新手和职业选手。
答案 1 :(得分:1)
由于c ++中的经典多重继承问题diamond of death,如果它不是虚拟的,那么继承示例不起作用。基本上,如果您没有指定虚拟继承,则每个父类(B,C)都有自己的基础A对象。这使得对非静态基类函数和变量(转换以及im假设)的所有访问都是模糊的。我无法想象你可以在c ++中避免这种情况。
编辑:对于记录,这是工作代码:
class A
{
public :
virtual ~A() {}
};
class B : virtual public A {};
class C : virtual public A {};
class D : virtual public B, virtual public C
{
public :
virtual ~D() {}
};
void foo(A * c) {}
void bar(D * d)
{
foo(d);
}
int main(void)
{
D d;
foo(&d);
return 0;
}
答案 2 :(得分:1)
您的第一条规则完全取消class D
:
对于动态多态,请考虑使用单继承(树状层次结构),可能具有抽象接口的多重继承
你的规则很好。
那么,你的问题是什么?现在还剩下什么?