Search code examples
c++refactoringinitialization-order

How can I store in a derived class information obtained during initialization of a base class?


I have the situation that, as a side-effect of coming up with data to initialize a base class, a derived class calculates a piece of information that must later be available through its interface. The following gives an idea of the problem, using a boolean as the information wanted:

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

The problem with this is that the important piece of information is calculated during the initialization of the base class, before the derived class' own data members are initialized. I must thus not write to the derived class' data elements yet. While I am sure I can get away with a boolean not yet officially created on any platform I have come across in the last 20 years, I would want to avoid invoking undefined behavior.

Note that the information in question has nothing to do at all with the base class, so storing it in the base class is no option. Also, the information can not be stored in a static data member. I have a few ideas about how to refactor the code so that I can do this, but the ones I could come up with all seem quite intrusive for such a small issue. So I wonder if one of you can come up with something simple?


Note: Since we're on an embedded platform, we're stuck with GCC 4.1.2. So strictly C++03 (including TR1), but no C++11.


Solution

  • in C++11, you may do something like:

    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, you may change your derived class to something like:

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