<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">我想有看过不少C++的书籍,都会有以下的表述:</span>
在Class中,如果我们没有声明构造函数,编译器都会给我们默认构造一个构造函数,也就是Default Construct,但是真的是如此吗,请看以下的example:
lass AA
{
public:
int x;
AA *next;
};
int main()
{
AA a;
std::cout << a.x << std::endl;
system("pause");
return 0;
}
我在vs2010上编译,会有一个运行时错误。
编译器不是应该给我们声明一个默认的构造函数吗,比如像这样,虽然什么都不做
AA()
{
}
但是,它并没有这么做,因为编译器并没有这个责任,这是程序员本身的需要。
那如果我们定义了像上面的构造函数,就可以通过编译了,结果如下:
那如果我们在AA中定义了一个虚函数,然后不定义构造函数,比如说,
那么,它也可以通过编译,虽然值是乱码。所以你明白了吗,这个时候,编译器为我们定义了一个默认的构造函数,虽然并没有初始化它的成员变量。
情况2:如果我们的类AA虚拟继承于Base,那么它也会定义一个默认的构造函数,来放置其对象base的位置。
情况3:如果我们继承于某个类,这个类有构造函数,那么编译器也会为我们定义一个默认的构造函数(才能调用其基类的构造函数),如下所示:
那如果基类,都没有一个有定义(程序员明确定义或者编译器定义的默认构造函数),那么类也不会为我们定义一个默认的构造函数,此时也会有运行时错误:
情况4:如果类中的数据成员,带有构造函数,此时类也会为我们定义一个默认的构造函数(编译器会为我们调用数据成员的构造函数,初始化数据),如下所示:
所以,总结如下:
有四种情况,编译器会为我们定义一个默认的构造函数,已满足编译器的需要(初始化虚表、初始化基类或者数据成员等等):
1. 带有虚函数的类(编译器会为我们定义虚表,已实现多态);
2. 虚继承(编译器需要为我们初始化虚基类的位置);
3. 数据成员带有构造函数(默认或者明确定义,此时需要编译器合成一个默认的构造函数,来调用数据成员的构造函数);
4.继承于基类,这个基类带有构造函数,此时需要编译器合成一个默认的构造函数,才调用基类的构造函数)。
以上四种情况,编译器才认为合成的默认构造函数有用的,其他情况,编译器都不会为我们合成此类的构造函数。