1

ニワトリ<->エッグの問題があります。
コンテナー クラスのインターフェイスを作成して、特定の属性アクセサーやその他のメソッドの実装を強制できるようにすると同時に、コンテナー コンストラクターからこれらのメソッドを呼び出せるようにしたいと考えています。
しかし、Constructor から仮想メソッドを呼び出すと、階層内のコンストラクターが呼び出される順序のために、Base クラスのメソッドが呼び出されることがわかっています。
問題は、実装を強制するために仮想メソッドが必要ですが、それはコンストラクターで呼び出すことができないことです。
編集: コンテナー クラス (C1、C2...) を実装する必要があるときに、特定のメソッドを強制的に実装する必要があり、次にコンテナー コンストラクターでそれらのメソッドを使用できるようにしたい。簡単に言えば、INTERFACE 要件、declaration-only-mixin を実装したいと考えています。ありがとう
この問題をどのように解決しますか?
以下はコードサンプルです。

#include <iostream>
using namespace std;

class Base {
public: 
    virtual void myvirt() { cout << "Base::virt()" << endl; };
};

class C1 : public Base {
 public:
    C1() {cout << "C1()" << endl; C1::myvirt(); };
    C1(int i) { cout << "C1(int)" << endl; }
    void myvirt() { cout << "C1::virt" << endl;}
};


class C2 : public Base {
 public:
    C2() {cout << "C2()" << endl; C2::myvirt();};
    C2(int i) { cout << "C2(int)" << endl; }
    void myvirt() { cout << "C2::virt" << endl;}
};

template<class C = C1>
class Sc: public C {
 public:
    Sc() : C() { cout << "Sc()" << endl; };
    Sc(int n): C(n)  { cout << "Sc(int)" << endl; };

};


int main() {
    Sc<C2>  $sx(12);
    return 0;
}

私が尋ねているように、特定の Constructors() の子孫クラスで強制的に実装する方法はありますか。「仮想コンストラクタ」のようなもの。

4

2 に答える 2

5

コンストラクターを自明にして、コンストラクターが戻った後、ある種の初期化関数を呼び出して、オブジェクトの構築を完了します。構築するオブジェクトの種類を決定する方法に応じて、 cloneイディオムを使用することもできます。

コンストラクターが最初に内部クラスを構築し、次にその仮想初期化関数を呼び出すラッパー クラスを使用することもできます。

更新:次のようにラップできます:

 Class Wrapper : public Inner
 {
        public:
        Wrapper(...) : Inner(...)
        {
            init();
        }
        virtual ~Wrapper();
 }

今、あなたはただすることができます

 Wrapper foo(whatever);

fooと同じように使用できますInner

于 2012-09-08T21:56:49.943 に答える
3

そもそも、構築中または破棄中に仮想関数を呼び出すべきではありません。それは単に良い習慣ではありません。

有効な C++、第 3 版の項目 9 からの抜粋:

この一見直感に反する動作には、十分な理由があります。基本クラス コンストラクターは派生クラス コンストラクターの前に実行されるため、派生クラスのデータ メンバーは基本クラス コンストラクターの実行時に初期化されていません。基本クラスの構築中に呼び出された仮想関数が派生クラスに移行した場合、派生クラスの関数はほぼ確実にローカル データ メンバーを参照しますが、それらのデータ メンバーはまだ初期化されていません。それは、未定義の動作と深夜のデバッグ セッションへのノンストップ チケットです。まだ初期化されていないオブジェクトの部分を呼び出すことは本質的に危険であるため、C++ ではそれを行う方法がありません。

http://www.artima.com/cppsource/nevercall.html

于 2012-09-08T22:43:44.247 に答える