I have defined a Cloneable interface:
struct Cloneable
{
virtual Cloneable * clone(void) const = 0;
}
I have also some other interface classes (content not relevant to issue):
struct Interface
{
};
struct Useful_Goodies
{
};
I have created a leaf object which开发者_如何学编程 inherits from the above classes:
struct Leaf : public Cloneable, public Interface, public Useful_Goodies
{
Leaf * clone(void) const // Line #1 for discussion.
{
return new Leaf(*this);
}
};
I'm getting the error:
overriding virtual function return type differs and is not covariant from 'Cloneable::clone'
If I change the type to Cloneable *
, I get this error message:
'return' : ambiguous conversions from 'Leaf *' to 'Cloneable *'
My Questions (all related):
- How can the leaf class resolve the
requirements of the
Cloneable
interface? - Is there a better solution to implement a Cloning contract, where all objects are guaranteed to implement cloning?
I'm using this paradigm as part of generic programming (records, fields & database).
Compiler: MS Visual Studio 2008; Platforms: Windows XP & Vista
Having your clone
function return a Cloneable *
is correct.
You will get an ambiguous conversion if one of your interfaces also derives from Cloneable
.
Edit: Alf points out in the comments that not only is it possible for Leaf::clone
to return a Leaf*
, it's actually preferable for it to do so. I stand corrected.
You probably failed to mention that Interface
or some other base class also inherits Cloneable
. The "ambiguous conversion" means Leaf
probably contains multiple Cloneable
base class subobjects. (A problem with covariant return type could be a direct result of the same problem.)
You'll want to solve this problem using virtual inheritance (recommended and linked reading: C++ FAQ Lite topics 25.8 through 25.13). To start with, change all instances of : public Cloneable
to : public virtual Cloneable
.
I can risk and say that you are probably non virtually inheriting from Cloneable
from more than one path. That is, some of your other base besides the direct Cloneable
inherits (directly or indirectly) from Cloneable
. This makes the conversion from Leaf*
to Cloneable*
ambiguous as there are more than one Cloneable
base in your Leaf
.
The simple solution is using virtual inheritance from the interface:
struct Cloneable {
virtual Cloneable * clone() = 0;
};
struct Interface : virtual Cloneable {
};
struct Test : virtual Cloneable, Interface {
virtual Test* clone() {
return new Test(*this);
}
};
Virtual inheritance means that even if both Interface
and Test
inherit from Cloneable
, there is only a single Cloneable
base object.
精彩评论