Question

Je l'ai défini une interface Cloneable:

struct Cloneable
{
  virtual Cloneable * clone(void) const = 0;
}

J'ai aussi quelques autres classes d'interface (contenu non pertinent à émettre):

struct Interface
{
};

struct Useful_Goodies
{
};

J'ai créé un objet feuille qui hérite des classes ci-dessus:

struct Leaf : public Cloneable, public Interface, public Useful_Goodies
{
  Leaf * clone(void) const  // Line #1 for discussion.
  {
     return new Leaf(*this);
  }
};

Je reçois l'erreur:

overriding virtual function return type differs and is not covariant from 'Cloneable::clone'

Si je change le type de Cloneable *, je reçois ce message d'erreur:

'return' : ambiguous conversions from 'Leaf *' to 'Cloneable *'

Mes questions (toutes liées):

  1. Comment la classe des feuilles peut résoudre le exigences de la Cloneable interface?
  2. Y at-il une meilleure solution pour mettre en œuvre une contrat de clonage, où tous les objets sont garantis à mettre en œuvre le clonage?

J'utilise ce paradigme dans le cadre de la programmation générique (enregistrements, champs et base de données).

Compiler: MS Visual Studio 2008; Plates-formes: Windows XP et Vista

Était-ce utile?

La solution

Avoir votre retour de la fonction de clone un Cloneable * est correct.

Vous obtiendrez une conversion ambiguë si l'un de vos interfaces aussi de dérive Cloneable.

Modifier Alf souligne dans les commentaires que non seulement il est possible de retourner un Leaf::clone Leaf*, il est en fait préférable à le faire. Je me suis trompé.

Autres conseils

Vous avez probablement omis de mentionner que Interface ou d'une autre classe de base également de Cloneable inherits. Les moyens « de conversion » ambiguë Leaf contient probablement plusieurs sous-objets de classe de base de Cloneable. (Un problème avec le type de retour covariant pourrait être une conséquence directe du même problème.)

Vous aurez envie de résoudre ce problème en utilisant virtuel héritage (recommandé et lié lecture: C ++ FAQ Lite sujets 25,8 par 25,13). Pour commencer, le changement tous instances de : public Cloneable à : public virtual Cloneable.

Je peux risquer et dire que vous êtes probablement non pratiquement héritant de Cloneable de plus d'un chemin. C'est, une partie de votre autre base en plus des inherits de Cloneable directs (directement ou indirectement) de Cloneable. Cela rend la conversion de Leaf* à Cloneable* ambiguë car il y a plus d'une base de Cloneable dans votre Leaf.

La solution simple utilise l'héritage virtuel de l'interface:

struct Cloneable {
   virtual Cloneable * clone() = 0;
};
struct Interface : virtual Cloneable {
};
struct Test : virtual Cloneable, Interface {
   virtual Test* clone() {
      return new Test(*this);
   }
};

moyens d'héritage virtuel que même si les deux Interface et Test Hériter de Cloneable, il n'y a qu'un seul objet de base de Cloneable.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top