在调用Base类构造函数之前初始化Derived类成员变量。这是UB吗?

时间:2016-09-21 12:19:03

标签: c++ object-construction

我想初始化Derived类的成员变量,然后将其传递给Base类构造函数。我想出了下面的解决方案(也在这里:http://cpp.sh/4uu4q

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;
}

1 个答案:

答案 0 :(得分:3)

  

我想初始化Derived类的成员变量,然后将其传递给Base类构造函数。

在C ++中,构造的顺序是派生部分之前的基础部分。这是因为衍生零件更常见(可能)根据基础零件构造。为了使这个定义明确,指定了基本随后派生的顺序。因此,使用base中的derived是未定义的。

如果您希望您的基地使用派生成员,那么可以确保订单正常。成为&#34;成员&#34;基类也是。请注意,boost::base_from_member的构建完全是为了让这更方便。

说你有一些

class member_type{};

并且您希望derived拥有member_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();
};

请注意,现在derivedmy_member_typebase的子类(按此顺序)。因此,后者可以在构造中使用前者。

derived::derived() : 
    my_member_type{3},
    base{my_member_type::member} {
}