Question

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.

Was it helpful?

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

OTHER TIPS

If available on your compiler you can use a delegating constructor:

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

With C++03 you could use a default argument:

class derived : public base {
public:
    derived(derived_init init = derived_init{})
        : base(init.calc()), init_data(init)
    {
    }
private:
    derived_init init_data;
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top