¿Cómo puedo almacenar en una información de clase derivada obtenida durante la inicialización de una clase base?

StackOverflow https://stackoverflow.com//questions/22016200

Pregunta

Tengo la situación que, como efecto secundario de crear datos para inicializar una clase base, una clase derivada calcula una pieza de información que luego debe estar disponible a través de su interfaz. Lo siguiente da una idea del problema, utilizando un booleano como la información que deseaba:

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

El problema con esto es que la información importante de la información se calcula durante la inicialización de la clase base, antes de que se inicien los miembros de datos propios de la clase derivada. Por lo tanto, no debo escribir a los elementos de datos de la clase derivada todavía. Mientras estoy seguro de que puedo apartarme con un booleano que aún no se crea oficialmente en cualquier plataforma que haya encontrado en los últimos 20 años, me gustaría evitar invocar el comportamiento indefinido.

Tenga en cuenta que la información en cuestión no tiene nada que ver en absoluto con la clase base, lo que lo almacena en la clase base no es una opción. Además, la información no se puede almacenar en un miembro de datos estáticos. Tengo algunas ideas sobre cómo refactorizar el código para que pueda hacer esto, pero las que podría encontrar todo parece bastante intrusivo para un tema tan pequeño. ¿Así que me pregunto si uno de ustedes puede llegar a algo simple?


Note : Dado que estamos en una plataforma incrustada, estamos atascados con GCC 4.1.2. Tan estrictamente C ++ 03 (incluyendo TR1), pero no C ++ 11.

¿Fue útil?

Solución

en C ++ 11, puede hacer algo como:

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

En C ++ 03, puede cambiar su clase derivada a algo como:

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

Otros consejos

Si está disponible en su compilador, puede usar un constructor de delegación:

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

con C ++ 03 Podría usar un argumento predeterminado:

class derived : public base {
public:
    derived(derived_init init = derived_init{})
        : base(init.calc()), init_data(init)
    {
    }
private:
    derived_init init_data;
};

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top