【cpluplus教程翻译】重载和模板(Overloads and templates)
重载函数
C++允许两个函数同名,只要参数不同,数目或类型不同都行,就不会编译报重定义的错误
// overloading functions
#include <iostream>
using namespace std;
int operate (int a, int b)
{
return (a*b);
}
double operate (double a, double b)
{
return (a/b);
}
int main ()
{
int x=5,y=2;
double n=5.0,m=2.0;
cout << operate (x,y) << '\n';
cout << operate (n,m) << '\n';
return 0;
}
上面这个例子,两个函数都是operator,一个参数是int,一个是double,编译器通过参数类型可以明白应该调用哪个
这个例子两个函数的行为不一样,一个是乘法,一个是除法,这不是一个好的设计,不过也是完全符合语法规则的
注意只有返回值不同是不能被重载的(本质上函数返回都是放在eax寄存器里?)
函数模板
重载函数的定义可能是完全一样的
// overloaded functions
#include <iostream>
using namespace std;
int sum (int a, int b)
{
return a+b;
}
double sum (double a, double b)
{
return a+b;
}
int main ()
{
cout << sum (10,20) << '\n';
cout << sum (1.0,1.5) << '\n';
return 0;
}
sum虽然被重载了,但是函数体是一样的
sum可能会被很多类型重载,但是函数体都是一样的,因此可以使用函数模板减少代码,语法和函数一致,前面加template关键字,然后用尖括号包括模板参数即可
template <class SomeType>
SomeType sum (SomeType a, SomeType b)
{
return a+b;
}
注意尖括号,和函数的参数列表一样,前面是类型,后面是参数名,用class和typename完全是一样的
上面的例子声明SomeType是一个通用类型,这样就可以在函数体里随便使用,可以是参数类型,也可以是返回值,可以用来声明其他变量,只是表示一个通用的类型
实例化模板是指用一个特定的类型替换模板参数来创造函数,name <template-arguments> (function-arguments),例子```c++
x = sum
int只是一种实例化,实际上就和定义了一个函数差不多
```c++
int sum (int a, int b)
{
return a+b;
}
// function template
#include <iostream>
using namespace std;
template <class T>
T sum (T a, T b)
{
T result;
result = a + b;
return result;
}
int main () {
int i=5, j=6, k;
double f=2.0, g=0.5, h;
k=sum<int>(i,j);
h=sum<double>(f,g);
cout << k << '\n';
cout << h << '\n';
return 0;
}
上面这个例子,我们用了两个模板函数,第一个模板参数是int,第二个是double。
编译器也可以通过类型推导选择需要实例化的版本,因此可以写成下面这个形式
k = sum (i,j);
h = sum (f,g);
如果两个参数的类型不同,编译器没办法自动推导
模板是很有用且通用的特性,可以有多个模板参数(模板本身也是完备的,实现模板元编程,在编译器完成计算,加快速度),还可以使用不是类型的参数
// function templates
#include <iostream>
using namespace std;
template <class T, class U>
bool are_equal (T a, U b)
{
return (a==b);
}
int main ()
{
if (are_equal(10,10.0))
cout << "x and y are equal\n";
else
cout << "x and y are not equal\n";
return 0;
}
自动推导了类型are_equal<int,double>(10,10.0)
这里不会产生歧义,因为数字字面量总是有特定的类型,除非指定了前缀,否则10永远是int,10.0永远是double。
非类型模板参数(Non-type template arguments)
不光可以用class或typename声明模板参数,基本类型也可以(需要是编译器常量,进行替换)
// template arguments
#include <iostream>
using namespace std;
template <class T, int N>
T fixed_multiply (T val)
{
return val * N;
}
int main() {
std::cout << fixed_multiply<int,2>(10) << '\n';
std::cout << fixed_multiply<int,3>(10) << '\n';
}
第二个模板参数是int,就可以一个函数参数差不多,可以直接使用
但是核心不同是:模板参数编译器就确定了,然后才能实例化,生成函数指令,所以一定不能是运行期指定,上面的两次调用实际上调用的是两个函数,两份指令,所以必须是常量
总结
模板和重载本质上是想解决同样的问题,泛型编程,不同的类型如果操作相同,可以用模板实现,不同也可以模板特化或者函数重载。
本质上模板实例化就是进行类型替换,因此替换点需要告诉模板参数类型,且能看到模板定义,所以模板通常以头文件提供,注意非参数类型的使用,最新C++支持string和float
本文来自博客园,作者:xiaoweing,转载请注明原文链接:https://www.cnblogs.com/xiaoweing/p/17434004.html

浙公网安备 33010602011771号