Comment puis-je stocker dans une classe dérivée des informations obtenues lors de l'initialisation d'une classe de base?

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

Question

J'ai la situation qui, comme effet secondaire de proposer des données pour initialiser une classe de base, une classe dérivée calcule une pièce d'information qui doit plus tard être disponible via son interface. Ce qui suit donne une idée du problème, en utilisant un booléen comme l'information souhaitée:

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

Le problème est que l'information importante est calculée lors de l'initialisation de la classe de base, avant que les membres de données de classe dérivés soient initialisés. Je ne dois donc pas encore écrire aux éléments de données de la classe dérivée. Bien que je sois sûr, je peux vous échapper avec un booléen non encore officiellement créé sur une plate-forme que j'ai rencontrée au cours des 20 dernières années, je voudrais éviter d'invoquer un comportement indéfini.

Notez que les informations en question n'ont rien à faire du tout avec la classe de base, alors la stocker dans la classe de base n'est pas une option. En outre, les informations ne peuvent pas être stockées dans un organe de données statique. J'ai quelques idées sur la façon de refactoriser le code afin que je puisse faire cela, mais ceux que je pouvais trouver avec tous semblent assez intrusifs pour un tel problème. Alors je me demande si l'un de vous peut trouver quelque chose de simple?


note : puisque nous sommes sur une plate-forme intégrée, nous sommes bloqués avec GCC 4.1.2. Si strictement C ++ 03 (y compris TR1), mais non C ++ 11.

Était-ce utile?

La solution

en C ++ 11, vous pouvez faire quelque chose comme:

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, vous pouvez modifier votre classe dérivée à quelque chose comme:

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

Autres conseils

Si disponible sur votre compilateur, vous pouvez utiliser un constructeur de délégation:

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

avec C ++ 03 Vous pouvez utiliser un argument par défaut:

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top