C++ 新特性委托构造和继承构造

#include <iostream>
#include <vector>
#include <list>
/** 委托构造函数作用时调用其他构造函数(目标构造函数)进行初始化,优点是优化代码,看起来精简
 *  在初始化列表中调用构造函数,函数体中调用构造函数会报参数重复定义问题
 *  目标构造函数执行优先与委托构造函数
 */

struct Test
{
    Test(){}; 
    Test(int max)   // 目标构造函数
    {
        this->m_max = max;
    }
    Test(int max, int min) : Test(max)  // 即是委托构造函数,也是目标构造函数
    {
        this->m_min = max > min ? min : 1;
    }
    Test(int max, int min, int mid) : Test(max, min) // 委托构造函数
    {
        this->m_mid = mid > min && mid < max ? mid : 50;
    }

    int m_max;
    int m_min;
    int m_mid;
};

/*
 在初始化列表中使用委托构造函数初始化类成员变量后,不能在初始化列表中再次初始化这个成员变量了
Test(int max, int min):Test(max), m_max(max) // error
 */

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, std::string k) : m_i(i), m_j(j), m_k(k) {}

    void Func(int i)
    {
        std::cout << "Base:"<< i << std::endl;
    }

    void Func(int i, int j)
    {
        std::cout <<"Base:"<< i << "," << j << std::endl;
    }
	void Func1(int i, int j, int k)
	{
		std::cout<< "Base:"<< i << "," << j << "," << k << std::endl;
	}
    int m_i;
    double m_j;
    std::string m_k;
};

// 在C++11之前,子类初始化父类成员,都是在子类构造函数初始化列表中初始化父类成员变量,比较繁琐
class Child : public Base
{
public:
    // 如父类构造函数只有有参构造函数时(有无参默认构造函数,不需要再初始化列表中初始化父类),必须在初始化列表中初始化父类成员变量
    Child(int l, int i) : m_l(l), Base(i) {}
    Child(int l, int i, double j) : m_l(l), Base(i, j) {}
    Child(int l, int i, double j, std::string k) : m_l(l), Base(i, j, k) {}
    int m_l;
};

class Child1 : public Base
{
public:
    // 在子类中可以调用父类的所有构造函数
    using Base::Base;

    // C++11之前可以使用using父类的函数
    using Base::Func;
    void Func()
    {
        std::cout << "child1 Func" << std::endl;
    }
};


void Test1()
{
    // using Base constructor
    Child1 c1(1);   
    std::cout << c1.m_i << std::endl;// 1
    Child1 c2(2, 3);
    std::cout << c2.m_i << "," << c2.m_j << std::endl;// 2,3
    Child1 c3(3, 4, "5");
    std::cout << c3.m_i << "," << c3.m_j << "," << c3.m_k << std::endl;// 3,4,5

    // using Base function
    c1.Func(); // child1 Func
    c1.Func(1); // Base:1
    c1.Func(1, 2);// Base:1,2
    c1.Func1(1, 2, 3);// Base:1,2,3


    // 一般调用父类函数,就是使用父类的对象引用或指针
}

// 若子类中也有自己成员需要初始化,又要使用继承构造函数,则可以
// 用=、{}对子类成员进行就地初始化(C++11开始支持)
struct Child2: public Base
{
    using Base::Base;
    int c=0;
    std::string str{"c++"};
};

void Test2()
{
    Child2 child(1);
    std::cout<<child.c<<","<<child.str<<std::endl; // 0,c++
}

// 委托构造函数注意不能形成环状,否则编译报错
struct DelegateConstruction {
    //DelegateConstruction():DelegateConstruction(1){}
    //DelegateConstruction(int a):DelegateConstruction("b"){}
    //DelegateConstruction(char b):DelegateConstruction(2){}

    int a;
    char b;
};


// 委托构造函数一个很实际应用是创建一个模板构造函数作为目标构造函数
// 通过委托构造函数的委托,构造函数模板被实例化,比罗列不同类型构造函数方便多
// 委托构造函数使得构造函数的泛型编程成为可能
struct DelegateTemplate{
    template<typename T>
    DelegateTemplate(T begin, T end):l(begin, end){} // 模板构造函数作为目标构造函数

    std::vector<int> l;

    DelegateTemplate(std::vector<int> &vec):DelegateTemplate(vec.begin(), vec.end()){}// 委托构造函数
    DelegateTemplate(std::list<int> &l):DelegateTemplate(l.begin(), l.end()){}  // 委托构造函数
};

// 委托构造函数可以捕获到目标构造函数中抛出的异常
struct DelegateException{
    DelegateException():a(1){throw 1;}

    DelegateException(char b) try: DelegateException(){
            this->b = b;
            std::cout<<"a:"<<a<<",b:"<<b<<std::endl; // 目标构造函数抛出异常,委托构造函数体并没有执行
        }catch(int e){
            std::cout<<"except:"<<e<<std::endl; // 1
        }
    
    int a;
    char b;
};
void Test3()
{
    DelegateException d('d');
}
int main()
{
    Test test(5, 1, 3);
    std::cout << test.m_max << "," << test.m_mid << "," << test.m_min << std::endl; // 5,3,1
    Test1();
    Test2();
    Test3();
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值