电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
适合具备 C 语言基础的 C++ 教程(十一)
分 享
扫描二维码分享
适合具备 C 语言基础的 C++ 教程(十一)
C++
wenzi 嵌入式软件
关注
发布时间: 2021-03-26
丨
阅读: 283
# 前言 在上一则教程中,着重叙述了抽象类界面以及函数模板的相关内容,在本节教程中,笔者将详细阐述函数模板重载的概念,将从具体的实例中阐述函数模板重载要注意的内容。 ## 函数模板重载 函数重载是在教程最开始就阐述过的概念,那么函数模板重载又该如何理解呢,我们以上一节教程中比大小的函数模板为背景,具体阐述函数模板重载的概念,代码如下所示: ```cpp template
const T& mymax(const T& a, const T& b) { cout<<"1: "<<__PRETTY_FUNCTION__<
const T& mymax(T& a, T& b) { cout<<"2: "<<__PRETTY_FUNCTION__<
const int` - 第二个模板函数:`int -> int` - 第三个普通函数:`int -> int ` - 所以,第二个模板函数和第三个普通函数并列**第一**,第一个模板函数排**第二** - 3、选择更加匹配的候选函数 - 如果匹配度相同 - 优先选择普通函数 - 对于多个模板函数,选择一个更加**特化**的(特化后续解释) - 否则,代码出现二义性 - 所以,根据第二得到的结果是第二个模板函数和第三个普通函数并列**第一**,根据第三条原则,优先选择普通函数,因此,在这里调用的是普通函数。 ### 二义性例子 接下来,我们来看一个二义性的例子,首先给出模板函数的代码,代码如下所示: ```cpp template
const T& mymax(const T& a, const T& b) { cout<<"1: "<<__PRETTY_FUNCTION__<
const T& mymax(T& a, T& b) { cout<<"2: "<<__PRETTY_FUNCTION__<
const T mymax(T a, T b) { cout<<"4: "<<__PRETTY_FUNCTION__<
const int` - 第二个模板函数:`int -> int` - 第三个模板函数:`int -> int` - 3、选择更加匹配的候选函数 - 由`2、`可知,第二个和第三个匹配度一样,所以当前这个程序也就造成了**二义性**的错误 下面是代码编译的结果: ![image-20210224195510811](https://gitee.com/wenzi_D/images4mk/raw/master/image-20210224195510811.png) ### 参数为指针 接下来,叙述一个实参为指针的一个例子,首先先看模板函数和普通函数,代码如下所示: ```cpp template
const T& mymax(const T& a, const T& b) { cout<<"1: "<<__PRETTY_FUNCTION__<
const T& mymax(T& a, T& b) { cout<<"2: "<<__PRETTY_FUNCTION__<
const T mymax(T * a, T* b) { cout<<"4: "<<__PRETTY_FUNCTION__<
const int*` - 第二个:`int* -> int*` - 第四个:`int* -> int*` - 3、根据参数,进行排序: - 最匹配的是:第二个和第四个 - 4、它们都是模板函数,选出“更特化”的,更特化的意思也就是说参数匹配**更加特殊**,**更加具体**,**更加细化** 我们这个时候,回过头来看第二个模板函数,`mymax(T& a, T& b)`,对于这个模板函数来说,它存在两种情况: - 当`T = int`的时候,那么也就是`mymax(int &,int &)`; - 当`T= int *`的时候,那么也就是`mymax(int *&, int *&)` 我们再来看第四个模板函数,`mymax(T*, T*)`,参数只能是指针,也就是说当`T = int`的时候,也就是 `mymax(int*, int*)`,通过这里的分析,我们可以看出对于第二个模板函数和第四个模板函数来讲,第四个模板函数更加具体,也就是更加**特化**,所以上述是调用的第四个模板函数。 ### const int * 接下来,我们看一个由`int* -> const int*`的例子,首先,依旧是先看模板函数,代码如下所示: ```cpp template
const T& mymax(const T& a, const T& b) { cout<<"1: "<<__PRETTY_FUNCTION__<
const T mymax(const T * a, const T* b) { cout<<"2: "<<__PRETTY_FUNCTION__<
const int *&` - 第二个模板函数:`int* -> const int*` - 3、根据参数,进行匹配: - 由`2、`的结果可知,两个都是匹配的 既然两个都是匹配的,那要如何进行选取呢?首先额外补充一个知识点: > `const int *p`,遇到指针的时候,都是从右往左读,遇见`p`就读成`p is a`,遇见`*`就读成`pointer to`,那么这条语句也就翻译成这样:`p is a pointer to const int`,也就是说 `p`指向的对象是不可修改的 我们这个时候,来看第二个模板函数,对照其推导出来的模板函数,`mymax(const int*, const int*)`,也就是说传进去的实参所指向的内容是不可变的。 此时,我们再来看第一个模板函数,其模板函数是这样的:`const T& mymax(const T& a, const T& b)`,而推导的模板函数实际上也就是说`T = int *`,所以它的形参实际上应该是这样的:`const (int*)&`,那这么说来,`p`是常量引用,`p`无法修改,但是`p`指向的对象是可修改的。 回到我们的代码上去,我们传到函数里面的两个实参是可以修改的,所以这里应该选择第一个模板函数进行调用,下面是代码执行的结果: ![image-20210224210604846](https://gitee.com/wenzi_D/images4mk/raw/master/image-20210224210604846.png) > 虽然调用的是第一个模板函数,编译没有出错,但是实际上这里函数运行结果并非我们想要,它是比较的两个传进去的实参的地址的大小,返回的也是地址的大小,并非值的大小。 > ## 类模板 在首次介绍模板的时候,我们也指出,除了有函数模板以外还具有类模板,接下来,笔者将对类模板的相关概念进行阐述。当我们碰到相似的函数的时候,会想到使用函数模板来解决问题;自然,如果我们碰到有相似的类的时候,也可以使用类模板来解决问题,下面的代码就是一个类模板: ```cpp template
class AAA { private: T t; public: void test_func(const T &t); void print(void); }; ``` 上述就是一个类模板的写法,上述只是类的一个声明,如果要实现模板类里面的成员函数,则需要使用如下所示的代码: ```cpp template
void AAA
::test_func(const T &t) { this->t = t; } template
void AAA
::print(void) { cout << t << endl; } ``` 基于上述模板类,我们就可以编写主函数了,代码如下所示: ```cpp int main(int argc, char **argv) { AAA
a; a.test_func(1); a.print(); AAA
b; b.test_func(1.23); b.print(); return 0; } ``` 代码运行结果如下所示: ![image-20210224224823979](https://gitee.com/wenzi_D/images4mk/raw/master/image-20210224224823979.png) ## 类重载 我们知道函数是可以重载的,那么其实类也是可以进行重载的,类重载也可以称之为是**定做**,在上述代码的基础上,我们来定做类,代码如下所示: ```cpp template<> class AAA
{ public: void test_func_int(const int &t) { cout << t << endl; } void print_int(void); }; void AAA
::print_int(void) { cout << "for test" << endl; } ``` 在定做了类之后,我们来看主函数的代码: ```cpp int main(int argc, char** argv) { A
a; a.test_func_int(1); a.print_int(); return 0; } ``` 代码运行结果如下所示: ![image-20210224230451701](https://gitee.com/wenzi_D/images4mk/raw/master/image-20210224230451701.png) > 注:在上述介绍的函数模板和类模板,虽然在介绍的时候,都是在 `.cpp`中实现的,但是在实际的项目当中,其实基本都是写在`.h`文件中的,因为对于模板来说,它只是一些编译指令,一般都是将其放在头文件中供其他代码引用。 # 小结 上述便是本期分享的内容,本期涉及到的代码可以通过百度云链接的方式获取到: > 链接:https://pan.baidu.com/s/1p-GU0_5aa46lvaB2AdHemA > 提取码:1sxd
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
0
)
wenzi 嵌入式软件
关注
评论
(0)
登录后可评论,请
登录
或
注册
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交