5

基本クラスAにはサブクラスがありBBサブクラスがありCます。A仮想メソッドを実装し、実装doStuff()Bず、実装Cします。からの の実装Cを呼び出したい(これはの の実装内から実行しますが、それはあまり重要ではありません)。AdoStuff()CdoStuff()

A::doStuff();

または:

B::doStuff();

最初のものは、実際の実装を参照しているため、より明確に見えます。B一方、2 番目のdoStuff()方法は、後でA. どちらがより標準的ですか? どちらがより危険ですか?

B::doStuff()警告が発生しなかったことに少し驚きましたがB、基本クラスからのものであっても、定義により実装があると思います。基本クラスと実装のチェーンは、任意に長く複雑にすることができますか? たとえば、それぞれが前のサブクラスをA通過した場合Z、チェーンのどこにでも実装を持つことができますか?クラスのメソッドを呼び出すと、実装が見つかるまで「チェーンを上る」だけですか?

4

2 に答える 2

2

まず、最後の段落に関しては、はい、あなたは完全に正しいです。

次に、主な質問について:

ケースバイケースで扱われるべき論理の問題です。まだ実装されていなくても、Bからロジックを呼び出すか、 からロジックを呼び出すかを決定できるのは、あなただけです。正解はありません。AB::doStuff()

ただし、テンプレート メソッドのパターンを調べる必要があります。私の推測では、Cから何かを呼び出したい場合、後で(の兄弟) に同じことをさせAたいと判断した場合、コードを複製していると思います。だから私は別のアプローチを取るだろう:DC

class A
{
private:
   void doAStuff(); //doesn't have to be here
public:
   virtual void doStuff()
   {
      doAStuff();
   }
   void doAStuffAndStuff();
   {
      doAStuff();
      doStuff();
   }
}

class B : A
{
public:
   virtual void doStuff(); //or not
}

class C : B
{
public:
   virtual void doStuff();
}

IMO これはより直感的です。があるA* aとしますが、の動的タイプがわかりませんa:

  • doStuff()最も派生したクラスのロジックで呼び出したい場合は、 を呼び出しますdoStuff()
  • doStuff()最も派生したクラスのロジックで呼び出したいが、 からのロジックも必要な場合はA、 を呼び出しますdoAStuffAndStuff()

私はこのアプローチを代替手段として述べています。必ずしもあなたのケースに当てはまるとは言いませんが、当てはまるかもしれません。

于 2012-04-20T16:56:28.267 に答える
0

コールしB::doStuffます。さらに良いことに、可能であれば、基本クラスのメソッドを明示的に呼び出す必要がある設計を使用しないでください。必要base.doStuffに応じて、まさにその種のエラーを防ぐために、何らかのマクロまたはエイリアス構造でシミュレートしてください。BaseTypeクラスでエイリアスを定義し、コンパイル時にエイリアスが存在することを確認して、BaseType::doStuff構文を使用できます。

B::doStuff() が警告をトリガーしなかったことに少し驚きましたが、基本クラスからのものであっても、定義により B には実装があると思います

警告するものは何もありません。あなたの場合、それは法的なシナリオです。

基本クラスと実装のチェーンは、任意に長く複雑にすることができますか?

はい、できますが、すべきではありません。長い継承チェーンを必要とし、さらに何らかの隠されたルールを含む設計では、通常、どの基本クラスのどのメソッドを呼び出すべきかが壊れています。

于 2012-04-20T16:59:34.923 に答える