01~C++ 函数模板

模板设计目的:尽量减少代码的编辑量/冗余结构

一 C 的大小比较

1. C函数实现

为了实现比对大小的算法,写了三个函数 ,岂不是很啰嗦?

//max.c
#include <stdio.h>
#include <stdbool.h>  // for C bool type 
bool max_int(int a, int b){
	return a > b ? true : false;
}
bool max_double (double a, double b) {
	return a > b ? true : false;
}
bool max_pint (int *a , int *b) {
	return *a > *b ? true : false;
}

int main(void) {
int a = 99;
int b = 100;
printf("int a : b %d\n",max_int(100,99)); //true
printf("double c : d %d\n",max_double(9.9,10.10)); //false
printf("pint e : f %d\n", max_pint(&a, &b)); //false
return 0;
}

2. C 宏定义表达式

C 宏 :MAX 精简了上面的冗余代码,但是对于第三次调用MAX(&a,&b)调用因为形式上展开后相当于在做地址的大小比较,展开 形如 ((&a > &b) ? true : false),和我的初衷比对 *a > *b ,这个设计存在重大bug,原因在于宏展开时不会检查形参类型,而是简单的进行文本展开

//max.c
#include <stdio.h>
#include <stdbool.h>  // for C bool type 
#define MAX(A,B) ((A) > (B) ? true : false) 
int main(void) {
int a = 99;
int b = 100;
printf("int a : b %d\n",MAX(100,99)); //true
printf("double c : d %d\n",MAX(9.9,10.10)); //false
printf("pint e : f %d\n", MAX(&a, &b)); //? 
return 0;
}

3. C宏定义函数

规避风险,使用宏 实现不同算法接口(做到了代码尽量精简,存在使用不到的代码也会被 静态编译到可执行文件中的问题)

实际使用中还是要顾及针对不同类型 需要认为判定选用函数名称
如:MAX_int, MAX_double , MAX_pint … ,存在一定的不便

//max.c
#include <stdio.h>
#include <stdbool.h>  // for C bool type 
#define MAX(T)  \
bool MAX_##T (T a , T b) { \
return a > b ? true : false; \
}

MAX(int)
MAX(double)

//对于指针需要 特殊实现
bool MAX_pint(int *a , int *b) { 
	return *a > *b ? true : false; 
}

int main(void) {
int a = 99;
int b = 100;
printf("int a : b %d\n",MAX_int(100,99)); //true
printf("double c : d %d\n",MAX_double(9.9,10.10)); //false
printf("pint e : f %d\n", MAX_pint(&a, &b)); //false
return 0;
}

4. C 宏定义-一个接近模板的实现

//max.c
#include <stdio.h>
#include <stdbool.h>  // for C bool type 
#define MAX(T)  \
bool MAX_##T (T a , T b) { \
return a > b ? true : false; \
}

MAX(int)
MAX(double)

//对于指针需要 特殊实现
bool MAX_pint(int *a , int *b) { 
	return *a > *b ? true : false; 
}
#define max(T) MAX_##T

int main(void) {
int a = 99;
int b = 100;
printf("int a : b %d\n",max(int)(100,99)); //true
printf("double c : d %d\n",max(double)(9.9,10.10)); //false
printf("pint e : f %d\n", max(pint)(&a, &b)); //false
return 0;
}

二 C++ 函数模板

1. 函数模板 替代C宏实现

其设计形式和使用形式相对C语言宏的版本就简单很多

#include <iostream>
#include <cstdio>

template <typename T>
bool max(T a , T b) {
	return a > b ? true : false;
}
//模板重载
template <typename T>
bool max(T *a , T *b) {
	return *a > *b ? true : false;
}

//摸板特化/具体化
template <>
bool max(int a ,  int b) {
	using namespace std;
	cout <<"max int Always return false" <<endl;
	return false;
}
template <>
bool max(double a ,  double b) {
	using namespace std;
	cout <<"max double Always return false" <<endl;
	return false;
}

//非模板函数
bool max(double a , double b) {
	using namespace std;
	cout <<"max double Always return true" << endl;
	return true;
}

//优先级 非模板 > 模板特化 > 普通模板

int main(void) {
using namespace std;

int a = 99;
int b = 100;
printf("int a : b %d\n",::max<int>(100,99)); //具体化  always false
printf("double c : d %d\n",::max<double>(9.9,10.10)); //显示调用模板,always false
printf("pint e : f %d\n", ::max<int *>(&a, &b)); //false 通用模板重载版本

//::max ,匿名作用域,避免同 std::max 引用冲突, max(a,b), 编译器会做隐式类型推断
cout << ::max(100, 99) << endl; //具体化 int
cout << ::max(9.9, 10.10) << endl; //非模板函数
cout << ::max(&a,  &b) << endl;//指针版本
return 0;
}

/*
Log:
max int Always return false
int a : b 0
max double Always return false
double c : d 0
pint e : f 0
max int Always return false
0
max double Always return true
1
0
*/

三 重载解析

以上示例代码我们看到一个事实,通用模板、重载模板、模板特化、非模板函数都可以为调用者提供实现的接口——这对于习惯于C编程来说,需要C++使用者判断究竟调用者会匹配哪一个版本,着实痛苦。

C++ 在函数调用时,编译器决定选用哪一个实现的过程称为 重载解析
优先级 依次为非模板函数 模板特化 通用模板

读者可以参考C++ primer plus V6 8.5.5 一节

方便查表与记忆,具体如下:

调用时如下:
may('B');

备选函数与模板如下:
void may(int); #1
float may(float ,  float = 3); #2
void may(char); #3
char * may(char *); #4
char may(const char &); #5
template <typename T> void may(const T&); #6
template <typename T> void may (T *); #7

第一步,筛选函数名称为may并且有一个参数的函数,见 #1 ~ #7
第二部,选择匹配的函数列表
匹配类型从优到差依次分为
完全匹配 出现多个完全匹配是错误,编译不通过
提升转换 char 转换为int float 转换为double
标准转换 int 转换为short,char,long转换为double
用户转换 用户定义的转换

完全匹配示例:
void recycle (int); #1
void recycle (int const); #2
void recycle (int &); #3
void recycle (int const &); #4

完全匹配未必一定出错
#3 和#4 一起并不会出错(实际上发生重载)
#1 和 #2 一起会出错
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值