web-dev-qa-db-ja.com

初期化リストを使用して親の保護されたメンバーを初期化する(C ++)

子クラスのコンストラクタの初期化リストを使用して、親クラスで保護されていると宣言されたデータメンバーを初期化することは可能ですか?私はそれを動作させることができません。私はそれを回避できますが、必要がなければいいでしょう。

いくつかのサンプルコード:

class Parent
{
protected:
    std::string something;
};

class Child : public Parent
{
private:
    Child() : something("Hello, World!")
    {
    }
};

これを試すと、コンパイラは「クラス 'Child'には 'something'という名前のフィールドがありません」と表示します。このようなことは可能ですか?もしそうなら、構文は何ですか?

どうもありがとう!

123
Stephen

あなたが説明する方法では不可能です。それを転送するために、基本クラスにコンストラクタを追加する必要があります(保護することができます)。何かのようなもの:

class Parent
{
protected:
    Parent( const std::string& something ) : something( something )
    {}

    std::string something;
}

class Child : public Parent
{
private:
    Child() : Parent("Hello, World!")
    {
    }
}
117
philsquared

コンパイラが初期化子リストに出くわすと、派生クラスオブジェクトはまだ形成されていません。基本クラスコンストラクターはそれまで呼び出されていません。基本クラスコンストラクターが呼び出された後にのみ、somethingが生成されます。したがって、問題。基本クラスコンストラクターを明示的に呼び出さない場合、コンパイラーはそれを行います(基本クラスの適切な単純なコンストラクターを生成することにより)。これにより、somethingメンバーがデフォルトで初期化されます。

C++ 0xドラフトから:

12.6.2ベースとメンバーの初期化

2 mem-initializer-idの名前は、コンストラクターのクラスのスコープで検索され、そのスコープで見つからない場合は、コンストラクターの定義を含むスコープで検索されます。 [注:コンストラクターのクラスにクラスの直接または仮想基本クラスと同じ名前のメンバーが含まれる場合、メンバーまたは基本クラスを命名し、単一の識別子で構成されるmem-initializer-idはクラスメンバーを参照します。非表示の基本クラスのmeminitializer-idは、修飾名を使用して指定できます。 --end note] mem-initializer-idがコンストラクターのクラス、コンストラクターのクラスの非静的データメンバー、またはそのクラスの直接または仮想ベースを指定しない限り、mem-initializer-idは不正な形式です。

注:重点鉱山

61
dirkgently

cant派生クラスコンストラクターの初期化リストで親クラスのメンバーを初期化します。それらが保護されているか、公開されているか、他の何かであるかは問題ではありません。

この例では、メンバーsomethingParentクラスのメンバーです。つまり、Parentクラスのコンストラクター初期化リストでのみ初期化できます。

12
AnT

たぶん、「using」というキーワードを使用して、その方法で試すことができます

class Parent
{

protected:
std::string something;
};

class Child : public Parent
{

private:
using Parent::something;
Child()
{
    something="Hello, World!";
}
};
0
user7710359