C ++ Странная проблема наследования Diamond - PullRequest
3 голосов
/ 29 августа 2010

У меня есть

    A
  /   \
 B     C
  \   /
    D

A имеет чисто виртуальную функцию, имеющую прототип:

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'

Безумная идея, как решить эту проблему.

Заранее спасибо.

Ответы [ 3 ]

9 голосов
/ 29 августа 2010

Используйте виртуальное наследование, если вы хотите, чтобы в вашей иерархии была только одна копия родительского элемента.

class B : public virtual A

Edit:
В MSVC ++ 2010 может быть ошибка. Intellisense не обнаруживает проблему, но компилятор ее закрывает. Странно, потому что VC6 достаточно доволен этим.

В качестве обходного пути, если вы объявите D следующим образом, это сделает MSVC ++ 2010 счастливым, работая в компиляторах без этой проблемы:

class D: public virtual A, public B, public C
5 голосов
/ 29 августа 2010

То, что вы описываете в своем оригинальном посте, совершенно законно.Быстрый пример кода, который точно компилируется без каких-либо ошибок, компилятором Comeau Online

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; }
};

Либо вы не делаете то, что, как вы сказали, вы делаете, либо ваш компилятор сломан.Отправьте реальный код, который вы пытаетесь скомпилировать.

PS Я только что попытался скомпилировать это в VS 2010 Express и получил ту же ошибку.Как Gunslinger47 также предлагает в комментариях, это ошибка в компиляторе VS 2010.

1 голос
/ 29 августа 2010

избежать алмазного наследства? ; ->

во всяком случае, вот образец (действительно образец - не разыгрывайте так)

// 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...