虚拟继承使用

时间:2013-12-02 12:04:48

标签: c++ oop inheritance multiple-inheritance

我需要编写一个新手和经验丰富的C ++开发人员都会使用的编码约定。动态多态的继承规则如下:

  
      
  • 对于动态多态,请考虑使用单继承(树状层次结构),可能具有抽象接口的多重继承
  •   
  • 用于继承层次结构(基类等),默认,使用公共继承
  •   
  • 用于继承抽象接口,默认,使用公共虚拟继承
  •   

此规则之后将提供有关实施,可能的例外情况等的详细信息。

所以,问题是:这个规则是否适合新手和有经验的C ++开发人员?(优点/缺点,以及欢迎来源和链接)


我看到的是:

优点:

    新手可以轻松使用
  • 规则,而不会限制经验丰富的开发人员。
  • 熟悉Java / .NET界面的人
  • 避免与实现的虚拟继承相关的问题(因为它是为抽象接口保留的),以及非虚拟继承(在转换为接口类时可能存在歧义)

缺点:

  • 轻微的性能成本(转换到接口时的速度,虚拟表的大小,类实例中的其他指针)

注意:我已阅读以下在线消息来源:

注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 *
}

是的,显式转换以消除歧义是错误的解决方案(无论如何,显式转换通常是错误的解决方案)。

3 个答案:

答案 0 :(得分:2)

你知道吗?您已经在问题中提供了所有重要信息。我在技术层面上没有看到任何答案。显然,没有人看到你发布的任何重大技术问题。

我会回答你粗体问题:,它适合新手和职业选手。

  • Newbs有一些有用的技术指南。
  • Pros 可以做他们想要的事情如果他们可以给出理由,因为你用“考虑”和“默认”来限定你的规则,所以基本上没有其他人可以说你必须这样做或者因为样式规则,因为你的规则的措辞已经允许例外。

答案 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

  

对于动态多态,请考虑使用单继承(树状层次结构),可能具有抽象接口的多重继承

你的规则很好。

那么,你的问题是什么?现在还剩下什么?