[C++11 类的改进] --- 继承构造函数和委托构造函数

Posted Overboom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[C++11 类的改进] --- 继承构造函数和委托构造函数相关的知识,希望对你有一定的参考价值。

1 继承构造函数

C++11 中提供的继承构造函数可以让派生类直接使用基类的构造函数,而无需自己再写构造函数,尤其是在基类有很多构造函数的情况下,可以极大地简化派生类构造函数的编写。先来看没有继承构造函数之前的处理方式:

#include <iostream>
#include <string>
using namespace std;

class Base

public:
    Base(int i) :m_i(i) 
    Base(int i, double j) :m_i(i), m_j(j) 
    Base(int i, double j, string k) :m_i(i), m_j(j), m_k(k) 

    int m_i;
    double m_j;
    string m_k;
;

class Child : public Base

public:
    Child(int i) :Base(i) 
    Child(int i, double j) :Base(i, j) 
    Child(int i, double j, string k) :Base(i, j, k) 
;

int main()

    Child c(520, 13.14, "i love you");
    cout << "int: " << c.m_i << ", double: " 
         << c.m_j << ", string: " << c.m_k << endl;
    return 0;

在子类中初始化从基类继承的类成员,需要在子类中重新定义和基类一致的构造函数,这是非常繁琐的,C++11 中通过添加继承构造函数这个新特性完美的解决了这个问题,使得代码更加精简。
继承构造函数的使用方法是这样的:通过使用 using 类名::构造函数名(其实类名和构造函数名是一样的)来声明使用基类的构造函数,这样子类中就可以不定义相同的构造函数了,直接使用基类的构造函数来构造派生类对象。

#include <iostream>
#include <string>
using namespace std;

class Base

public:
    Base(int i) :m_i(i) 
    Base(int i, double j) :m_i(i), m_j(j) 
    Base(int i, double j, string k) :m_i(i), m_j(j), m_k(k) 

    int m_i;
    double m_j;
    string m_k;
;

class Child : public Base

public:
    using Base::Base;
;

int main()

    Child c1(520, 13.14);
    cout << "int: " << c1.m_i << ", double: " << c1.m_j << endl;
    Child c2(520, 13.14, "i love you");
    cout << "int: " << c2.m_i << ", double: " 
         << c2.m_j << ", string: " << c2.m_k << endl;
    return 0;

2 委托构造函数

委托构造函数允许使用同一个类中的一个构造函数调用其它的构造函数,从而简化相关变量的初始化。下面举例说明:

#include <iostream>
using namespace std;

class Test

public:
    Test() ;
    Test(int max)
    
        this->m_max = max > 0 ? max : 100;
    

    Test(int max, int min)
    
        this->m_max = max > 0 ? max : 100;              // 冗余代码
        this->m_min = min > 0 && min < max ? min : 1;   
    

    Test(int max, int min, int mid)
    
        this->m_max = max > 0 ? max : 100;             // 冗余代码
        this->m_min = min > 0 && min < max ? min : 1;  // 冗余代码
        this->m_middle = mid < max && mid > min ? mid : 50;
    

    int m_min;
    int m_max;
    int m_middle;
;

int main()

    Test t(90, 30, 60);
    cout << "min: " << t.m_min << ", middle: " 
         << t.m_middle << ", max: " << t.m_max << endl;
    return 0;

在上面的程序中有三个构造函数,但是这三个函数中都有重复的代码,在 C++11 之前构造函数是不能调用构造函数的,加入了委托构造之后,我们就可以轻松地完成代码的优化了:

#include <iostream>
using namespace std;

class Test

public:
    Test() ;
    Test(int max)
    
        this->m_max = max > 0 ? max : 100;
    

    Test(int max, int min):Test(max)
    
        this->m_min = min > 0 && min < max ? min : 1;
    

    Test(int max, int min, int mid):Test(max, min)
    
        this->m_middle = mid < max && mid > min ? mid : 50;
    

    int m_min;
    int m_max;
    int m_middle;
;

int main()

    Test t(90, 30, 60);
    cout << "min: " << t.m_min << ", middle: " 
         << t.m_middle << ", max: " << t.m_max << endl;
    return 0;

在修改之后的代码中可以看到,重复的代码全部没有了,并且在一个构造函数中调用了其他的构造函数用于相关数据的初始化,相当于是一个链式调用。在使用委托构造函数的时候还需要注意一些几个问题:

  • 这种链式的构造函数调用不能形成一个闭环(死循环),否则会在运行期抛异常。
  • 如果要进行多层构造函数的链式调用,建议将构造函数的调用的写在初始列表中而不是函数体内部,否则编译器会提示形参的重复定义。
Test(int max)

    this->m_max = max > 0 ? max : 100;


Test(int max, int min)

    Test(max);	// error, 此处编译器会报错, 提示形参max被重复定义
    this->m_min = min > 0 && min < max ? min : 1;

  • 在初始化列表中调用了代理构造函数初始化某个类成员变量之后,就不能在初始化列表中再次初始化这个变量了。
// 错误, 使用了委托构造函数就不能再次m_max初始化了
Test(int max, int min) : Test(max), m_max(max)

    this->m_min = min > 0 && min < max ? min : 1;

以上是关于[C++11 类的改进] --- 继承构造函数和委托构造函数的主要内容,如果未能解决你的问题,请参考以下文章

[C++11 类的改进] --- 继承构造函数和委托构造函数

[C++11 类的改进] --- 继承控制:=default和=delete

[C++11 类的改进] --- 继承控制:=default和=delete

[C++11 类的改进] --- 继承控制:=default和=delete

[C++11 类的改进] --- 继承控制:final和override

[C++11 类的改进] --- 继承控制:final和override