C++构造函数之委托构造函数

今天在读《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。函数体内的初始化要晚于成员列表初始化,即委托其他构造函数构造完后,在进行函数体内的赋值。

总结
  一个构造函数想要委托另一个构造函数,那么被委托的构造函数应该包含较大数量的参数,初始化较多的成员变量。而且在委托其他构造函数后,不能再进行成员列表初始化,而只能在函数体内进行初始化其他成员变量。
————————————————
版权声明:本文为CSDN博主「赤道以北」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/huangtiao2509/article/details/73882305

发布了190 篇原创文章 · 获赞 107 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/digitalkee/article/details/105042672
今日推荐