关于使用C++11中委托构造函数

  今天在读《C++Primer》时读到委托构造函数一节,书中关于委托构造函数是这样描述的:

一个委托构造函数使用它所属的类的其他构造函数执行自己的初始化过程,或者说它把自己的一些(或者全部)职责委托给了其他构造函数。和其他构造函数一样,一个委托构造函数也有一个成员初始值的列表和一个函数体。在委托构造函数内,成员的初始值列表只有一个唯一的入口,就是类名本身。和其他成员初始值一样,类名后面紧跟圆括号括起来的参数列表,参数列表必须与类中另外一个构造函数匹配。

  初读这段话,可能理解上有一些偏差,一开始觉得意思就是一个构造函数可以用其他构造函数。于是写了段测试代码:

    class A
    {
        private:
            int a;
            char c;
        public:
            A(int num):a(num){}
            A(char C):c(C){}
            A(int num,char C):A(num),A(C){}//调用其他两个构造函数
    };

示例化一个对象x:A x(0,'x')
编译不过,提示错误:

error:mem-initializer for ‘class A’ follows constructor delegation A(int num,char C):A(num),A(C){}

成员初始化失败!StackOverFlow上也有人遇到了这个问题,有人给出了解答:

When you delegate the member initialization to another constructor, there is an assumption that the other constructor initializes the object completely, including all members. You can’t therefore initialize any of the members again.

 意思大概是当你委托另一个构造函数时,假定这个构造函数可以完整地构造出这个对象。上面的无论是A(int num)还是A(char C)都不能完整地构造出对象。按照这个思路,改一下代码如下:

    class A
    {
        private:
            int a;
            char c;
        public:
            A(int num,char C):a(num),c(C){}
            A(int num):A(num,' '){}//给char c默认值
    };

 这下代码可以编译通过了。那么是否真的这样呢?再用一段测试代码:

    class A
    {
        private:
            int a;
            int b;
            char c;
            //char d;
        public:
            A(int num0,int num1,char C):a(num0),b(num1),c(C){}
            A(int num0,char C):A(num0,0,C){}//委托上一个构造函数
            A(int num0):A(num0,' '){}       //委托上一个构造函数 
    };

  代码编译通过,注意到这里第二个构造函数委托第一个构造函数,能完整地构造出对象;而第三个构造函数委托第二个函数,也能完整地构造出对象。如果第一个构造函数不能完整地构造出对象,结果是什么样呢?把上面对char d的注释去掉,发现代码也能编译通过,d有默认值空!!!
那么StackOverFollow上的解答就是有误的,被委托的构造函数并不用包含所有成员变量,只要包含最大数量的成员变量即可。关于stackoverflow上的解答请点这里
不过,我发现答主后面补充了一下:

As a general rule, you should fully specify that version of the constructor that takes the largest number of arguments, and then delegate from the other versions (using the desired default values as arguments in the delegation).

  普遍规则是被委托的构造函数应该包含最大数量的参数,然后被其他构造函数委托(可以使用默认值进行委托构造)~
  了解到在使用委托构造函数时,不能再进行成员列表初始化,而只能在函数体内进行初始化其他成员变量。那么我们在委托其他构造函数构造对象时,一些成员变量以默认值构造了,在函数体内进行初始化就不叫初始化了,只能叫重新赋值了。见下面例子:

 class A
  {
      private:
          int a;
          int b;
          char c;
          char d;
      public:
          A(int num0,int num1,char C):a(num0),b(num1),c(C){}
          A(int num0,char C):A(num0,0,C){}//b默认初始化为0
          A(int num0):A(num0,'p'){b=1;}//b重新赋值为1
          void getMembers()
          {
              cout<<a<<" "<<b<<" "<<c<<" "<<d<<endl;
          }
  };

在委托第二个构造函数构造时,b被初始化为0,这里我们在函数体内重新赋值为1,那么b到底是0还是1呢?结果是1。函数体内的初始化要晚于成员列表初始化,即委托其他构造函数构造完后,在进行函数体内的赋值。

总结

  一个构造函数想要委托另一个构造函数,那么被委托的构造函数应该包含较大数量的参数,初始化较多的成员变量。而且在委托其他构造函数后,不能再进行成员列表初始化,而只能在函数体内进行初始化其他成员变量。

  • 12
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,我理解了您的要求,下面是我的回答: 委托构造函数是指在一个构造函数调用另一个构造函数来完成对象的初始化,从而避免重复编写初始化代码的冗余。在 C++11 标准委托构造函数可以用来实现类构造函数之间的代码复用,其语法形式是在构造函数的初始化列表使用类名进行初始化;在 C++14 标准,还允许使用“成员初始化器列表”的形式来初始化数据成员;在 C++17 和 C++20 标准,则进一步扩展了委托构造函数的应用场景,如支持默认参数、派生类构造函数自动继承基类的所有委托构造函数等。 区别如下: C++11标准委托构造函数只能在初始化列表调用,委托到的构造函数必须在当前类声明且不能包含任何成员初值设定项(即不能有成员初始化器列表),否则会导致编译错误。 C++14标准委托构造函数支持成员初始化器列表,因此也可以在成员初始化器列表调用其他的委托构造函数C++17标准委托构造函数可以使用默认参数,即可以省略代表默认值的实参,同时,派生类构造函数可以自动继承基类的所有委托构造函数C++20标准委托构造函数可以在初始化列表对非直接基类进行构造,即可以将委托到的构造函数放在任意位置,并且可以使用 constexpr 构造函数进行委托构造。 希望我的回答对您有帮助,如果还有其它问题,请继续提问!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值