Проблема наследования C++ Weird Diamond

у меня есть это

    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'

Ни хрена не придумал, как решить эту проблему.

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


person snoofkin    schedule 28.08.2010    source источник
comment
Я получаю следующие 6 строк ошибок: Вы пропустили остальные 5.   -  person R. Martinho Fernandes    schedule 29.08.2010
comment
Я имел в виду, что я получаю ту же самую ошибку еще 5 раз...   -  person snoofkin    schedule 29.08.2010
comment
О, я и забыл, какими странными могут быть ошибки компилятора C++...   -  person R. Martinho Fernandes    schedule 29.08.2010
comment
Вы заметили обходной путь, который я упомянул в своем ответе?   -  person Gunslinger47    schedule 30.08.2010


Ответы (3)


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

в любом случае, вот сэмпл (на самом деле семпл - не бросайте так)

// 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;
}
person nilphilus    schedule 28.08.2010
comment
Имена функций в определении класса D совершенно незаконны. Что это должно означать: B::clone, C::clone в D? - person AnT; 29.08.2010
comment
@AndreyT Я скомпилировал его, и он работает - результат - BC - это некрасиво, но наследование бриллиантов некрасиво. - person nilphilus; 29.08.2010
comment
Ну, я не знаю, какой компилятор вы используете, но приведенный выше код не C++. В C++ вы не можете использовать полные имена (например, B::clone) при объявлении функции в классе. - person AnT; 29.08.2010
comment
@Andrey: MSVC++2010 это позволяет. ошибки g++, в которых говорится, что невозможно определить функцию-член B::clone в пределах D - person Gunslinger47; 29.08.2010
comment
@AndreyT: точно - и вопросы имеют тег "визуальный-2010", так что для меня это правильно - некрасиво, но правильный ваш ответ намного красивее - person nilphilus; 29.08.2010

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

class B : public virtual A

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

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

class D: public virtual A, public B, public C
person Gunslinger47    schedule 28.08.2010
comment
IntelliSense не видит проблем с кодом, поскольку Visual C++ 2010 IntelliSense использует интерфейс EDG, а не интерфейс Visual C++. Я сократил пример @AndreyT до минимума, необходимого для воспроизведения проблемы, и сообщил об ошибке: connect.microsoft.com/VisualStudio/feedback/details/590625/. - person James McNellis; 29.08.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; }
};

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

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

person AnT    schedule 28.08.2010
comment
Похоже на проблему с MSVC++2010. - person Gunslinger47; 29.08.2010