学习了博主的《漫谈继承技术》系列博文之后,相信大家都有所收获吧!这次博主将和大家一起探讨 《灵活而奇特的C++语言特性》 ,主要包括引用、常量(const)、常量表达式(constexpr)、静态(static)、外部(expert)、类型定义(typedef)、类型别名(aliases)、类型转换、作用域解析、统一初始化、显示转换运算符、特性(attribute)、用户自定义文本、头文件、可变长度参数列表和预处理器宏。尽管这个知识清单显得有点凌乱,但是这些话题都是博主经过精心挑选,是容易混淆的语言特性。本篇我们来学习一下typedef和类型别名(aliases)的概念以及使用场景,增进大家对《灵活而奇特的C++语言特性》的理解。
typedef
typedef为已有的类型声明提供一个新的名称。可以将typedef看成已有类型声明的同义词,typedef不会创建新的类型。typedef的最常见用法是当实际类型的声明过于复杂时,提供易于管理的名称,这一情形通常出现在函数指针和模板中。当然,typedef还可以包括作用域限定符。下面咱们来举个栗子吧。
#include <iostream>
#include <string>
#include <vector>
using namespacestd;
//使用typedef给int指针取别名
typedef int*IntPtr;
//使用typedef给string矢量取别名
typedef std::vector<std::string> StringVector;
//使用typedef给函数指针类型取别名
typedef int(*FuncPtr)(std::initializer_list<int>list);
//初始化列表简化了参数数量可变函数的编写
int Sum(initializer_list<int>list)
{
intresult = 0;
//用for each累加列表中的值
foreach(constint&var in list)
{
result+= var;
}
returnresult;
}
void print(StringVector&vStr)
{
cout<< "vStr = {";
for(constauto&var : vStr)
{
cout<< var << ", ";
}
cout<< "}" << endl;
}
int main(intargc,char**argv)
{
//使用类型别名定义int指针变量
IntPtr nPtr = new int(10);
cout<< "*nPtr: "<< *nPtr << endl;
//使用类型别名定义string矢量
StringVector vStr;
//调整数组大小为2,保证能保存两个数据元素
vStr.reserve(2);
vStr.push_back("typedef");
vStr.push_back("std::vector<std::string>");
//调用函数输出数组中所有元素
print(vStr);
//使用类型别名定义函数指针变量
FuncPtr fPtr = Sum;
//通过函数指针变量调用函数
autoresult = fPtr({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
cout<< "result:" << result << endl;
//释放堆上空间
deletenPtr;
//避免野指针
nPtr = nullptr;
return0;
}
程序运行结果:
可能有的人还是觉typedef在定义函数指针时,有点麻烦,不怎么好理解。没有关系,我们还有跟简便的方法来实现取别名的目的,而且还很容易理解。那究竟是什么呢?就是我们之前在《漫谈继承技术》系列博文中讲到的using。如果忘记了,那就把这篇博文学习完后回去再复习回顾一下!下面我们一起来探讨一下using的高级用法。我们可以把上例转换为以下实例。
#include <iostream>
#include <string>
#include <vector>
using namespacestd;
//使用using给int指针取别名
using IntPtr= int*;
//使用using给string矢量取别名
using StringVector= std::vector<std::string>;
//使用using给函数指针类型取别名
using FuncPtr= int(*)(std::initializer_list<int>list);
//初始化列表简化了参数数量可变函数的编写
int Sum(initializer_list<int>list)
{
intresult = 0;
//用for each累加列表中的值
foreach(constint&var in list)
{
result += var;
}
returnresult;
}
void print(StringVector&vStr)
{
cout<< "vStr = {";
for(constauto&var : vStr)
{
cout<< var << ", ";
}
cout<< "}" << endl;
}
int main(intargc,char**argv)
{
//使用类型别名定义int指针变量
IntPtr nPtr = new int(10);
cout<< "*nPtr: "<< *nPtr << endl;
//使用类型别名定义string矢量
StringVector vStr;
//调整数组大小为2,保证能保存两个数据元素
vStr.reserve(2);
vStr.push_back("typedef");
vStr.push_back("std::vector<std::string>");
//调用函数输出数组中所有元素
print(vStr);
//使用类型别名定义函数指针变量
FuncPtr fPtr = Sum;
//通过函数指针变量调用函数
autoresult = fPtr({1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
cout<< "result:" << result << endl;
//释放堆上空间
deletenPtr;
//避免野指针
nPtr = nullptr;
return0;
}
程序运行结果:
通过上例的学习,我们发现:当typedef变得复杂时(例如前面列举的typedef用于函数指针和模板的情况),类型别名特性特别有用。关于typedef和别名(using)我们就探讨到这里了。当然,using的用法不仅仅在于别名,还可以在继承技术方面大显身手,如果想了解using的更多用法,请关注博主《漫谈继承技术》系列博文,我们将会在那里继续探讨using的用法。
如果想了解更多关于C++语言特性相关的知识,请关注博主《灵活而奇特的C++语言特性》系列博文,相信你能够在那里寻找到更多有助你快速成长和加深你对C++语言特性相关的知识和一些特性的理解和掌握。当然,如果你想了解关于继承方面的技术,请关注博主《漫谈继承技术》系列博文。