0

メンバーを持ち、同じものを基本クラスに渡すと、次の場合に機能します。

DerrivedClass::DerrivedClass(SomeParamType* p)
    : BaseClass(p),
      derrivedClassMember(p),
{
 ...
}

...しかし、DerrivedClassコンストラクターにparamとして渡さずに共有する方法は? これは有効ですか?それとも、この時点で derrivedClassMember が初期化されていませんか?

DerrivedClass::DerrivedClass()
    : BaseClass(derrivedClassMember),
      derrivedClassMember(new SomeParamType()),
{
 ...
}

基本クラスの実装を変更できません。

4

5 に答える 5

4

C++11 では、委譲コンストラクターを使用できます。

class Derived : public Base {
public:
    Derived() : Derived(new SomeParamType()) {}
    ...
private:
    Derived(SomeParamType* p) : Base(p), derivedMember(p) {}
};

補足として、これはおそらく単なる例ですが、コンストラクターでこのようにヒープにアンマネージ オブジェクトを作成しないでBaseください。コンストラクターがスローすると、メモリ リークが発生します。可能な限りスマート ポインターを優先します。

于 2013-09-05T08:57:33.867 に答える
3

これを書いているとうんざりしますが…。

DerrivedClass::DerrivedClass(SomeParamType* p = new SomeParamType())
    : BaseClass(p),
      derrivedClassMember(p)
{
}

私は今シャワーを浴びる必要があります。とにかく、あなたの質問に敬意を表して、はい、メンバーが初期化される前に基本コンストラクターを実行する必要があります。メンバーは、コンストラクターの基本メンバーから始めて、上から順に初期化する必要があります。

注: これが指定されている場所を見つけるには、標準コピーをはがす必要がありますが、lintは順不同の初期化警告とそれらの非準拠について教えてくれるので、そこにあると確信しています。

于 2013-09-05T08:54:12.203 に答える
2

その時点では初期化されません。基本クラス コンストラクターは、derrivedClassMemberが初期化される前に呼び出されます。これは、派生メンバーまたは派生クラスのコンストラクターが基底クラスのメンバーに依存している可能性があるためです。

于 2013-09-05T08:53:24.203 に答える
2

これまでの回答を要約し、さらに追加すると、いくつかの解決策が考えられます。

1基本クラスにメンバーのアクセサーがある場合は、かなり簡単です。

DerrivedClass::DerrivedClass()
: BaseClass(new SomeParamType()),
  derrivedClassMember(getBaseClassMember()),
{
  ...
}

2 C++ 11 では、委譲コンストラクターを使用して、投稿した元のコンストラクターを呼び出します。

DerrivedClass::DerrivedClass()
: DerrivedClass(new SomeParamType())
{}

3 C++03 では、デフォルトの引数を使用します (これは醜いです):

DerrivedClass::DerrivedClass(SomeParamType* p = new SomeParamType())
    : BaseClass(p),
      derrivedClassMember(p),
{
 ...
}

4 C++03 でコンストラクターの既定の引数を取り除く別の回避策は、多重継承を使用してderivedclassMember、基本クラスの前に初期化されたものを取得することです。

struct DerivedClassInitializationWorkaround {
  SomeParamType* derivedClassMember:
  DerivedClassInitializationWorkaround(SomeParamType* param) 
    : derivedClassMember(param) {}
};

class DerivedClass : private DerivedClassInitializationWorkaround, //this has to go first!
                     public BaseClass {
public:
  DerivedClass::DerivedClass()
    : DerivedClassInitializationWorkaround(new SomeParamType())
    , BaseClass(derivedClassMember)
  {}
};

基本クラスの初期化は宣言の順序で行われるため、 から派生する場合、DerivedClassInitializationWorkaround含まderivedClassMemberれている が最初に初期化されます。

いずれにせよ、コードは例外セーフではありません。所有ポインターを生のポインターとして保存するのではなく、スマート ポインターを使用する必要があります。基本クラスは変更できないため、オブジェクトの所有権を取得するかどうか (つまり、コンストラクターに渡したオブジェクトを破棄するかどうか) を判断する必要があります。

基本クラス オブジェクトが所有権を取得する場合、派生クラスがポインターの代わりに参照を格納する必要があることを除いて、多かれ少なかれ既存のソリューションに固執しSomeParamTypeます。

基本クラスが所有権を取得しない場合は、次を保存する必要がありますunique_ptr

class DerivedClass : public BaseClass {
  unique_ptr<SomeParamType> derivedClassMember;

  DerivedClass::DerivedClass(unique_ptr<SomeParamType> param)
    : BaseClass(param.get())
    , derivedClassMember(move(param))
  {}

public:
  DerivedClass::DerivedClass()
    : DerivedClass(make_unique<SomeParamType>)
  {}
};
于 2013-09-05T09:24:09.687 に答える
1

簡単な答えはノーです。有効ではありません。

あなたの質問に対する良い答えは次のとおりです。

派生クラスの初期化リストから基本クラス コンストラクターを呼び出す順序

于 2013-09-05T08:58:30.197 に答える