4

通常、コンストラクターは次のようになります。

//ctor1
SmallSim::SmallSim()
:mSimInit(false)
,mServersCreated(false)
,mTotalCPUTime(0)
{
    ...
}

複数のコンストラクターがある場合はどうなりますか?

2番目のコンストラクターから最初のコンストラクターを呼び出すと、最初のメンバー変数が初期化されないように見えます。

//ctor2
SmallSim::SmallSim(bool ImmediateExecution, bool Report)
{
    SmallSim();

    ...
}

それで、私が持っているすべてのコンストラクターで:mSimInit(false)、mServersCreated(false)、mTotalCPUTime(0)を繰り返す必要がありますか?

私の知る限り、InitClassVars()を使用するのは最善の方法ではありません...

//ctor1
SmallSim::SmallSim()
{
    InitClassVars();

    ...
}

//ctor2
SmallSim::SmallSim(bool ImmediateExecution, bool Report)
{
    InitClassVars();

    ...
}

//Common function for init of member vars for multiple constructors
void SmallSim::InitClassVars(void)
{
    mSimInit = false;
    mServersCreated = false;
    mTotalCPUTime = 0;
}

すべてのコンストラクターでinitを繰り返さずにメンバー変数を初期化する正しい方法はありますか?

4

4 に答える 4

10

これを行う場合:

SmallSim::SmallSim(bool ImmediateExecution, bool Report)
{
    SmallSim(); // 1

    ...
}

1でマークされた行は、SmallSim使用されていないためすぐに破棄される新しい一時オブジェクトを作成します。現在初期化されているオブジェクトには何の影響もありません。同じオブジェクトで別のコンストラクターを呼び出すには、次のようにします。

SmallSim::SmallSim(bool ImmediateExecution, bool Report)
: SmallSim() {
    ...
}

(これはC ++ 11の機能です。)

于 2012-05-02T15:57:44.787 に答える
6

C++03には2つのオプションがあります。

  • すべてのコンストラクターから呼び出すinit関数を使用します
  • すべてのctorの初期化リストを提供する

C ++ 11では、委任ctorを使用して、他のすべてから1つのctorを呼び出すことができます。

于 2012-05-02T15:56:34.313 に答える
2

それを行う正しい方法はありません。初期化を関数に委任する場合は、デフォルトでデータを1回初期化してから、値を割り当てます。初期化リストの作成を利用したい場合は、繰り返す必要があります。設定は異なります。

幸い、C ++11ではコンストラクターを委任できます。ここを参照してください。

C ++ 11では、宣言の時点で初期化することもできます。これは次の場合に役立ちます。

struct Foo {
  int i{0};
  double x{0.}:
};

ここで、コンストラクターは、値を変更したい場合を除いて、iまたはについて何もする必要はありません。x

于 2012-05-02T15:57:06.130 に答える
0

@juanchopanzaが述べたように、コンストラクターを処理する「正しい」または「完璧な」方法はありません。オブジェクトを割り当て、そのフィールド/プロパティを初期化する方法はいくつかあります。

コンストラクターが別のコンストラクターを呼び出すことはお勧めしません。同じクラスで、混乱する可能性があります。

申し訳ありませんが、あなたの例がよくわかりませんでした。簡単な例を使用します。自動化されたレストランを持っている旅行セールスマンのためのこのビジネスホテルがあると仮定しましょう。

注文を受ける機械もあれば、コーヒー、パン、ケーキ、ジュースなどの料理もありますが、ワッフル、卵などの料理は準備に時間がかかります。

顧客はレストランに到着して機械に行き、注文時にいくつかのボタンを押すことができます。彼(彼女)は、他の食べ物を待っている間に、コーヒーなどのすでに準備された食べ物のいくつかを提供するように要求することがあります。彼はまた、空の皿を取り、すべてが一緒に提供されるのを待つかもしれません。

彼は後で、何よりも同じ価格で戻ることができます。

この例では、注文を受け取るマシンを表すクラスを定義します。

