#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;
}
C++ 新特性委托构造和继承构造
于 2022-04-07 23:00:23 首次发布