Como posso armazenar em uma classe derivada de informações obtidas durante a inicialização de uma classe base?

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

Pergunta

Eu tenho uma situação em que, como um efeito colateral de chegar com dados para inicializar uma classe base, uma classe derivada calcula um pedaço de informação que posteriormente deve estar disponível através de sua interface.A seguir dá uma idéia do problema, usando um booleano como a informação que queria:

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

O problema com isto é que a informação importante é calculado durante a inicialização da classe base, antes que a classe derivada dos próprios membros de dados são inicializados.Devo, portanto, não escreva para a classe derivada de' elementos de dados ainda.Enquanto eu tenho certeza que eu posso fugir com um booleano ainda não foi oficialmente criado em qualquer plataforma com que me deparei nos últimos 20 anos, eu gostaria de evitar invocar comportamento indefinido.

Observe que as informações em questão não tem nada a ver com a classe base, de modo que armazená-lo na classe base não é opção.Também, a informação não pode ser armazenado em um membro de dados estáticos.Eu tenho algumas idéias sobre como refatorar o código para que eu possa fazer isso, mas o que eu poderia vir acima com todos parecem bastante intrusiva para um pequeno problema.Então eu me pergunto se de que você pode vir acima com algo simples?


Nota:Como estamos em uma plataforma embarcada, estamos presos com GCC 4.1.2.Portanto, estritamente C++03 (incluindo TR1), mas não em C++11.

Foi útil?

Solução

em C++11, você pode fazer 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;
};

Em C++03, você pode alterar sua classe derivada para 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;
};

Outras dicas

Se estiver disponível no seu compilador, você pode usar uma delegação construtor:

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

Com o C++03 você pode usar um argumento padrão:

class derived : public base {
public:
    derived(derived_init init = derived_init{})
        : base(init.calc()), init_data(init)
    {
    }
private:
    derived_init init_data;
};
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top