マイナーな構文、エラー、バグを無視し、コンストラクターとフィールドの初期化を処理するためにこのアイデアを確認してください。


// note: good idea to add an empty value to enumerations:

enum BeveragesEnum {
  none,
  water,
  orangejuice,
  milk,
  coffe,
  cocoa
}; // enum BeveragesEnum

enum BreadsEnum {
  none,
  donut,
  bagel,
  cherrypie,
  applepie,
  cake
}; // enum BreadsEnum

enum FoodEnum {
  none,
  ScrambledEggs,
  OverEggs,
  Chicken,
  Waffles,
  Pancakes,
  Beef
}; // enum FoodEnum

class AutomatedCafeteriaClass
  protected: 
    BeveragesEnum Beverage;
    BreadsEnum Bread;
    FoodEnum Food;

    public:
      /* constructor*/ AutomatedCafeteriaClass();
      /* destructor*/ ~AutomatedCafeteriaClass();

    public:
      void quickGiveMeCoffe();
      void wantCoffeAndBread
        (
          BreadsEnum aBread
        );
      void onlyBeverage(BeveragesEnum aBeverage);
      void BeverageBreadFirstFoodLater
        (
          BeveragesEnum aBeverage;
          BreadsEnum aBread;
          FoodEnum aFood;
        );
      void waitForEverything
        (
          BeveragesEnum aBeverage;
          BreadsEnum aBread;
          FoodEnum aFood;
        );
      void wantFood
        (
          FoodEnum aFood;
        );

    public:
      void prepare();
}; // class AutomatedCafeteriaClass

/* constructor*/ AutomatedCafeteriaClass::AutomatedCafeteriaClass()
{
  // first assign empty values
  this.Beverage = BeveragesEnum.none;
  this.Bread    = BreadsEnum.none;
  this.Food     = FoodsEnum.none;
} // constructor AutomatedCafeteriaClass

/* destructor*/ AutomatedCafeteriaClass::~AutomatedCafeteriaClass()
{
  // clear by assigning empty values
  this.Beverage = BeveragesEnum.none;
  this.Bread    = BreadsEnum.none;
  this.Food     = FoodsEnum.none;
} // constructor AutomatedCafeteriaClass

void AutomatedCafeteriaClass::quickGiveMeCoffe()
{
  this.Beverage = BeveragesEnum.Coffe;
  prepare();
}

void AutomatedCafeteriaClass::wantCoffeAndBread
(
BreadsEnum aBread
)
{
  this.Beverage = BeveragesEnum.Coffe;
  this.Bread    = aBread;
  prepare();
}

void AutomatedCafeteriaClass::onlyBeverage(BeveragesEnum aBeverage)
{
  this.Beverage = aBeverage;
  prepare();
}

void AutomatedCafeteriaClass::BeverageBreadFirstFoodLater
(
BeveragesEnum aBeverage;
BreadsEnum aBread;
FoodEnum aFood;
)
{
  this.Beverage = aBeverage;
  this.Bread    = aBread;
  this.Food     = aFood;
  prepare();
}

void AutomatedCafeteriaClass::waitForEverything
(
  BeveragesEnum aBeverage;
  BreadsEnum aBread;
  FoodEnum aFood;
)
{
  this.Beverage = aBeverage;
  this.Bread    = aBread;
  this.Food     = aFood;
  prepare();
}

void AutomatedCafeteriaClass::wantFood
(
  FoodEnum aFood;
)
{
  this.Food     = aFood;
  prepare();
}

void AutomatedCafeteriaClass::prepare();
{
  // prepare the food
}

コンストラクターではなく、これらすべての関数が、コンストラクターと同じようにフィールドを初期化することに注意してください。これは、「postconstructors」または「initialiazers」とも呼ばれます。

これらすべての関数を実際のコンストラクターに変換することも可能ですが、混乱する可能性があるため、各関数が独自の識別子を持っている方が簡単です。

乾杯。

于 2012-05-02T16:43:37.083 に答える