2012-02-22 5 views
4

私は以下のような定義された純粋仮想クラスがあります。私のような定義のコンストラクタを追加していない場合は純粋に仮想/抽象クラスは、特に保護されたconstメンバ変数にコンストラクタを必要とするのはなぜですか?

class BaseClass { 
protected: 
    const int var; 
public: 
    void somefun() = 0; // what I mean by a purely virtual class 
    // stuff... 
}; 

を:

BaseClass(const int & VAR) : var(VAR) {}; 

私はその後、これまで派生クラスで使用しなければならないでしょう、私の派生クラスはconst変数varをどの値にでも初期化できません。今私は実際にここで何が起こっているのか理解しています。派生クラスを構築する前に、基本クラスのコンストラクタが呼び出され、その時点でconstメンバ変数を初期化する必要があります。私の質問は、「私のコード作業をどうすればいいのか」という質問ではなく、すでに完了している。私の質問は、コンパイラがそれが必要だと思う理由についてです。コンパイラは以降(BaseClassのコンストラクタへの呼び出しは、必ずしもいくつかの派生クラスconstructrorへの呼び出しが続くことを知っている場合

class DerivedClass : BaseClass { 
public: 
    DerivedClass() : var(SOME_VALUE) {}; 
} 

:純粋仮想クラスのために、私はのような何かを書くことは許されるべきではありません抽象型のオブジェクトをインスタンス化することはできません)余裕をもう少し与えてはいけませんか?

これは、C++がダイヤモンドの問題を回避する方法の結果ですか?たとえそうであったとしても、コンパイラは、純粋に仮想関数のconstメンバー変数が派生クラスで定義される可能性を少なくとも何らかの形で許してはいけませんか?それはあまりにも複雑か、それともC++のDiamond問題の解決法が混乱していますか?

皆さんありがとうございます。

+0

おそらく、コンパイラは、派生クラスが基本クラスの保護されたメンバを初期化しなければならないというルールを強制しなければならない可能性があります。 –

+0

私はそれがそうするのは事実だと思います。しかし、この状況で本当に必要なのでしょうか? – ticster

答えて

4

「純粋に仮想」ではありません(あなたがそれを意味していても) - それにはデータメンバーが含まれています。

クラスメンバは、派生クラスではなく、そのクラスのコンストラクタの初期化子リストによってのみ初期化できます。これは、オブジェクトの初期化がどのように指定されるかです。初期化されるすべてのメンバーは、コンストラクタ本体が開始する前に初期化されます。

定数オブジェクトは、あとで値を割り当てることができないため、初期化する必要があります。

したがって、定数データメンバーを持つクラスは、各コンストラクターでそれを初期化する必要があります。純粋仮想クラスについては

+0

私が純粋にバーチャルを意味するのは、派生クラス、つまり決して初期化されないクラス以外では定義されていない関数を含む、抽象クラスと呼ばれるものです。 – ticster

+0

@ 。つまり、基本クラス以外のクラスはインスタンス化できませんが、データ・メンバーとは関係ありません。それらは非抽象クラスと同じように動作します。 –

+0

しかし、私のポイントは、彼らはする必要がありますか?その型のオブジェクトがインスタンス化されることはないことを知って、コンパイラは余裕を持たせるべきではありませんか? – ticster

1

、私はありません

のようなもの を書くことは許されるべきではない、しかし、あなたは(この場合にすべきである)このような何か書くことができます。

class DerivedClass : BaseClass { 
public: 
    DerivedClass() : BaseClass(SOME_VALUE) {}; 
}; 
+0

はい、私が言ったように、それは私がBaseClassのために定義したコンストラクタを使って行ったことです。私はなぜ言語がそのようなものなのか疑問に思っています... – ticster

+0

あなたが私たちに与えた例では、BaseClassコンストラクタを使わずに直接DerivedClass :: DerivedClassからBaseClass :: varを初期化しようとしました。親コンストラクタを呼び出すことで、実際にはvarインスタンス変数を初期化できます。これは「自分のコード作業をどうやって作るのか」という質問に答えます。 – mfontanini

+0

私が言ったように、私はすでにそれを考え出してやった。私は、BaseClassを決して初期化することができないため、なぜこの場合に必要なのかを理解しようとしています。 – ticster

1

オブジェクトの構築は特定の順序で行われます。基本クラスは、派生クラスのコンストラクターが実行される前に完全に構​​築されていなければなりません。派生コンストラクターは、完全に形成された有効な基本オブジェクトで動作します。基本メンバー変数の初期化が、派生クラスの構築まで延期された場合、この不変式は壊れてしまいます。

+0

これは抽象クラスにはなぜ適用されますか?結局のところ、コンパイラは、抽象型のオブジェクトは決してインスタンス化できないので、次のコンストラクタは必ず呼び出されることを知っています。 – ticster

関連する問題