我最近开始研究 C++,我在通过初始化列表初始化成员变量时观察到一个奇怪的行为。
//Demo.h
#ifndef DEMO
#define DEMO
#include <iostream>
class Demo
{
public:
Demo();
explicit Demo(int x);
};
#endif
//Demo.cpp
#include "Demo.h"
Demo::Demo()
{
std::cout << "Demo()" << std::endl;
}
Demo::Demo(int x)
{
std::cout << "Demo(int x)" << std::endl;
}
//Test.cpp
#include "Demo.h"
class Test
{
public:
Test()
// : d_(123)
{
}
private:
Demo d_;
};
int main(int argc, char const *argv[])
{
Test t;
return 0;
}
在上面的代码片段中,我为类 Demo(d_
) 创建了一个对象,当我运行程序时,Demo()
正在打印。但是,如果我取消注释注释代码 (d_(123)
),我将获得 Demo(int x)
作为输出。
第一个场景对我来说很清楚,但第二个我无法理解? 编辑: 我的问题是我已经创建了一个对象(类测试中的成员变量),但是我再次在初始化列表中传递了整数参数。那么是否可以通过,因为对象已经创建并再次尝试初始化它?
答案 0 :(得分:3)
当您只是在类的主体中声明数据成员时,您不会初始化。实际上,当您为类编写定义时,您根本没有创建任何内容,它只是创建类的未来实例的蓝图。之后,当你创建一个类类型的对象时,对象是通过一个相应的构造函数创建的,然后我们才进行数据成员的初始化。
定义类后,将其实例化
Test t; // an object created, default constructor is used
在本例中,使用 t
的默认构造函数创建了一个对象 Test
。此默认构造函数使用 d_
的构造函数初始化 Demo
类型的类的数据成员 Demo
,该构造函数采用 int
。
当你构造一个对象时,成员初始值设定项列表中的所有数据成员仍然需要实例化 (它们不是默认构造的,它们仍然需要以某种方式构造) 。这就是 member initializer list 的美妙之处。
因此,一个对象可以是默认构造的,但它可以使用其他构造函数(非默认)构造,在这种情况下,甚至不触及默认构造函数。
注意,如果您要避免在构造函数的主体中使用成员初始值设定项列表和已初始化的数据成员,则数据成员将首先默认构造,然后重新分配新值(在主体中构造函数).
答案 1 :(得分:0)
第一个场景对我来说很清楚,但第二个我无法理解?
如果您取消对成员初始化列表的注释,您将向 Demo
的构造函数传递一个参数。