首页 > 代码库 > C++11初窥二: 继承构造函数和委派构造函数

C++11初窥二: 继承构造函数和委派构造函数

分析了这两种用法,真想吐槽两句,这两个特性确实有实际需要,但客观来说,现有标准足够用,而且带来的代价也非常大,又给C++复杂的语法糖重重的抹了一笔!!!

一、继承构造函数

继承构造函数的引入原因:如果基类的构造函数很多,那么子类的构造函数想要实现同样多的构造接口,必须一一调用基类的构造函数,有点麻烦

于是乎:C++11引入继承构造函数

class _A
    {
public:
    _A( int _InInt ) {;}
    _A( double _InDouble, int _InInt ) {;}
   _A( float _InFloat, int _InInt, const char* _Char ) {;}
    };

  
class _B : public _A
    {
public:
   using _A::_A;            // 使用_A中的构造函数
    // Somthing...
    virtual void _ExtraInterface() {;}
    };
 一句using _A::_A; 把基类中的构造函数都继承到派生类_B中, 这样最开始的那段代码就可以摆脱基类那么多构造函数接口了。

但是:

(1) C++11中的继承构造函数特性最有用的场合就是,派生类只是在基类的基础上添加了几个新的接口, 这个时候继承构造函数最能够展现威力.
但是缺陷就是, 继承构造函数只会初始化基类中的成员变量(毕竟只是从基类继承下来的), 对于派生类中的变量无能为力,

(2)不过,可以配合另一个C++11中的新特性: 数据成员就地初始化,来解决这个问题。但是,这种做法导致子类的成员不能在构造函数的参数列表中体现出来。

(3)一旦,子类继承了基类的构造函数,那么子类就不会自动生成默认构造函数。

struct _Base 
    { _Base( int ) {} };

  struct _Derived : _Base 
    { using _Base::_Base; };

  int main( int _Argc, char* *_Argv ) 
    {
    _Derived __derived; // 编译失败, 因为没有提供_Derived 的默认构造函数 
      return 0; 
          }

所以,如果子类新增了自己的成员变量,乖乖回到以前的初始化列表方法中吧。


二、委派构造函数

托构造函数允许类中的一个构造函数通过初始化列表方式来调用同一个类中的另一个构造函数。

class Info {
public:
    Info() : Info(1, 'a') { }
    Info(int i) : Info(i, 'a') { }
    Info(char e): Info(1, e) { }

private:
    Info(int i, char e): type(i), name(e) { /* 其他初始化 */ }
    int  type;
    char name;
    // ...
};
是减少冗余代码和重复代码的好办法,能提高代码的可读性。

但是,不要形成委托环

struct Rule2 {
    int i, c;
    Rule2(): Rule2(2) {}
    Rule2(int i): Rule2('c') {}
    Rule2(char c): Rule2(2) {}
};

Rule2定义中,Rule2()、Rule2(int)和Rule2(char)都依赖于别的构造函数,形成环委托构造关系。这样的代码通常会导致编译错误



C++11初窥二: 继承构造函数和委派构造函数