Delegating Constructor(委托构造函数)各版本异同

学习内容

本节学习委托构造函数在各版本的异同,后续请关注 学习C++11/14/17/20/23关键词版本更替 ,将持续更新~~

委托构造函数是在类的构造初始化列表中,不直接初始化类的成员变量,而是调用同一个类的其他构造函数,由被调用的构造函数完成成员初始化,当前构造函数仅需补充额外的初始化逻辑,或无额外逻辑

委托构造函数是C++11新引入特性,解决了传统C++构造函数之间代码冗余、初始化逻辑重复编写问题,允许同一个类的一个构造函数调用该类的另一个构造函数,实现初始化逻辑的复用

cpp 复制代码
//C++11前
class Test
{
public:
	Test(): string("") , used(false),num(0) , id(0){}
	Test(string n) :string(n)  , used(false),num(0) , id(0){}
	Test(string n , bool u) :string(n)  , used(u),num(0) , id(0){}
	//....此处省略其余构造函数,皆为重复代码
private:
	int id;
	int num;
	bool used;
	string name;
	};

委托构造函数核心价值:将公共初始化逻辑抽离到一个核心构造函数中,其他构造函数通过委托复用该逻辑

语法规则

委托构造函数语法集中在构造函数的初始化列表

cpp 复制代码
class Test
{
public:
	Test(): Test("Alice"){}
	Test(string n) :Test( n , false) {}
	Test(string n , bool u) :Test(n , u , 0 , 0 ){ }
private:
	int id;
	int num;
	bool used;
	string name;
	};

定义对象时,根据构造函数的参数来匹配对应的构造函数,禁止循环委托(同一类中构造函数相互调用)

cpp 复制代码
Test test();  
Test test1 ("Bob");

委托函数写在初始化列表中,不能同时初始化成员变量和委托构造函数

cpp 复制代码
//禁止以下写法 ,不能同时写
Test(string n , bool u ) : id(0) , num(0) , Test ( n,u ){}  

支持多层委托,但是层数越多导致逻辑过长,可读性降低

委托构造函数必须是本类的,不能委托父类构造函数

被委托构造函数执行优先级更高

cpp 复制代码
class Person
{
public:
	Person ( string name_ , int age_) : name(name_) , age(age_){ cout<< "优先级最高,核心函数" <<endl;  }
	Person (string name_) : Person(name_ ,12) { cout  << "优先级排名第二" << endl; }
	Person() : Person("Invalid") { cout << " 优先级第三 " << endl; };
private:
	string name;
	int age;
}

Person p;  //调用无参构造函数 

注意

成员变量已由委托构造函数初始化完成,若在委托函数体中再次赋值,则会覆盖原有值,导致初始化逻辑混乱

cpp 复制代码
class Test
{
public:
	A(int a ): age( a ){}
	A() : A(10){ age = 12; }  //原值被覆盖为12,将逻辑写到核心构造里面可解决
private:
	int age;
}

避免循环委托,编译期会检测,确定委托构造函数的终点是非委托核心构造函数

在继承体系中,委托构造不影响父类构造,子类的委托构造函数仅辅助子类内部的构造委托,父类的构造函数仍需在子类构造函数的初始化列表中显式调用,二者互不干扰

cpp 复制代码
class Base
{
public:
	Base(int a ) : age(a){}
private:
	int age;
}

class Derived : puhlic Base
{
public:
	Derived(int a, int d) : Base(b),data(d){}
	Derived(int d) : Derived(10,d){}
private:
	int data;
}

C++11,核心特性引入

初次引入委托构造函数,并完整定义该特性所有核心规则,包括:

  • 初始化列表中委托同一个类构造函数语法
  • 委托为初始化列表唯一项、禁止同时初始化成员变量约束
  • 禁止循环委托、支持多层委托
  • 被委托构造函数优先于委托构造函数体执行
  • 仅适用于类内部构造函数委托、不影响父类构造调用边界

C++14无优化,无修改,无变更

C++17 兼容性增强,适配类内静态断言与内联变量

新增类内静态断言(static_assert)和内联变量(inline)特性,可与委托构造函数无缝配合,提升代码健壮性

类内static_assert: 可在类中直接添加静态断言,校验委托构造参数合法性

类内内联变量: 类的静态成员可直接在类内初始化;委托构造函数可直接使用初始化完成的静态变量

cpp 复制代码
class Test
{
public:
	Test(int a) : age(a)
	{
		static_assert( is_integral_v<int> , "参数必须为正整数");
	}

	Test() : Test( staValue){}

private:
	int age;
	inline static staValue = 12;  //内联静态成员变量直接初始化
}

C++20 编译期支持constexpr委托构造

允许将委托构造函数标记为constexpr,支持编译期完成对象的委托初始化,其中:

被委托的构造函数也必须是constexpr

原有委托语法、执行顺序、约束规则不变

编译期初始化的对象,其成员变量为编译期常量,可用于模板参数、static_assert等

cpp 复制代码
class Person
{
public:
	constexpr Person ( string name_ , int age_) : name(name_) , age(age_){ cout<< "优先级最高,核心函数" <<endl;  }
	constexpr Person (string name_) : Person(name_ ,12) { cout  << "优先级排名第二" << endl; }
	constexpr Person() : Person("Invalid") { cout << " 优先级第三 " << endl; };
private:
	string name;
	int age;
}

constexpr  Person p;
constexpr Person p1("Ana");

Concepts编译期参数约束,与委托构造函数配合,为构造函数添加编译期强类型约束,替代传统static_assert

cpp 复制代码
template< class T>
concept NonNegativeInt = integral<T> && !signed<T>;

class Test
{
public:
	Test(NonNegativeInt auto a) : age(9){}
	Test() : Test( staValue){}

private:
	int age;
}

Test t(-2);  //error , -1不符合强类型约束

C++23 细节完成

适配显式对象构造(std::construct_at):使用std::construct_at在指定内存地址构造对象时,支持调用委托构造函数

相关推荐
晓131311 小时前
第七章 【C语言篇:文件】 文件全面解析
linux·c语言·开发语言
小镇敲码人11 小时前
探索华为CANN框架中的ACL仓库
c++·python·华为·acl·cann
梵刹古音11 小时前
【C语言】 指针基础与定义
c语言·开发语言·算法
Ekehlaft11 小时前
这款国产 AI,让 Python 小白也能玩转编程
开发语言·人工智能·python·ai·aipy
rit843249911 小时前
MATLAB中Teager能量算子提取与解调信号的实现
开发语言·matlab
开源技术11 小时前
Python GeoPandas基础知识:地图、投影和空间连接
开发语言·ide·python
Cult Of11 小时前
Alicea Wind的个人网站开发日志(2)
开发语言·python·vue
我找到地球的支点啦11 小时前
通信扩展——扩频技术(超级详细,附带Matlab代码)
开发语言·matlab
liu****12 小时前
2.深入浅出理解虚拟化与容器化(含Docker实操全解析)
运维·c++·docker·容器·虚拟化技术