0

これは良いパターンですか?

BaseClass {
protected:
  Data m_data;
public:
  Interesting public_method() {
    //returns something interesting about m_data
    //what exactly depends on what the subclass put into m_data
  }
}

DerivedClass {
public:
  DerivedClass() { //properly populate m_data }
}

これの欠点は、サブクラスのプログラマーが何かをするように言われるだけで、実際にそれをするように強制されるわけではないため、物事が「緩い」ことであり、コンパイル時に強制されないことです。

良い方法またはより良い方法はありますか?

サブクラスのコンストラクターがその作業を行った後に、スーパークラスのコンストラクターのみを強制的に呼び出すことができれば。次に、スーパークラスのコンストラクターに必要なパラメーターを含めることができます

c++ はこれを許可しません:(

4

5 に答える 5

1

私には、これは正しく聞こえません。派生クラスが基底クラスを呼び出すことは前代未聞ではありませんが、より一般的には、派生クラスが (仮想)public_methodをオーバーライドしてその情報を提供します。

または、提案されているように、ファクトリ関数を使用します。または、静的な「コンストラクター」メンバー関数の場合、new を呼び出すのではなく、 と を呼び出す関数を呼び出しnewますspecial function to make set the data

すべての可能な解決策。

于 2013-02-08T20:56:13.937 に答える
1

サブクラスのコンストラクターがその作業を行った後に、スーパークラスのコンストラクターのみを強制的に呼び出すことができれば。次に、スーパークラス コンストラクターに必要なパラメーターを含めることができます。

ctor -initializer-listは非常に強力です。式のみを使用できますが、これらの式には関数呼び出しを含めることができます。実質的に、コンストラクター本体内で実行できることはすべて、初期化リスト内から実行できます。

もちろん、構築順序を尊重する必要があるため、基本クラスを初期化する前にメンバー関数を呼び出すことはできません。ただし、メンバーを初期化するときに基本クラスにアクセスできます。

class BaseClass
{
  Data m_data;
protected:
  BaseClass( Data&& data ) m_data(data) {}
public:
  Interesting public_method() {
    //returns something interesting about m_data
    //what exactly depends on what the subclass put into m_data
  }
};

class DerivedClass : public BaseClass
{
  static Data make_arg_into_data( const T& arg ) { /* calculate and return the right value for m_data */ }
  static Interesting make_arg_into_member_init( BaseClass* pThis, const T& arg ) { return pThis->public_method(); }
  V m_member;
public:
  DerivedClass( T arg ) BaseClass(make_arg_into_data(arg)), m_member(make_arg_into_member_init(this, arg)) {  }
};
于 2013-02-08T21:02:05.423 に答える
1

パターンというより、これはアンチパターンです。経験則: 保護された変数は良くありません。継承された振る舞い (具体的なクラスからの継承全般) は良くありません。もちろん、これらのいずれかを無視する理由がある場合もありますが、実際に何をしようとしているのかを言わないとわかりません。

于 2013-02-08T20:52:13.357 に答える
1

私の意見では、保護された変数は決して使用すべきではありません。私は、保護されたメソッドでプライベート変数を使用することを好みます。このように、ポリモーフィック オブジェクトを使用する場合は、メソッドをオーバーライドして、「悪い驚き」を回避できます。クラスが の場合final、もちろん、保護された変数を直接使用できます。

于 2013-02-08T20:54:08.263 に答える
0

工場を使用できるように聞こえます:

BaseClass {
private:
  Data m_data;
public:
  void setData(const Data& data) { m_data = data; }
  virtual Data generateData() = 0;
};

struct Factory
{
   template<class T>
   static BaseClass* getInstance()
   {
       BaseClass* t = new T;
       t->setData(t->generateData());
       return t;
   }
};

そしてそれを次のように呼び出します

BaseClass* p = Factory::getInstance<Derived>();

ご覧のとおり、非抽象派生クラスは強制的に を呼び出すgenerateDataため、有効な を生成する必要がありますData

これを書きやすくするために生のポインターのみを使用しましたが、使用しないでください:)

于 2013-02-08T20:51:15.420 に答える