2013-03-20 60 views
1

我有以下代码:“可怕的钻石”与多态性

class Base 
{ 
    public: 
     virtual void doSomething() = 0; 
}; 

class BaseImpl : public virtual Base 
{ 
    public: 
     virtual void doSomething() { 
     // something 
     } 
}; 

class BaseDerived: public virtual Base 
{ 
    public: 
     virtual void doSomething2() = 0; 
}; 

class BaseDerivedImpl: public BaseImpl, public BaseDerived 
{ 
    public: 
     virtual void doSomething2(){ 
     // sonething2 
     } 
}; 

然后,我有

Base* b = new BaseImpl(); 
b->doSomething();   // fatal error at this line (not in the method, but in the method invocation) 

的问题是,它甚至没有进入该功能。

使用此类层次结构时出现错误吗?

+2

您的代码编译[here](http://liveworkspace.org/code/yJL1f$29)。你使用什么编译器? – 2013-03-20 13:34:12

+0

是的,它被编译。 GCC(4.7.2)。我有运行时错误 – user14416 2013-03-20 13:36:13

+1

你甚至没有使用BaseDerived或BaseDerivedImpl - 如果你的声明是Base * b = new BaseDerivedImpl;代替?无论如何也是如此。 – 2013-03-20 13:37:20

回答

2

由于OP忽略的评论,让我在这里回答这个问题:

是不是有毛病使用这种层次结构?

不,没有错。这是如何解决'可怕钻石'问题的标准方式(实际上并不是那么可怕)。

然而,钻石甚至不进来在这个例子中发挥:

Base* b = new BaseImpl(); 

BaseImpl直接从Base衍生让你拥有标准的单一继承。您的代码行为相同,如果根本没有定义BaseDerivedBaseDerivedImpl。你可以评论他们,应用程序仍然会崩溃。

然后您在此实例上调用doSomething并崩溃。的doSomething实现如下:

// something 

因此,我的结论是,// something结果与碰撞,但不可能说没有看到该方法的实现。

+0

请注意,“可怕的钻石”只有那些没有花一两分钟时间看看它是如何工作的人可怕的。这并不难... – 2013-03-20 13:54:23

+0

虽然我不会责怪OP。文学充满了对“可怕钻石”的盲目反复尖叫,很多人甚至不想知道细节。当然,你可以用它拍打你的脚,但它不是黑魔法 – 2013-03-20 13:56:30