1.什么是默认构造函数?
一个函数是默认构造函数当且仅当调用它可以不需要传入任何参数。这个函数可以是用户自定义的,也可以是编译器产生的。下边的各种构造函数都是默认构造函数。
struct A
{
int x;
A(): x(0) {}
};
struct B: A
{
//no user-defined ctor.
//the compiler implicitly declares a default constructor
};
class C
{
public:
explicit C(int n=0, int m=0); // may be invoked with no arguments
};
2.编译器什么时候隐式声明默认构造函数?
有两个条件:
- 该类没有显式声明任何构造函数。--既然你都定义了,系统就不给你生成了。
- 数据成员中没有const和reference。--因为要初始化。
满足则隐式生成默认构造函数。这里强调“任何”,是指即使用户自定义了复制构造函数或一个需要多个参数的构造函数,默认构造函数也不会被隐式声明了。
所以,在定义一个类时要保证有默认的构造函数。
3.隐式声明默认构造函数都干了什么?
什么都不做!确切的说,无论是隐式还是显式声明,都不意味着构造函数被定义。我们看看下边的情况:
class B
{
B(); //declaration only
};
B::B() {} //separate definition of the user-declared default constructor
class C
{
C() {} //declaration and definition
};
class D
{
//implicit declaration of a default constructor, no implicit definition
};
class E
{
//implicit declaration + implicit definition of a default constructor
virtualvoid f();
};
class F
{
virtualvoid f();
public:
F(); ////explicit declaration a default constructor, user forgot a definition
};
最后一种情况是常见的错误,用户忘记定义这个显式声明的默认构造函数,这会导致链接错误——用户自定义的默认构造函数必须实现,哪怕是空实现。
我们注意到class D的情况隐式声明,但是没有隐式定义,既然没有隐式定义,那编译器何必隐式声明呢?
首先我们要进一步明确隐式声明和隐式定义的实质,这两个动作都是概念上的,编译器并非真的到你的头文件中插入了相关代码,只是编译器、连接器和程序的行为表现出好像进行了这样的动作。实际上,编译器就是设置了几个bit做了标识而已。之所以要进行隐式声明,编译器只是规定了一个类可以被如何使用(Each implicit declaration is like an article in a contract that states how a certain class may be used. When the compiler implicitly declares one of the special member functions, it grants certain authorizations to the user.)
4.什么时候编译器隐式定义一个隐式声明的默认构造函数?
在下列情况中的任何一种就会隐式定义:
- 带有虚拟成员函数的类——完成vptr的初始化。
- 子类——隐式执行基类默认构造函数。
#include
usingnamespace std;
class Bar
{
public:
Bar(){cout<< "Default constructor!"<< pre>
};
class Too:public Bar
{
};
//Foo::Foo(Bar bar):bar(bar){}
int main()
{
Too too1;
return 0;
}
- 虚拟基类继承。
注:隐式定义的构造函数本身并不分配内存,它只是对一个类对象的初始而已,在声明对象时分配完内存,构造函数才被执行。并且也不对数据成员初始化。