views:

123

answers:

3

I have this

    A
  /   \
 B     C
  \   /
    D

A has a pure virtual function, prototyped as:

virtual A* clone(void) const = 0;

B and C virtually inherit from A ( class B: public virtual A, class C: public virtual A)

B has the virtual function, prototyped as:

virtual B* clone(void) const {}; 

C has the virtual function, prototyped as:

virtual C* clone(void) const {};

D inherits from both B & C like that: class D: public B, public C D has the virtual function, prototyped as:

virtual D* clone(void) const {};

Now, when compiling I get the following 6 lines of errors:

error C2250: 'D' : ambiguous inheritance of 'B *A::clone(void) const'

No freaking idea how to solve this issue.

Thanks in advance.

+5  A: 

Use virtual inheritance if you want only one copy of a parent in your hierarchy.

class B : public virtual A

Edit:
There may be a bug in MSVC++ 2010. The Intellisense doesn't detect a problem, but the compiler chokes on it. Strange since VC6 is happy enough with it.

As a workaround, if you declare D as follows, it makes MSVC++ 2010 happy while also working in compilers without this issue:

class D: public virtual A, public B, public C
Gunslinger47
I don't now that ^.^
nilphilus
But that's exactly what the OP is already doing.
AndreyT
IntelliSense sees no problem with the code because The Visual C++ 2010 IntelliSense uses the EDG frontend, not the Visual C++ frontend. I stripped down @AndreyT's example to the minim required to reproduce the problem and reported a bug: https://connect.microsoft.com/VisualStudio/feedback/details/590625/visual-c-incorrectly-reports-ambiguity-when-covariance-is-used-with-virtual-inheritance.
James McNellis
A: 

avoid diamond inheritance? ;->

anyway, here is sample (really sample - don't cast like that)

// ConsoleCppTest.cpp : Defines the entry point for the console application. //

#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;
}
nilphilus
Function names in class `D` definition are flat out illegal. What is that supposed to mean: `B::clone`, `C::clone` in `D`?
AndreyT
@AndreyT I compiled it, ant it works - output is BC - that isn't pretty but diamond inheritance isn't pretty.
nilphilus
@nilphilus: Well, I don't know what kind of compiler you are using, but the above code is not C++. In C++ you can't use qualified names (like `B::clone`) when declaring a function in a class.
AndreyT
@Andrey: MSVC++2010 allows this. g++ errors, saying "cannot define member function `B::clone` within `D`"
Gunslinger47
@AndreyT: exactly - and questions has tag 'visual-2010' so for me is correct - ugly but correct your anserw is much prettier
nilphilus
+4  A: 

What you describe in your original post is perfectly legal. A quick sample code that does exactly that compiles without any errors by Comeau Online compiler

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

Either you are not doing what you said you are doing, or your compiler is broken. Post real code you are trying to compile.

P.S. I just tried compiling this in VS 2010 Express and got the same error. As Gunslinger47 also suggests in the comments, this is a bug in VS 2010 compiler.

AndreyT
Looks like an issue with MSVC++2010.
Gunslinger47