Как я могу хранить в полученной информации, полученной при инициализации базового класса?
-
21-12-2019 - |
Вопрос
У меня есть ситуация, которая в качестве побочного эффекта придумывается с данными для инициализации базового класса, полученный класс рассчитывает часть информации, которая должна быть доступен через его интерфейс. Следующее дает представление о проблеме, используя логию в качестве информационной потребности:
class base {
public:
base(some_initialization_data);
// ...
};
class derived : public base {
public:
derived()
: base(calc_init_data())
{
}
bool condition_x_occurred() const
{
// How to get at the information obtained
// during the call to calc_init_data()?
}
private:
static some_initialization_data calc_init_data()
{
// This piece of information will later be needed:
const bool condition_x_occurred = /* ... */;
return some_initialization_data(condition_x_occurred);
}
};
.
Проблема с этим заключается в том, что важная информация рассчитывается при инициализации базового класса, до того, как инициализированы собственные элементы данных класса. Таким образом, я должен не писать в элементы данных полученного класса еще. Хотя я уверен, что могу уйти с булевом, еще не официально созданным на любой платформе, который я столкнулся за последние 20 лет, я хотел бы избежать неопределенного поведения.
Обратите внимание, что информация о вопросе не имеет ничего общего с базовым классом, поэтому сохраняя его в базовом классе не является вариантом. Кроме того, информация не может быть сохранена в статическом элементе данных. У меня есть несколько представлений о том, как ревертировать код, чтобы я мог сделать это, но те, которые я мог бы придумать, все, кажется, довольно навязчивым для такой маленькой проблемы. Поэтому мне интересно, может ли один из вас придумать что-то простое?
Решение
в C ++ 11, вы можете сделать что-то вроде:
class derived : public base {
public:
derived() : derived(calc_init_data()) {}
bool condition_x_occurred() const { return my_condition_x_occurred; }
private:
derived(const std::pair<bool, some_initialization_data>& p) :
base(p.second), my_condition_x_occurred(p.first)
{}
static std::pair<bool, some_initialization_data> calc_init_data()
{
// This piece of information will later be needed:
const bool condition_x_occurred = /* ... */;
return std::make_pair(condition_x_occurred, some_initialization_data(condition_x_occurred));
}
private:
bool my_condition_x_occurred;
};
.
в C ++ 03, вы можете изменить свой полученный класс к чему-то вроде:
class derived : public base {
public:
static derived make_derived() { return derived(calc_init_data()); }
bool condition_x_occurred() const { return my_condition_x_occurred; }
private:
derived(const std::pair<bool, some_initialization_data>& p) :
base(p.second), my_condition_x_occurred(p.first)
{}
static std::pair<bool, some_initialization_data> calc_init_data()
{
// This piece of information will later be needed:
const bool condition_x_occurred = /* ... */;
return std::make_pair(condition_x_occurred, some_initialization_data(condition_x_occurred));
}
private:
bool my_condition_x_occurred;
};
. Другие советы
Если на вашем компиляторе вы можете использовать делегирующий конструктор:
struct derived_init
{
bool data;
some_initialization_data calc()
{
data = true;
return some_initialization_data();
}
};
class derived : public base {
public:
derived()
: derived(derived_init{})
{ }
bool condition_x_occurred() const
{
return init_data.data;
}
private:
derived(derived_init init)
: base(init.calc()), init_data(init)
{ }
derived_init init_data;
};
.
С C ++ 03 вы можете использовать аргумент по умолчанию:
class derived : public base {
public:
derived(derived_init init = derived_init{})
: base(init.calc()), init_data(init)
{
}
private:
derived_init init_data;
};
.