在类构造函数中初始化成员

问题描述:

有人能解释为什么我不能在构造函数的主体中初始化一个变量,就像我可以在成员初始化列表中一样。在类构造函数中初始化成员

class MyClass 
{ 
    public: 
    MyClass(); 
    virtual ~MyClass(void); 
    private: 
    std::string test; 
}; 

MyClass::MyClass() 
: test("asdf") <-- Case 1: This is OK 
{ 
    test("asdf"); <-- Case 2: This is not 
} 

我在问我有一个第三方类,我需要使用并通过将某些变量传递给它的构造函数进行初始化。如果我按照上面的情况1使用它,但没有在情况2中使用它,那很好。

+3

你不能调用'test'作为一个函数。 –

语法在constructing an object in the member initialisation list之间变化,并在构造函数的主体中为其赋值。

在初始化列表中,它是你所拥有的;

MyClass::MyClass() 
:test("abcd") 
{ 
    //... 
} 

在身上,你可以使用赋值语法

test = "abcd"; 

语法test("asdf");被解析为一个名为test函数被调用的"abcd"一个说法。

必须记住,如果成员没有默认构造函数,则初始化列表是唯一正确构造成员的地方。一旦构造函数的主体运行,所有成员都以某种方式构建或初始化。如有可能(如不适用于参考和const成员等),他们可能会被分配到,但不会被重新构建。

+1

初始化列表的另一个不错的属性是它允许初始化const成员,*按照定义*你不能改变。 –

+0

我会说“他们可能被分配到”,因为他们中的一些不能被分配,只有初始化,例如参考。 – Slava

test(“asdf”)是一个函数调用,您不能调用那样的字符串。初始化列表(“案例1”)是一个特例。

在构造体,只是使用分配

test="asdf". 

在这种情况下,在第一串测试是默认构造(变空),然后一个新的字符串被构造和分配给构件测试。

+2

从技术上讲,由于字符串获取默认构造,因此不会进行初始化。它是在ctor体内分配的。 – NathanOliver

+0

同意。改变了我的回答 –

+0

仍然听起来错了“如果你想初始化然后分配”,不,你不能这样初始化。虽然在这种情况下,结果在很多情况下都是相似的,但仅仅因为无法以这种方式进行初始化而无法正常工作。 – Slava

你有波纹管方式的构造函数初始化变量:

class MyClass 
{ 
public: 
    MyClass(); 
    virtual ~MyClass(void); 
private: 
    std::string test; 
}; 

方式1:

MyClass::MyClass() : test("asdf") 
{ 
} 

方式2:

MyClass::MyClass() 
{ 
    test = "asdf"; 
} 
+1

从技术上讲,这不是初始化,因为字符串在进入ctor主体之前获得构造函数构造的默认值。它是在ctor体内分配的。 – NathanOliver

+0

@NathanOliver是的,字符串是一个类,并在它自我构造函数初始化。 –

+0

'test =“asdf”;'不是初始化。当因为不使用成员初始化列表而调用构造函数时,字符串成员是默认构造的。然后在ctor主体中,你要分配任务,而不是初始化。只有你的第一种方法实际上用''test'初始化变量' – NathanOliver

不能初始化变量在t他是构造函数的主体,因为构造函数的主体运行在所有基类和成员已经在成员初始化列表中初始化了已经。它们隐含地默认初始化,因为你没有列出它们是无关紧要的。

因此,在正文中,test("asdf");试图拨打operator()test,这会失败。使用赋值(test = "asdf";)更改其值,或者更好地直接在成员初始化列表中初始化它。

你不能在构造函数体中初始化成员,因为它已经在那个时候初始化了,并且语法反映了这个事实。这已经回答了,但我想指出另一件事 - 不正确地使用术语可能会导致错误的代码。所以有人说“你可以通过赋值在构造函数体中初始化”。为什么这是错的?让我们来看看这个例子:

struct foo { 
    int i = 0; 
    int &r = i; 

    foo() {} 
    foo(int &ref); 
}; 

,你想r点一样ref如果构造函数被调用:

foo::foo(int &ref) : r(ref) 
{ 
} 

现在,如果你尝试通过转让“初始化”会发生什么:

foo::foo(int &ref) 
{ 
    r = ref; 
} 
现在

所以不是指向相同参考 as ref您刚分配给成员i的值。这可能会导致难以发现的错误和士气是:“术语在编程中很重要,你不应该*地玩它”