2016-09-21 86 views
3

我想初始化一個Derived類的成員變量,然後將其傳遞給Base類的構造函數。我想出了下面的解決方案(也在這裏:http://cpp.sh/4uu4q在調用基類構造函數之前初始化派生類成員變量。這是UB嗎?

1)以下代碼是否有定義或未定義的行爲(UB)?

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

我想初始化一個派生類的成員變量,之後將其傳遞給基類的構造。

在C++中,構造順序是派生部分之前的基礎部分。這是因爲派生部分(可能)根據基礎部分構建得更加普遍。爲了使這個定義良好,指定了基於派生的訂單。因此,使用派生的基礎是未定義的。

如果您希望您的基地使用派生成員,有一種方法可確保訂單正常。製作「成員」基類也是如此。請注意,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} { 
} 
相關問題