4

基本クラスを初期化するためのデータを考え出すことの副作用として、派生クラスが、後でそのインターフェイスを介して利用できるようにする必要がある情報を計算するという状況があります。以下は、必要な情報としてブール値を使用して、問題のアイデアを示しています。

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

これに関する問題は、派生クラスの独自のデータ メンバーが初期化される前に、基底クラスの初期化中に重要な情報が計算されることです。したがって、派生クラスのデータ要素にはまだ書き込んではいけません。過去 20 年間に遭遇したどのプラットフォームでも、まだ正式に作成されていないブール値を使用できると確信していますが、未定義の動作を呼び出すことは避けたいと思います。

問題の情報は基本クラスとはまったく関係がないため、基本クラスに格納することはできません。また、情報を静的データ メンバーに格納することはできません。これを実行できるようにコードをリファクタリングする方法についていくつかのアイデアがありますが、思いついたものはすべて、このような小さな問題には非常に邪魔に思えます。それで、あなたの誰かが何か簡単なことを思いつくことができるのだろうか?


: 組み込みプラットフォームを使用しているため、GCC 4.1.2 に固執しています。厳密には C++03 (TR1 を含む) ですが、C++11 はありません。

4

2 に答える 2

2

コンパイラで利用可能な場合は、委譲コンストラクターを使用できます。

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

C++03 では、デフォルトの引数を使用できます。

class derived : public base {
public:
    derived(derived_init init = derived_init{})
        : base(init.calc()), init_data(init)
    {
    }
private:
    derived_init init_data;
};
于 2014-02-25T14:05:15.253 に答える
2

C++11 では、次のようなことができます。

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

C++03 では、派生クラスを次のように変更できます。

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;
};
于 2014-02-25T14:04:40.300 に答える