转自:http://www.cnblogs.com/gnuhpc/archive/2012/12/10/2811920.html【略有改动】
- 什么是默认构造函数?
默认构造函数(default constructor)是由不带参数的构造函数,或者为所有的形参提供默认实参的构造函数定义,也就是说,它被调用时可以不传入任何实参。默认构造函数可以是用户自定义的,也可以是编译器产生的。请看下面的构造函数:
struct A { int x; A(): x(0) {}//用户自定义的不带参数的默认构造函数 }; struct B: { //no user-defined constructor. //the compiler implicitly declares a default constructor }; class C { public: explicit C(int n=0, int m=0); // 为所有的形参提供默认实参的默认构造函数 explicit C(int n,int m=0);//带两个形参的构造函数,但不是默认构造函数</span>,因为有一个形参int n没有默认实参 };
- 编译器什么时候隐式(implicitly)声明默认构造函数?
有两个条件:
1)该类没有显式(explicitly)声明任何构造函数。--既然你都定义了,系统就不给你生成了。
2)数据成员中没有const和reference。--因为要初始化。
满足则隐式生成默认构造函数。这里强调“任何”,是指即使用户自定义了复制构造函数或一个需要多个参数的构造函数,默认构造函数也不会被隐式声明了。
所以,在定义一个类时要保证有默认的构造函数。
- 隐式声明构造函数都做了什么?
什么都不做!确切的说,无论是隐式还是显式声明,都不意味着构造函数被定义。我们看看下边的情况:
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 virtual void f(); }; class F { virtual void 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.)
- 什么时候编译器隐式定义一个隐式声明的默认构造函数?
在下列情况中的任何一种就会隐式定义:
1)带有虚成员函数的类——完成vptr的初始化。
2)子类——隐式执行基类默认构造函数。请看下面的程序:
#include using namespace 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; }
3)虚基类继承