我最近开始研究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()
正在打印时,我为类Demo(d_
(创建了一个对象。但是,如果我取消注释注释的代码(d_(123)
(,我将得到Demo(int x)
作为输出。
第一种情况我很清楚,但第二种情况我无法理解?编辑:我的问题是我已经创建了一个对象(类Test中的成员变量(,但我再次在初始值设定项列表中传递整数参数。那么,因为对象已经创建并再次尝试初始化它,所以可以通过吗?
当您在类的主体中声明数据成员时,不会初始化。实际上,当您为类编写定义时,根本不创建任何东西,它只是创建类的未来实例的蓝图。稍后,当您创建类类型的对象时,该对象是通过相应的构造函数创建的,只有这样我们才能初始化数据成员。
定义完类后,将其实例化为
Test t; // an object created, default constructor is used
在本例中,使用Test
的默认构造函数创建了一个对象t
。此默认构造函数使用Demo
的构造函数初始化Demo
类型的类数据成员d_
,该构造函数采用int
。
构造对象时,成员初始值设定项列表中的所有数据成员仍将被实例化(它们不是默认构造的,仍将以某种方式构造(。这就是成员初始值设定项列表的美妙之处。
因此,一个对象可以默认构造,但它可以使用其他构造函数(非默认(来构造,在这种情况下,默认构造函数甚至不会被触及。
注意,如果要避免在构造函数主体中使用成员初始值设定项列表和初始数据成员,则数据成员将首先默认构造,然后用新值(在构造函数主体(重新分配。
第一种情况我很清楚,但第二种情况我无法理解?
如果取消对成员初始化程序列表的注释,则会将一个参数传递给Demo
的构造函数。