C++实现一个通用的加法函数

1. 使用函数重载

【缺陷】

只要有新类型出现,就要重新添加对应函数

除类型外,所有函数的函数体都相同,代码的复用率不高

如果函数只是返回值类型不同,函数重载不能解决

一个方法有问题,所有的方法都有问题,不好维护

2. 使用公共基类  

【缺陷】 

 -借助公共基类来编写通用代码,将失去类型检查的优点

  -对于以后实现的许多类,都必须继承自某个特定的基类,代码维护更加困难

3. 使用宏函数  

【缺陷】

不是函数,不进行类型检测,安全性不高,表达式复杂容易出错

那还有什么其他方式吗? 能否将写代码的规则告诉编译器,让编译器来实现呢?、

4. 泛型编程

编写与类型无关的逻辑代码,是代码复用的一种手段。模板是泛型编程的基础 

函数模板

1. 概念  函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本2. 函数模板格式

template  </typename t1, typename t2,......,class tn>

返回值类型 函数名(参数列表(参数如果有多个,每一个前都要加 typename 或 class, 用逗号隔开)){}

template<typename T>
T Add(const T& left, const T& right)
{
	return left + right;
}

注意:typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替typename)建议尽量使用typename

函数模板还可以被定义为inline类型的:

template<class T>
inline T Add(const T& left, const T& right)
{
 return left + right;
} 

注意:inline关键字必须放在模板形参表之后,返回值之前,不能放在template之前。

3. 函数模板实例化&参数推演  

模板是一个蓝图,它本身不是类或者函数,编译器用模板产生指定的类或者函数的特定类型版本,产生模板特定类型的过程称为函数模板实例化

#include<iostream>
using namespace std;

template<typename T>//相当于声明了 T 这样一个类型

inline T Add(const T& left, const T& right)
{
	cout << typeid(left).name() << endl;
	return left + right;
}

int main()
{
	//模板函数的隐式实例化(需要根据参数的类型去推演 T 的类型)
	Add(1, 2);
	Add(1.0, 2.0);
	Add('1', '2');
	//Add(1, '1');//报错: 模板 T 类型不明确
	//模板函数的显式实例化,已经明确指定了 T 的类型
	Add<int>(1, '1');//相当于明确指定了模板里面的 T 为 int,会把字符类型'1'转换为 int 类型的 1
 	return 0;
}

输出结果:

真正意义上的 Add 函数的原型

int ---> Add<int>

double--->Add<double>

char--->Add<char>

注意:模板函数的编译分两个阶段

实例化之前,检查模板代码本身,是否出现简单语法错误,如:模板参数列表少了 typename

在实例化后,检查模板生成的代码,是否所有的调用都有效,如:实例化类型不支持某些函数调用

从函数实参确定模板形参类型和值的过程称为模板实参推演,多个类型形参的实参必须完全匹配

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章