IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++模版:深入使用函数模版 -> 正文阅读

[C++知识库]C++模版:深入使用函数模版

上文函数模版初探介绍了函数模版的基本使用,本文深入探讨函数模版。

函数模版参数的类型转换

函数模版有多个同类型的形参,使用过程中会碰到类型转换问题。

下面是一个加法函数模版:

template <typename  T>
T add2(T a, T b) {
  std::cout << "T add2(T a, T b)" 
    				<< std::endl;  
  return a + b;
}

使用隐式实例化,2个实参的类型必须相同,否则编译出错No matching function for call to add

使用显示实例化,2个实参的类型可以不同,但是会发生隐式类型转换。

void test1() {
    // 2个实参类型相同,可以使用隐式实例化
    int a1 = 1;
    int b1 = 2;
    add2(a1, b1);
    
  	// 2个实参类型不同,不能使用隐式实例化
    int a2 = 1;
    short b2 = 1;
    // No matching function for call to 'add2'
    // add2(a2, b2); 
  
    // 显示实例化, short被隐式转换成int
    add2<int>(a2, b2);      
}

函数模版重载

函数模版跟普通函数一样支持重载。函数参数列表中,参数不一定是泛型,也可以是具体的类型。

比如,加法函数模版中,增加3个数相加的函数模版。第3个参数,可以是泛型,也可以是具体的double类型。

template <typename  T>
T add2(T a, T b, T c) {
    std::cout << "T add2(T a, T b, T c)" 
      				<< std::endl;
    return a + b + c;
}

template <typename  T>
T add2(T a, T b, double c) {
    std::cout << "T add2(T a, T b, double c)" 
      				<< std::endl;
    return a + b + c;
}

函数模版的局限性及解决方案

函数模版很可能无法处理某些类型。

比如下面的例子,如果T是自定义类,则无法正常运行。

template <typename  T>
bool equal(T &a, T &b) {
    return a == b;
}

class FTPerson {
	public:
    int age;
};

一种解决方案是,为特定类型提供具体化的函数定义,这称之为显示具体化(explicit specialization)。

显示具体化的原型和定义:

template<> bool equal<FTPerson>(FTPerson &p1, FTPerson &p2);

template<> bool equal<FTPerson>(FTPerson &p1, FTPerson &p2) {
    std::cout << "equal(FTPerson &p1, FTPerson &p2)" 
      				<< std::endl;
    return p1.age == p2.age;
}

编译器会选择最合适的显示具体化函数。

void test3() {
    FTPerson p1;
    FTPerson p2;
    
    equal(p1, p2);	// 调用的是具体化函数
}

编译器选择哪个函数

调用函数时,如果有多个函数或者模版符合要求:

  • 函数名称相同
  • 实参与形参个数相同,并且类型相同或者可以隐式转换

编译器必须选择一个最佳的函数。以下匹配规则,优先级从高到低:

  • 函数完全匹配,按照下面优先级匹配
    • 普通函数
    • 模版的显示具体化函数
    • 函数模版
  • 提升转换,比如char转换为intfloat转换为double
  • 标准转换,比如char转换为floatint转换为charlong转换为double

下面是5个函数或者模版,编号是1到5。使用不同编号的函数和测试用例,验证匹配规则。

// #1 普通函数
void eat(int a) {
    std::cout << "eat(int a)" 
      				<< std::endl;
}

// #2 普通函数
void eat(char a) {
    std::cout << "eat(char a))" 
      				<< std::endl;
}

// #3 普通函数
void eat(float a) {
    std::cout << "eat(float a)" 
      				<< std::endl;
}

// #4 函数模版
template<typename T> void eat(T a) {
    std::cout << "template void eat(T a)" 
      				<< std::endl;
}

// #5 模版的显示具体化函数
template<> void eat(int a) {
    std::cout << "template void eat(int a)" 
      				<< std::endl;
}

测试用例1:

void test4() {
    int a = 1;
    eat(a);
}

下面情况都是完全匹配,输出结果如下:

  • 使用#1#4#5,则编译器选择普通函数#1,输出日志eat(int a)
  • 使用#4#5,则编译器选择显示具体化函数#5,输出日志template void eat(int a)

下面情况是完全匹配优先级高于提升转换或者标准转换,输出结果如下:

  • 使用#2#3#4,则编译器选择函数模版#4,输出日志template void eat(T a)

测试用例2:

void test5() {
    char a = 'a';
    eat(a);
}

下面情况是提升转换优先级高于标准转换,输出结果如下:

  • 使用#1#3,则编译器选择提升转换#1,输出日志eat(int a)

总结

  • 使用函数模版,要注意隐式类型转换
  • 函数模版支持重载
  • 函数模版不能处理所有的类型,可以为特定类型提供具体化的函数定义
  • 如果多个函数或者模版符合要求,编译器会根据优先级,选择最合适的函数

阅读原文

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-28 00:06:47  更:2021-09-28 00:07:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 4:04:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计