2

両方のクラスが抽象クラスから派生している別のクラスへの参照を取得するメンバー関数を使用してクラスを作成したいと思います。addElem()を実装していないため、クラスContainerが抽象であるというコンパイラエラーが発生します。

class Ielem
{
public:
  virtual void action() = 0;
};

class Elem: public Ielem
{
public:
  void action() {};
  void extra() {};
};

class Icontainer
{
public:
  virtual void addElem(Ielem &elem) = 0;
};

class Container: public Icontainer
{
public:
  void addElem(Elem &elem) { elem.extra(); };
};

int main(int argc, char* argv[])
{
  Elem e;
  Container c;
  c.addElem(e);

  return 0;
}

Elemへの参照はIelemへの参照でもあるため、これは機能するはずです。Container::addElemにIelemへの参照を取得させるとコンパイルされます。ただし、Container :: addElem()は、使用している組み込みコンパイラで使用できないdynamic_cast、またはタイプセーフではない通常のキャストを使用しない限り、Elem :: extra()を呼び出すことはできません。

提案?

4

2 に答える 2

1

これは間違った方法です。基本クラスは、任意のオブジェクトを引数として取ることができることをIcontainer指定しますが、派生クラスでは、のみを受け入れます。これは「より狭い」タイプであるため、基本クラスで指定されている「あなたが私に投げたものはすべて受け入れます」という契約に違反しています。addElem Ielem ElemIelem

ここではテンプレートが解決策になると思います。基本クラスももう必要ありません。このようなもの:

class Elem
{
public:
  void action() {};
  void extra() {};
};

template<typename ElemType>
class Container
{
public:
  void addElem(ElemType &elem) { elem.extra(); };
};

int main(int argc, char* argv[])
{
  Elem e;
  Container<Elem> c;
  c.addElem(e);

  return 0;
}

Containerボーナスとして、機能を備えた任意のタイプで使用できるようextra()になり、それが機能します。

于 2012-10-03T19:10:22.327 に答える
0

問題は、仮想メソッドが、それをオーバーロードすることを目的とした具象メソッドと同じシグネチャを持っていないことです。したがって、コンパイラはそれを完全に別の関数と見なし、を実装していないために文句を言いますvoid addElem(Ielem &elem)。これはおそらく望まない解決策の1つです-

class Icontainer
{
public:
  virtual void addElem(Elem &elem) = 0;  //Ielem -> Elem
};

それは他のすべての制約に依存しますが、私が行うこと、そして一般的な設計ガイドライン(Sutter&Alexandreascuなど)に準拠しているように見えることは、完全なインターフェイスを備えた中間抽象クラスを作成することだと思います。

class Melem: public Ielem
{
public:
  // void action() {}; //Already have this form Ielem
  void extra() = 0;
};

その後

class Icontainer
{
public:
  virtual void addElem(Melem &elem) = 0;
};

class Container: public Icontainer
{
public:
  void addElem(Melem &elem) { elem.extra(); }; 
     //*Now* we're implementing Icontainer::addElem
};
于 2012-10-03T20:34:49.963 に答える