3

C++(03) クラスには、オブジェクトの構築中に値を割り当てる必要があるメンバー変数があります。ただし、必要な値を計算できるのは派生クラスだけです。この投稿で説明したように、C++ では、派生クラスから基底クラスのメンバーを初期化する必要がありますか? 、派生クラスが基底クラスのメンバーを初期化できないことは理解していますが、割り当てで十分です。

したがって、基本クラスにメソッドを提供して値を割り当てますが、派生クラスにそれを強制的に呼び出す方法がわかりません。以下のサンプル コードは、この点を示しています。

class Base {
public:
    Base() {}
    setFoo(unsigned inFoo) { foo = inFoo; }
private:
    unsigned foo;
};

class Derived : public Base {
    Derived() : Base() { 
        unsigned desired = ... // do calculations to get the desired value
        setFoo(desired);  // --> how to ensure that derived class calls this?
    }
};

その後foo、他のいくつかの Base クラス メソッドによって使用されます。に「フラグ」を設定しても、setFoo()それを確認できる「ポストコンストラクタ」メソッドはありません。が使用される基本クラスには、他にもいくつかのメソッドがありますfoo。そこで確認することはできますが、退屈でエラーが発生しやすく、非効率的です。

これが以前に尋ねられた場合、私の謝罪。「派生クラスコンストラクターが特定の基本クラスメソッドを呼び出す必要があることを確認する」および「派生クラスに基本クラスメンバーを割り当てるように強制する」を検索して尋ねる前に、ここで見つけようとしました。C++ の派生クラスのコンストラクターで基本クラスの const 変数を初期化するにはどうすればよいですか? Derived Class に Base Class の Constructor を使用するように強制しますが、残念ながら私の質問には対応していません。

この状況に対処するための適切なアプローチを教えてください。コンパイル時のチェック ソリューションが望ましいですが、それが不可能な場合は、ランタイム チェックも役に立ちます。私の問題に C++11 を使用することはできませんが、C++11 の解決策も教えていただければ幸いです。ご検討いただきありがとうございます。

編集もちろん、これを要件として文書化することもオプションですが、プログラムによる解決策があるかどうかを知りたいです。

Edit2コンストラクターパラメーターで値を渡す必要があるという回答に同意します。Baseゼロから作成する必要がある場合、このアプローチは要求しませんでした。問題は、従来の理由により、Baseすでにいくつかのコンストラクターパラメーター (9) があり、コンストラクター本体にそれらを「オフロード」することで、さらに (3) 追加することを避けたいと考えていたことです。ただし、長期的には、コードをリファクタリングする必要があります。

Edit3非常に多くの編集を申し訳ありません。クラスは好きなように変更できBaseますが、Derivedクラスはクライアント コードにあり、制御できません。

4

3 に答える 3

9

派生クラスのコンストラクターが を呼び出さなければならない場合、setFoo()それは設計上の問題だと思います。コンストラクターが目的の値を引数として取り、派生クラスが計算された値を次のように渡すように、基本クラスを設計することをお勧めします。

class Base {
public:
    Base(unsigned int foo) : m_foo (foo) {}  //define this constructor
private:
    unsigned int m_foo; //member data
};

class Derived : public Base {
    Derived() : Base(computeValue()) 
    { 
    }
private:
    static unsigned int computeValue() //it may take argument(s)
    {
        unsigned int desired = ... //do calculations to get the desired value
        return desired;
    }
};
于 2012-12-09T13:47:40.987 に答える
2

オブジェクトの構築に値が必要な場合は、コンストラクターのパラメーターにする必要があります。

class Base {
public:
    Base(unsigned inFoo) { setFoo(inFoo); }
    setFoo(unsigned inFoo) { foo = inFoo; }
private:
    unsigned foo;
};

class Derived : public Base {
    Derived() : Base(compute_desired()) { }

};

ここcompute_desiredには、 のメンバーDerived、または計算を行う任意の関数を指定できます。

于 2012-12-09T13:50:28.350 に答える
0

派生クラスに、そのコンストラクターで基本クラスのメソッドを強制的に呼び出すことはできないと思います。他の応答で手法を使用して実装/呼び出しを強制できる場合がありますが、基本クラスを変更できない限り、私の知る限り、Derived のコンストラクターでそれが行われることを完全に確認することはできません。

于 2012-12-09T13:57:11.610 に答える