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

本文深入探讨了泛型编程的概念及其在代码复用中的重要性,通过对比函数重载、公共基类和宏函数的局限性,引出了模板作为解决代码复用问题的有效手段。详细解析了函数模板的格式、实例化过程及参数推演,展示了如何利用模板提高代码的通用性和维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值