默认构造函数的常见问题

转自:http://www.cnblogs.com/gnuhpc/archive/2012/12/10/2811920.html【略有改动】

  1. 什么是默认构造函数?
    默认构造函数(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没有默认实参
    };

  2. 编译器什么时候隐式(implicitly)声明默认构造函数?
    有两个条件:
            1)该类没有显式(explicitly)声明任何构造函数。--既然你都定义了,系统就不给你生成了。
            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
    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.)

  4. 什么时候编译器隐式定义一个隐式声明的默认构造函数?
    在下列情况中的任何一种就会隐式定义:
             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)虚基类继承
       注:隐式定义的构造函数本身并不分配内存,它只是对一个类对象的初始而已,在声明对象时分配完内存,构造函数才被执行,并且也不对数据成员初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值