Question

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):

  1. How can the leaf class resolve the requirements of the Cloneable interface?
  2. 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

Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top