2009-04-29 69 views
28

是否有可能在不聲明C++的情況下聲明一個變量?我想要做這樣的事情:在C++初始化之前聲明一個對象

Animal a; 
if(happyDay()) 
    a("puppies"); //constructor call 
else 
    a("toads"); 

Basially,我只想因此它的權利範圍申報條件的外面。

有沒有辦法做到這一點,而不使用指針並在堆上分配a?也許聰明的引用?

+0

看到RAII(資源採集是初始化) – newacct 2009-04-29 00:57:03

+1

,如果它是一個非靜態全局/命名空間範圍,那麼它是值得大家注意的,你可以不初始化它實際上宣告:EXTERN動物; ...動物(東西); – 2009-04-29 14:25:58

+0

@newacct:一個鏈接將有助於https://stackoverflow.com/questions/2321511/what-is-meant-by-resource-acquisition-is-initialization-raii – spinkus 2014-06-10 22:08:24

回答

27

你不能這樣直接在C,因爲當你使用默認的構造函數定義它的對象構造做++。

你可以,但是,運行參數的構造函數來開始:

Animal a(getAppropriateString()); 

或者你實際上可以使用類似的?: operator,以確定正確的字符串。 (更新:@Greg給出了這個語法,看到這個答案)

-3

是的,你可以不執行以下操作:

Animal a; 
if(happyDay()) 
    a = Animal("puppies"); 
else 
    a = Animal("toads"); 

這將正確地調用構造函數。

編輯:忘了一件事... 當聲明一個,你必須仍然調用一個構造函數,無論它是一個什麼都不做的構造函數,或者仍然初始化值爲任何東西。因此該方法創建兩個對象,一個在初始化時,另一個在if語句內。

一種更好的方式是創建該類的一個init()函數,如:

Animal a; 
if(happyDay()) 
    a.init("puppies"); 
else 
    a.init("toads"); 

這樣會更有效。

+2

你確定嗎?我認爲這會調用默認的構造函數,然後調用賦值操作符,所以你會失去舊的a。 – Uri 2009-04-29 00:24:43

+0

是的,我最初忘記了最初的構造函數。這就是爲什麼我通常在發佈之前測試我的代碼......這次沒有... – DeadHead 2009-04-29 00:27:16

+3

是的,但是假設(1)動物有一個可訪問的默認構造函數(在某些情況下有一個默認構造函數可能沒有意義(2)動物有一個賦值操作符(有些類不能通過設計賦值),(3)動物的構建和賦值與直接構建動物具有相同的效果。 – newacct 2009-04-29 00:27:18

34

如果不調用構造函數,則不能聲明變量。然而,在你的例子,你可以做到以下幾點:

Animal a(happyDay() ? "puppies" : "toads"); 
16

你不能在這裏使用引用,因爲只要你離開範圍,引用就會指向一個對象,被刪除。

真的,你有兩個選擇:

1的指針轉到:

Animal* a; 
if(happyDay()) 
    a = new Animal("puppies"); //constructor call 
else 
    a = new Animal("toads"); 

// ... 
delete a; 

2-添加init方法來Animal

class Animal 
{ 
public: 
    Animal(){} 
    void Init(const std::string& type) 
    { 
     m_type = type; 
    } 
private: 
    std:string m_type; 
}; 

Animal a; 
if(happyDay()) 
    a.Init("puppies"); 
else 
    a.Init("toads"); 

我會親自去與選項2.

15

我更喜歡格雷格的答案,但你也可以這樣做:

char *AnimalType; 
if(happyDay()) 
    AnimalType = "puppies"; 
else 
    AnimalType = "toads"; 
Animal a(AnimalType); 

我建議這樣做是因爲我曾經在那些條件運算符被禁止的地方工作。 (嘆氣!)另外,這可以很容易地擴展到兩種選擇之外。

5

除了格雷格Hewgill的回答,還有一些其他選項:

提升了代碼的主體爲一個功能:

void body(Animal & a) { 
    ... 
} 

if(happyDay()) { 
    Animal a("puppies"); 
    body(a); 
} else { 
    Animal a("toad"); 
    body(a); 
} 

(AB)使用放置新:

struct AnimalDtor { 
    void *m_a; 
    AnimalDtor(void *a) : m_a(a) {} 
    ~AnimalDtor() { static_cast<Animal*>(m_a)->~Animal(); } 
}; 

char animal_buf[sizeof(Animal)]; // still stack allocated 

if(happyDay()) 
    new (animal_buf) Animal("puppies"); 
else 
    new (animal_buf) Animal("toad"); 

AnimalDtor dtor(animal_buf); // make sure the dtor still gets called 

Animal & a(*static_cast<Animal*>(static_cast<void*>(animal_buf)); 
... // carry on 
8

如果你想避免垃圾收集 - 你可以使用智能指針。

auto_ptr<Animal> p_a; 
if (happyDay()) 
    p_a.reset(new Animal("puppies")); 
else 
    p_a.reset(new Animal("toads")); 

// do stuff with p_a-> whatever. When p_a goes out of scope, it's deleted. 

如果你仍然想使用。語法代替 - >,你可以在上面的代碼之後執行此操作:

Animal& a = *p_a; 

// do stuff with a. whatever 
0

最好的解決方法是使用指針。

Animal a*; 
if(happyDay()) 
    a = new Animal("puppies"); //constructor call 
else 
    a = new Animal("toads");