在C++初始化之前声明一个对象

问题描述:

是否有可能在不声明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://*.com/questions/2321511/what-is-meant-by-resource-acquisition-is-initialization-raii – spinkus 2014-06-10 22:08:24

你不能这样直接在C,因为当你使用默认的构造函数定义它的对象构造做++。

你可以,但是,运行参数的构造函数来开始:

Animal a(getAppropriateString()); 

或者你实际上可以使用类似的?: operator,以确定正确的字符串。 (更新:@Greg给出了这个语法,看到这个答案)

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

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

如果不调用构造函数,则不能声明变量。然而,在你的例子,你可以做到以下几点:

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

你不能在这里使用引用,因为只要你离开范围,引用就会指向一个对象,被删除。

真的,你有两个选择:

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.

我更喜欢格雷格的答案,但你也可以这样做:

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

我建议这样做是因为我曾经在那些条件运算符被禁止的地方工作。 (叹气!)另外,这可以很容易地扩展到两种选择之外。

除了格雷格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 

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

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 

最好的解决方法是使用指针。

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