Инициализируйте переменную-член производного класса перед вызовом конструктора базового класса. Это UB?

Я хотел бы инициализировать переменную-член класса Derived и после этого передать ее конструктору базового класса. Я придумал решение ниже (также здесь: 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;
}

3

Решение

Я хотел бы инициализировать переменную-член класса Derived и после этого передать ее конструктору базового класса.

В C ++ порядок построения состоит из базовой части (частей) перед производными частями. Это связано с тем, что производные части гораздо чаще (потенциально) конструируются в терминах базовых частей. Для того, чтобы сделать это четко определенным, указывается порядок «основа-потом-производная». Следовательно, использование производного в базе не определено.

Если вы хотите, чтобы ваша база использовала производные члены, есть способ убедиться, что порядок в порядке. Сделайте также «члены» базовых классов. Обратите внимание, что 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();
};

Обратите внимание, что сейчас derived подклассы оба my_member_type а также base (в этой последовательности). Следовательно, последний может использовать первый в своей конструкции.

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

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]