2

と関数が定義されAた基本クラスが与えられます。A::getA::add

class A { 
public:
  int get() { return 3; }
  int add() {
    return get() + get();
  }
};

A::addを呼び出すことに注意してくださいA::get。派生クラスBが呼び出しA::addて独自のB::get関数を使用する方法はありますか? 何かのようなもの:

class B : public A {
  int get() { return 7; }
};

#include <iostream>

int main() {
  A foo;
  std::cout << foo.add() << std::endl;

  B bar;
  std::cout << bar.add() << std::endl;
  return 0;
}

期待される出力は、2 番目のケースではあり14ません。6を制御できれば、仮想関数をA作成でき::get、各派生クラスは必要に応じてそれを実装できます。ただし、それは不変であると仮定しAましょう - どうすれば正しい を呼び出すことができます::getか?

4

3 に答える 3

5

いいえ、これは不可能です。それAが個別にコンパイルされ、事前にコンパイルされたライブラリとして提供されていると想像してください。理由を確認してください。

は仮想ではないため、コンパイラは、 vtableを介した間接処理なしで、A::getへの直接の呼び出しをの出力に挿入します。さらに、コンパイラは、呼び出しをインライン化することを選択した場合、呼び出しをインライン化し、 の戻り値を出力に「焼き込む」ことさえできます。A::getA::add3

于 2012-08-13T19:36:31.327 に答える
2

そのようです:

class B : public A {
  int get() { return 7; }
  int add() {
    return get() + get();
  }
};

それは、次のように定義するA::add()

int add() {
  return get() + get();
}

コンパイラに を使用するように指示します。これはA::get()ではないためvirtual、呼び出しは静的に解決されます。

重要: これを行う必要がある場合は、おそらく何か間違ったことをしている可能性があります。ほとんどの場合、の作成者はA、何らかの方法で動作することを望んでおり、仮想get的であることを望んでいませんでした. addこれは単なる回避策です。

于 2012-08-13T19:35:46.373 に答える
1

Aが不変の場合、A必要な仮想インターフェイスを定義するプロキシを作成できます。

class A_Proxy : public A {
public:
  virtual ~A_Proxy () {}
  virtual int get() { return A::get(); }
  int add() { return get() + get(); }
};

これで、代わりにB継承元に変更して、必要な動作を得ることができます。A_Proxy

編集: Luchian へのコメントに基づいて、テンプレート メソッドの方が適していると思います。ルーチンがテンプレート メソッドのパラメーターから値を取得するAように変更します。元の動作と一致するテンプレート パラメーターを使用して、テンプレート化されたバージョンを呼び出すaddnew を作成します。add

class A {
public:
  int get() { return 3; }

  template <typename GET>
  int add(const GET &g) { return g(this) + g(this); }

  struct DefaultGet {
    int operator () (A *p) const { return p->get(); }
  };

  int add() { return add(DefaultGet()); }
};

次に、必要な get パラメーターを渡してB、テンプレートadd化されたルーチンを呼び出します。

class B : public A {
public:
  struct BGet {
    int operator () (A *) const { return 7; }
  };
  int add() { return A::add(BGet()); }
};
于 2012-08-13T19:42:02.793 に答える