0

次の基本クラスについて考えてみます。これは、CallDerivedFunctionを呼び出した回数をカウントします。

class B {
  public:
    B() {numCalls = 0;}
    void CallDerivedFunction() {numCalls++; DerivedFunction();}
    int GetNumCalls() {return numCalls;}
  private:
    virtual void DerivedFunction() = 0;
    int numCalls;
};

私以外の人は、DerivedFunctionを実装する派生クラスを作成します。ただし、DerivedFunctionが呼び出される回数をカウントしようとしています。

派生クラスDがDerivedFunctionの独自の実装を直接呼び出すのを防ぐ方法はありますか?禁止:

class D : public B {
  private:
    void DerivedFunction() {
      if(<some condition>) DerivedFunction(); // I don't want to allow this.
      if(<some condition>) CallDerivedFunction(); // This is OK.
    }
};

注:もちろん、これは単純化したものです。より一般的な質問は、基本クラスがマネージャーとして機能し、派生クラスのコレクションの使用パターンの追跡などを行うことになっている場合、派生クラスにマネージャークラスを介して呼び出すように強制できますか?それとも、ここで正しいことをするために派生クラスの開発者に頼らなければなりませんか?

4

2 に答える 2

4

はい、あなたはこれを行うことができます-これはパスキーイディオムと呼ばれていると思います。

基本クラスにのみ「キー」ヘルパークラスを追加します。これは、基本クラスのみがインスタンス化できます(つまり、ctorはプライベートですが、基本クラスのフレンドです)が、派生クラスは見ることができます。次に、このヘルパークラスへの参照を「ロック」する関数のシグネチャに追加して、基本クラスのみが呼び出すことができるようにします。これは、「キー」をインスタンス化できる唯一のクラスであるためです。

class A
{
   public:
     class Key {Key(); friend ::A;};
     // Only A can call this, since only A can instantiate A::Key
     virtual void Foo(A::Key&)=0; 
};


class B:public A
{
  public:
    virtual void Foo(A::Key&) override
    {
      // B can override this...
    }

    void Bar()
    {
      Key k; // <- this wont compile, so you cannot call Foo from B
      this->Foo(k);
    }
};

これは、例のように再帰を防ぐものではないことに注意してください。ただし、参照の代わりに値を使用し、キーのコピーコンストラクターを無効にすることで、おそらくそれを機能させることができます。

于 2012-06-20T22:16:15.270 に答える
0

その関数がプライベートである場合、クラスDのDerivedFunctionをどのように呼び出しますか?つまり、クラスBからのみCallDerivedFunctionを呼び出すことができます

于 2012-06-20T20:21:47.633 に答える