• c++11新特性篇-委托构造函数和继承构造函数


    C++11引入了委托构造函数(Delegating Constructor)和C++11及后续标准引入了继承构造函数(Inheriting Constructor)两个特性。

    1.委托构造函数

    委托构造函数是C++11引入的一个特性,它允许一个构造函数调用同一类的另一个构造函数,从而避免在类内部出现相似的初始化代码,提高代码的可维护性。在构造函数的初始化列表中使用 : 符号,可以调用同一类中的其他构造函数

    下面是一个简单的例子,展示了如何使用委托构造函数:

    #include 
    using namespace std;
    
    class Myclass {
    public:
    	// 有参构造
    	Myclass(int x, int y):m_X(x), m_Y(y) {
    
    	}
    
    	// 无参构造调用有参构造
    	Myclass(): m_X(0), m_Y(10) {
    
    	}
    
    public:
    	int m_X;
    	int m_Y;
    };
    
    void test01() {
    	// 利用无参构造创建对象
    	// 两个属性值会直接初始化为0和10
    	Myclass mc;
    	cout << mc.m_X << endl; // 0
    	cout << mc.m_Y << endl; // 10
    
    }
    
    int main() {
    	test01();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    在上述例子中,有参构造函数负责实际的初始化工作,而无参构造函数则使用了委托构造函数的方式,通过调用有参构造函数来完成初始化。这样,无参构造函数就避免了代码的重复,并且仍然能够正确地初始化对象。

    需要注意的是,委托构造函数的调用必须出现在构造函数的初始化列表中在构造函数主体中调用其他构造函数是不允许的。

    使用委托构造函数可以使得类的构造函数更加灵活,能够复用已有的构造函数,减少代码冗余。

    2.继承构造函数

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

    #include 
    #include 
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    通过测试代码可以看出,在子类中初始化从基类继承的类成员,需要在子类中重新定义和基类一致的构造函数,这是非常繁琐的,C++11中通过添加继承构造函数这个新特性完美的解决了这个问题,使得代码更加精简。

    继承构造函数的使用方法是这样的:通过使用using 类名::构造函数名(其实类名和构造函数名是一样的)来声明使用基类的构造函数,这样子类中就可以不定义相同的构造函数了,直接使用基类的构造函数来构造派生类对象。

    #include 
    #include 
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在修改之后的子类中,没有添加任何构造函数,而是添加了using Base::Base;这样就可以在子类中直接继承父类的所有的构造函数,通过他们去构造子类对象了

    另外如果在子类中隐藏了父类中的同名函数,也可以通过using的方式在子类中使用基类中的这些父类函数:

    #include 
    #include 
    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) {}
    
        void func(int i)
        {
            cout << "base class: i = " << i << endl;
        }
        
        void func(int i, string str)
        {
            cout << "base class: i = " << i << ", str = " << str << endl;
        }
    
        int m_i;
        double m_j;
        string m_k;
    };
    
    class Child : public Base
    {
    public:
        using Base::Base;
        using Base::func;
        void func()
        {
            cout << "child class: i'am luffy!!!" << endl;
        }
    };
    
    int main()
    {
        Child c(250);
        c.func();
        c.func(19);
        c.func(19, "luffy");
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    上述示例代码输出的结果为:

    child class: i'am luffy!!!
    base class: i = 19
    base class: i = 19, str = luffy
    
    • 1
    • 2
    • 3

    子类中的func()函数隐藏了基类中的两个func()因此默认情况下通过子类对象只能调用无参的func(),在上面的子类代码中添加了using Base::func;之后,就可以通过子类对象直接调用父类中被隐藏的带参func()函数了。

    需要注意的是,using 关键字引入的基类函数在派生类中并不变成虚函数。如果你需要达到虚函数的效果,可以在基类中将相应的函数声明为虚函数。

  • 相关阅读:
    linux 压缩命令之tar工具的基本使用
    FreeSWITCH ESL C++ 接口程序
    LINUX安装KDC服务
    Redis概述和安装
    DocuWare 文档管理系统Intelligent Indexing(智能索引)、 Forms(表单)和连接到Outlook 功能
    怎么使二层交换机和三层交换机之间用vlan连接各个终端并 ping 通
    支持JDK19虚拟线程的web框架,之五(终篇):兴风作浪的ThreadLocal
    利用完全二叉树的性质,如何创建一个大根堆和一个小根堆?
    思腾云计算
    开源3D激光(视觉)SLAM算法汇总(持续更新)
  • 原文地址:https://blog.csdn.net/f593256/article/details/134382203