2016-09-21 10 views
3

派生クラスのメンバ変数を初期化した後、それをBaseクラスのコンストラクタに渡したいとします。次のコードが定義されていないInitialize Baseクラスのコンストラクタを呼び出す前に、派生クラスのメンバ変数を初期化します。このUBですか?

1)または未定義の動作(UB):私は(http://cpp.sh/4uu4qもここに)以下の解決策を考え出しましたか?

2)は私が悪いデザインの表示を行うようにしようとしています何ですか?

struct Data { 
    int fValue; 

    Data(int value = -1) : fValue(value) 
    {} 
}; 


struct Base { 
    Base(const std::unique_ptr<Data> & derivedData) { 
     std::cout << "Constructing Base derivedData=" << derivedData->fValue << std::endl; 
    } 
}; 


struct Derived : public Base { 
    std::unique_ptr<Data> fData = std::move(fData); 

    Derived() : Base(ConstructData()) 
    {} 

    const std::unique_ptr<Data> & ConstructData() { 
     fData.release(); 
     fData.reset(new Data(777)); 
     std::cout << "in ConstructData: fData->fValue =" << fData->fValue << std::endl; 
     return fData; 
    } 
}; 


int main() { 
    Derived d; 
    std::cout << "In main: d.fData->fValue =" << d.fData->fValue << std::endl; 
    return 0; 
} 
+0

2)はい、あなたの基本クラスはコンストラクタ内の派生クラスについて知る必要があるのはなぜですか? – user463035818

+0

派生クラスは、基本クラスが構築されるまで構築されません。これはUBです。 –

+0

コンストラクタが呼び出される前にfDataを操作するので、UBです。 –

答えて

3

Iは、派生クラスのメンバ変数を初期化したい、その後基底クラスのコンストラクタに渡すことになります。

C++では、構築順序は、派生した部分の前の基底部分の順序です。これは、導出された部品が(潜在的に)ベース部品に関して構築されることがはるかに一般的であるためです。これを明確にするために、基底派生順序が指定されています。したがって、基底での派生の使用は未定義です。

あなたのベースが派生メンバーを使用したい場合は、注文がOKであることを確認する方法があります。 "メンバー"ベースクラスも作成してください。 boost::base_from_memberは、これをより便利にするために作られています。

はあなたには、いくつかの

class member_type{}; 

があり、derivedmember_typeメンバーを持っている、とbaseから派生したいのですが言います。そして、あなたが使用することができます

class derived : 
    private boost::base_from_member<member_type>, 
    public base { 
    using my_member_type = private boost::base_from_member<member_type>; 

public: 
    derived(); 
}; 

なお、今derivedサブクラスの両方my_member_typebase(この順番で)。したがって、後者は前者をその構成に使用することができる。

derived::derived() : 
    my_member_type{3}, 
    base{my_member_type::member} { 
} 
関連する問題