Как я могу хранить в производном классе информацию, полученную во время инициализации базового класса?

У меня возникла ситуация, когда в качестве побочного эффекта при получении данных для инициализации базового класса производный класс вычисляет часть информации, которая впоследствии должна быть доступна через его интерфейс. Следующее дает представление о проблеме, используя логическое значение в качестве требуемой информации:

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 лет, я бы хотел избежать вызова неопределенного поведения.

Обратите внимание, что рассматриваемая информация не имеет никакого отношения к базовому классу, поэтому хранить ее в базовом классе не вариант. Также информация не может быть сохранена в статическом элементе данных. У меня есть несколько идей о том, как реорганизовать код, чтобы я мог это сделать, но те, которые я мог придумать, кажутся довольно навязчивыми для такой маленькой проблемы. Поэтому мне интересно, может ли кто-нибудь из вас придумать что-нибудь простое?


Заметка: Так как мы на встроенной платформе, мы застряли с GCC 4.1.2. Так что строго C ++ 03 (включая TR1), но не C ++ 11.

4

Решение

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

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

Если доступно на вашем компиляторе, вы можете использовать делегирующий конструктор:

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

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