2

この質問に触発されて、私は反対を達成するためのトリック(SFINAEのような)があるかどうか知りたいです。

編集:例を追加

私はこのようなものを持っています(それは多くの詳細を持っているので非常に単純化されています):

#include <iostream>

class Base {
public:
  Base(){}
  virtual ~Base(){
  }
  void initialize() { implementation(); }
private:
  virtual void implementation() = 0;
};

class Derived : public Base {
private:
  virtual void implementation() { std::cout << "initialization" << std::endl;}
};

int main() {

  std::unique_ptr<Base> b(new Derived());
  b->initialize();

  return 0;
}

initializeメソッドを呼び出す必要があります。

しかし、初期化メソッドをBaseコンストラクター内に置くと、純粋仮想メソッドが呼び出されます。誰かが構築されたオブジェクトを不適切に使用するのを防ぐ方法があるかどうか知りたいです。

編集:私の「解決策」:

#include <iostream>

class Base {
public:
  virtual ~Base(){
  }
  Base() {};
private:
  void initialize() { implementation(); }
  virtual void implementation() = 0;
  template<class DerivedType> friend Base *factory();
};

class Derived : public Base {
private:
  Derived() {}
  virtual void implementation() { std::cout << "initialization" << std::endl;}
  template<class DerivedType> friend Base *factory();
};

template<class DerivedType>
static Base *factory(){
  Base *b = new DerivedType();
  b->initialize();
  return b;
}

int main() {

  std::unique_ptr<Base> b(factory<Derived>());

  return 0;
}
4

2 に答える 2

2

コンパイラエラーを強制することはできませんが、他の方法があります。

初期化が呼び出されない限り、型のインスタンスが単に無効であり、その事実を文書化するか、初期化されていない場合に使用時に例外をスローすることが受け入れられない場合は、コンストラクターをプライベートにし、静的メソッドを公開して型のインスタンスを作成する必要があります。

このように、コードのクライアントは、初期化されていないタイプのインスタンスを使用できません。より良い、よりエレガントなアプローチがある場合、私はそれを知りません(しかし、おそらくこのあたりの誰かが知っています)。

于 2012-06-28T21:42:28.183 に答える
1

オブジェクトを作成するときに、そのオブジェクトは初期化関数を呼び出さなくても適切に初期化できるため、これは必須ではないことに注意してください。

これは奇妙に聞こえるかもしれませんが、ほとんどの場合、そのinitialization()機能は適切ではありません。

class A
{
public:
    A() { do initialization of A fields here; }
};

class B : public A
{
public:
    B() { do initialization of B fields here; }
};

ほとんどの場合、これで十分です。

コンストラクターにパラメーターを渡す場合は、いくつかのインターフェースが必要になる場合があり(#includeでループを作成しないため)、次のようにそれらのパラメーターを渡すだけです。

class C;
class D;

class A
{
public:
    A(C c) { do initialization of A fields here; }
};

class B : public A
{
public:
    B(C c, D d) : A(c) { do initialization of B fields here; }
};

それ以外の場合は、実行時に検証するために、boostと私のcontroled_vars(intなどの型を安全にするためのテンプレート、最終的に!)は、フィールドが初期化され、デフォルト値をスローして返すことができるかどうかをチェックする機能を提供します。

そうでなければ、私はそのようなテストを行うためのコンパイラーの機能を知りません。ただし、テストを作成する場合(とにかく常にテストを行う必要があります!)、テストでそのような検証を行うことができます。

私が最初にプロファイラーについて考えたのですが、それはとにかくあなたが正しいかどうかを教えてくれるテストを必要とし、プロファイラーは初期化が呼び出されたことを示すことができますが、それがすべての場合に起こったかどうかはわかりません。

ただし、Ed S.が述べたように、コンパイル時にこのような初期化を実際に実施するには(本当に必要であると想定して)、おそらくファクトリを使用するのが最善です。そうすれば、すべての醜い初期化コードは隠されたままになります。

于 2014-06-03T10:36:37.687 に答える