2012-05-02 34 views
4

初始化成員變量通常是一個構造函數應該是這樣的:C++與多個構造

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

,如果我有多個構造會發生什麼?

它在我看來,如果我從我的第二個構造函數調用,第一個成員變量不會被初始化。

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

    ... 
} 

所以我需要重複 :mSimInit(假) ,mServersCreated(假) ,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成員用了重複的每一個構造在init瓦爾正確的方法是什麼?

+3

您使用的是C++ 03還是C++ 11? – Electro

+0

我使用gcc -std = C++ 0x編碼,所以我在思考11,因爲智能指針工作。 – DieSlower

回答

8

如果你這樣做:

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

    ... 
} 

標有1的行創建其很容易被破壞,因爲它不被使用一個新SmallSim臨時對象。它對目前正在初始化的對象沒有任何影響。要調用同一對象的另一個構造函數,你做這樣的:

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

(這是一個C++ 11功能)。

+1

+1用於解釋他在用SmallSim()進行的操作。 –

+0

示例總是有幫助的,謝謝,現在接受我收到一個錯誤,提示「類型'SmallSim'不是'SmallSim'的直接基礎」任何想法?我的C++ 11標誌在... – DieSlower

+4

@DieSlower可能你的編譯器不支持委託構造函數。 AFAIK,你至少需要GCC 4.7或Clang 3.0。 –

6

有兩個選項在C++ 03:

  • 使用您打電話從每一個構造函數
  • 的初始化函數爲所有構建函數

在C提供一個初始化列表++ 11你可以使用委託,以便你可以從其他人那裏調用一個委託人。

+0

添加從每個構造函數調用的init時,必須小心。確保這個方法不是虛擬的,因爲在構造函數中調用虛擬方法並不總是給出您期望的結果。 –

+0

@J_D:這當然是一個給定的要求,請參閱FAQ 23.5 (儘管你可以在技術上使用虛擬,如果你*非常*,*非常*小心,並在特殊條件下)。 – dirkgently

+1

@J_D顯然你只會初始化這個類的變量,所以我不知道你爲什麼期望在這裏有一個虛擬函數。 –

2

沒有正確的方法來做到這一點。如果您將初始化委託給函數,那麼您默認初始化數據,然後分配值。如果你想從初始化列表構造中受益,那麼你必須重複自己。首選項不同。

幸運的是C++ 11允許委託構造函數,請參閱here

C++ 11也允許初始化在聲明的時候,這可能有助於:

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

這裏,構造函數不必做任何事情ix,除非他們想改變的值。

0

正如@juanchopanza提到的,不存在「正確」或「完美「的方式來處理構造函數,有幾種方法來分配對象,並初始化它的字段/屬性。

我不建議構造函數調用另一個構造函數,在同一個類上,它可能會一團糟。

對不起,我不太瞭解你的例子,我會用一個簡單的例子。讓supp supp有這個商務酒店的旅行推銷員有一個自動化的餐廳。

有一些機器接受訂單,一些食物已經準備好,如咖啡,麪包或蛋糕,果汁,而其他食物如華夫餅,雞蛋需要時間準備。

顧客可以到達餐廳去機器,並按其順序按下一些按鈕。他(她)可能會要求在等待其他食物的同時供應已經準備好的一些食物,例如咖啡。他也可以拿一個空盤子,等待,全部送達。

他可以以更高的價格返回更多的東西。

本示例將定義一個類,它表示接受訂單的機器。

請忽略次要語法,錯誤&錯誤,並檢查這個想法來處理構造函數&字段的初始化。


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

注意,所有這些功能,altought,不直接構造,initialiaze領域的一個構造器,也被稱爲 「postconstructors」 或 「initialiazers」。

它也有可能將所有這些函數轉換爲真正的構造函數,但可能會有些混亂,因此每個函數都有自己的標識符。

乾杯。