C++奇怪的菱形继承问题

3

我有这个

    A
  /   \
 B     C
  \   /
    D

一个类有一个纯虚函数,原型为:

virtual A* clone(void) const = 0;

B和C均虚拟继承自A (class B: public virtual A, class C: public virtual A)

B有一个虚函数,原型为:

virtual B* clone(void) const {}; 

C语言中有虚函数,其原型如下:

virtual C* clone(void) const {};

D继承自B和C,代码如下:class D: public B, public C D有一个虚函数,原型如下:

virtual D* clone(void) const {};

现在,编译时我得到了以下6行错误信息:
error C2250: 'D' : ambiguous inheritance of 'B *A::clone(void) const'

我完全不知道如何解决这个问题。

提前感谢。


我得到了以下6行错误信息:你错过了另外5行。 - R. Martinho Fernandes
我的意思是,我又遇到了完全相同的错误5次... - snoofkin
哦,我忘记了C++编译器错误有多奇怪... - R. Martinho Fernandes
你有注意到我在答案中提到的解决方法吗? - Gunslinger47
3个回答

9

如果您想在继承层次结构中只有一个父类的副本,请使用虚拟继承。

class B : public virtual A
编辑:
MSVC++ 2010可能存在一个错误。Intellisense检测不到问题,但编译器却无法处理它。奇怪的是VC6可以处理它。
作为一种解决方法,如果您按以下方式声明D,则它将使MSVC++ 2010适应并在没有此问题的编译器中正常工作:
class D: public virtual A, public B, public C

1
IntelliSense看不到代码的问题,因为Visual C++ 2010 IntelliSense使用EDG前端而不是Visual C++前端。我简化了@AndreyT的示例以最小化需要重现问题,并报告了一个错误:https://connect.microsoft.com/VisualStudio/feedback/details/590625/visual-c-incorrectly-reports-ambiguity-when-covariance-is-used-with-virtual-inheritance。 - James McNellis

5

您在原帖中描述的内容是完全合法的。一个快速的示例代码可以精确地编译,而不需要任何错误通过Comeau在线编译器。

class A {
public: virtual A* clone() const = 0;
};

class B: public virtual A {
public: virtual B* clone() const { return 0; }
};

class C: public virtual A {
public: virtual C* clone() const { return 0; }
};

class D: public B, public C
{
public: virtual D* clone() const { return 0; }
};

要么你没有做你说你在做的事情,要么你的编译器出了问题。请发布你正在尝试编译的真实代码。

P.S. 我刚刚在VS 2010 Express中尝试编译了这个代码,得到了相同的错误。正如Gunslinger47在评论中建议的那样,这是VS 2010编译器中的一个bug。


似乎是MSVC++2010的问题。 - Gunslinger47

1

避免菱形继承?;->

无论如何,这是一个示例(真正的示例 - 不要像那样投掷)

// ConsoleCppTest.cpp:定义了控制台应用程序的入口点。 //

#include "stdafx.h"
#include "iostream"

class A {
public:
    virtual void* clone() = 0;
};

class B: public A {
public:
    virtual void* clone() = 0;
};

class C: public A {
    public:
    virtual void* clone() = 0;
};

class D: public B, public C
{
public:


    virtual void* B::clone() 
    {
        std::cout << "B";
        return (void*)this;
    }

    virtual void* C::clone()
    {
        std::cout << "C";
        return (void*)this;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{

    D* d = new D();

    void* b = ((B*)d)->clone();

    void* c = ((C*)d)->clone();

    return 0;
}

D定义中的函数名是非法的。这意味着什么:在D中的B::cloneC::clone - AnT stands with Russia
@AndreyT 我编译了它,它可以运行 - 输出是BC - 这不太美观,但钻石继承也不太美观。 - nilphilus
嗯,我不知道你在使用什么类型的编译器,但是上面的代码不是C++。在C++中,当在类中声明函数时,不能使用限定名称(例如B::clone)。 - AnT stands with Russia
1
@Andrey:MSVC++2010 允许这样做。g++ 报错,提示“无法在 D 内定义成员函数 B::clone”。 - Gunslinger47
@AndreyT:没错 - 而且问题的标签是“visual-2010”,所以对我来说是正确的 - 丑陋但正确,你的答案更漂亮。 - nilphilus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接