1

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

4
  • I used the same compiler, everything compiles fine. This was a bug, resolved VC6 onwards . Commented Oct 15, 2010 at 16:15
  • There's something you're not telling us, because this code compiles fine for me in VS 2008. Commented Oct 15, 2010 at 16:30
  • The real question if why do you need to clone an object. I see a lot f this from Java converts (where it is a big problem/concept) but I have yet to see the need in c++ code. An explanation of what you are actually trying to achieve may give you some good advice on c++ techniques, Commented Oct 15, 2010 at 16:30
  • @Martin York: I find that this is especially common when creating dynamic language tools such as interpreters, to fill the need for a copy constructor that can be invoked dynamically. I haven't found any other valid use for it yet, but that doesn't mean one doesn't exist. I prefer to give people the benefit of the doubt, tempting though it may always be to intervene. Commented Oct 15, 2010 at 17:53

3 Answers 3

2

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.

Sign up to request clarification or add additional context in comments.

5 Comments

I found one of the interfaces was also inheriting from Cloneable as virtual. The "main" inheritance line was inheriting from Cloneable but not virtual.
yes, but returning Leaf* is also correct, and far more practical. Returning Cloneable* is a Java-ism. In C++ one should use the most specific types available, for static type checking. The OPs problem was/is apparently in the information he didn't provide. Namely use of an archaic pre-standard compiler (or possibly something else). Cheers & hth.,
@Alf, I must disagree. The function is defined as returning a Cloneable* in the base class, so that is what it must return. Of course you will want to create a Leaf* to return, but it must be cast to the proper type before returning, especially when multiple inheritance is involved. If the caller already knows which kind of class is being returned, it could use a copy constructor and avoid the clone method altogether for superior type checking.
No, that's incorrect. This is sort of novice level so I'm sending you to the FAQ instead of quoting the standard. See the explanation of C++ "covariant" function results in FAQ item "20.8 What is a "virtual constructor"?"". Uhm, while I'm throwing links about I might as well reference my own blog entry on how to implement cloning in a reusable way. :-) Cheers & hth.,
@Alf: amazing that there's still corners of the C++ language that make me look like an ignorant fool. Thanks for the link.
1

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.

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.