Come posso archiviare in una classe derivata le informazioni ottenute durante l'inizializzazione di una classe base?

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

Domanda

Mi trovo nella situazione in cui, come effetto collaterale della creazione di dati per inizializzare una classe base, una classe derivata calcola un'informazione che deve essere successivamente disponibile attraverso la sua interfaccia.Quanto segue dà un'idea del problema, utilizzando un valore booleano come informazione desiderata:

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

Il problema è che l'informazione importante viene calcolata durante l'inizializzazione della classe base, prima che i membri dati della classe derivata vengano inizializzati.Pertanto non devo ancora scrivere sugli elementi dati della classe derivata.Anche se sono sicuro di poter farla franca con un booleano non ancora creato ufficialmente su nessuna piattaforma che ho incontrato negli ultimi 20 anni, vorrei evitare di invocare un comportamento indefinito.

Tieni presente che le informazioni in questione non hanno nulla a che fare con la classe base, quindi memorizzarle nella classe base non è un'opzione.Inoltre, le informazioni non possono essere archiviate in un membro dati statico.Ho alcune idee su come rifattorizzare il codice in modo da poterlo fare, ma quelle che ho potuto trovare sembrano tutte piuttosto invadenti per un problema così piccolo.Quindi mi chiedo se qualcuno di voi può inventare qualcosa di semplice?


Nota:Dato che siamo su una piattaforma incorporata, siamo bloccati con GCC 4.1.2.Quindi rigorosamente C++03 (incluso TR1), ma niente C++11.

È stato utile?

Soluzione

in C++11, puoi fare qualcosa del tipo:

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

In C++03, puoi modificare la classe derivata in qualcosa del tipo:

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

Altri suggerimenti

Se disponibile sul tuo compilatore puoi utilizzare un costruttore delegante:

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 potresti usare un argomento predefinito:

class derived : public base {
public:
    derived(derived_init init = derived_init{})
        : base(init.calc()), init_data(init)
    {
    }
private:
    derived_init init_data;
};
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top