1

クローン可能なインターフェースを定義しました:

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

他にもいくつかのインターフェイスクラスがあります(問題に関係のないコンテンツ):

struct Interface
{
};

struct Useful_Goodies
{
};

上記のクラスから継承するリーフオブジェクトを作成しました。

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

エラーが発生しました:

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

タイプをに変更するとCloneable *、次のエラーメッセージが表示さ れます。

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

私の質問(すべて関連):

  1. リーフクラスはどのようにしてCloneable インターフェースの要件を解決できますか?
  2. すべてのオブジェクトがクローン作成を実装することが保証されているクローン作成コントラクトを実装するためのより良いソリューションはありますか?

私はこのパラダイムをジェネリックプログラミング(レコード、フィールド、データベース)の一部として使用しています。

コンパイラ:MS Visual Studio 2008; プラットフォーム:WindowsXPおよびVista

4

3 に答える 3

2

関数が aをclone返すようにすることCloneable *は正しいです。

インターフェイスの 1 つが からも派生している場合、あいまいな変換が行われますCloneable

編集: Alf はコメントで、 がLeaf::clonea を返すことが可能であるだけでなくLeaf*、実際にはそうすることが望ましいと指摘しています。私は訂正します。

于 2010-10-15T16:23:06.990 に答える
1

あなたはおそらくそれについて言及しなかったInterfaceか、他の基本クラスも継承してCloneableいます。「あいまいな変換」とはLeaf、おそらく複数のCloneable基本クラスのサブオブジェクトが含まれていることを意味します。(共変の戻り値の型の問題は、同じ問題の直接の結果である可能性があります。)

仮想継承を使用してこの問題を解決することをお勧めします (推奨される関連記事: C++ FAQ Lite トピック 25.8 から 25.13)。まず、のすべてのインスタンスを: public Cloneableに変更します: public virtual Cloneable

于 2010-10-15T17:28:31.160 に答える
1

Cloneableおそらく、複数のパスから事実上継承していない可能性が高いと言えます。つまり、直接Cloneable継承以外の他のベースの一部が (直接または間接的に) から継承されCloneableます。に複数のベースがあるため、これにより からLeaf*への変換があいまいになります。Cloneable*CloneableLeaf

簡単な解決策は、インターフェイスからの仮想継承を使用することです。

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

仮想継承とは、 と の両方がInterfaceからTest継承されたとしても、基本オブジェクトCloneableは 1 つしかないことを意味します。Cloneable

于 2010-10-15T17:28:32.813 に答える