曲径通幽论坛
标题: 通用函数(模板函数) [打印本页]
作者: beyes 时间: 2011-9-3 20:36
标题: 通用函数(模板函数)
模板可以用来创建通用函数和通用类。顾名思义或通用类,通用函数可以将一个函数或类应用于几种不同类型的数据,而不需要显式地再函数中对每种类型的数据做特定的处理。
template 是用来定义通用函数的关键字。我们可以使用 template 来创建一个模板,或者说是一个框架,并在在这个模板(框架)中定义函数的功能,而编译器则会根据实际使用的数据类型来完成整个函数的调用。定义模板函数的通用形式如下:
[C++] 纯文本查看 复制代码
template <class Ttype> ret-type func-name(parameter list)
{
//函数体
}
在上面定义中,Ttype 是一个占位符,它代表函数使用的数据类型,占位符名字可被用在函数的定义中,但是它也仅仅就是个占位符而已,编译器在创建一个具体的函数时将用实际的数据类型来替换它。
在传统用法中,template 声明中的通用类型通常是使用关键字 class 来指定,但也可以使用关键字 typename 。
下面程序示例一个通用函数的声明及用法(该函数用来交换两个变量的值):
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;
template <class X> void swapargs(X &a, X &b)
{
X temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int i = 10, j = 20;
double x = 10, y = 23.3;
char a = 'x', b = 'z';
cout << "Original i, j: " << i << ' ' << j << endl;
cout << "Original x, y: " << x << ' ' << y << endl;
cout << "Original a, b: " << a << ' ' << b << endl;
swapargs(i, j);
swapargs(x, y);
swapargs(a, b);
cout << "Swapped i, j: " << i << ' ' << j << endl;
cout << "Swapped x, y: " << x << ' ' << y << endl;
cout << "Swapped a, b: " << a << ' ' << b << endl;
return 0;
}
运行输出:$ ./genfunc
Original i, j: 10 20
Original x, y: 10 23.3
Original a, b: x z
Swapped i, j: 20 10
Swapped x, y: 23.3 10
Swapped a, b: z x
通用函数也称为模板函数。当编译器创建模板函数的某个特定版本时,这个函数被称为特例函数(specialization)。常见特例函数的过程被称为实例化模板函数,换句话说,特例函数是模板函数的一个特例实现。
由于在 C++ 中行结束符并不被认为是一条语句的结束,所以上面例子中通用函数的声明也可以声明:
[C++] 纯文本查看 复制代码
template <class X>
void swapargs(X &a, X &b)
{
X temp;
temp = a;
a = b;
b = temp;
}
如果使用上面的定义形式,那么需要注意的是 template 语句和通用函数的定义开始之间不能有任何其他任何的语句,如:template <class X>
int i = 0; //错误!
void swapargs(X &a, X &b)
上面例子中的模板函数里只包含了一个通用数据类型,但也允许包含多个,在使用多个通用数据类型时,它们之间要用逗号分隔开来。下面程序创建了一个模板函数,该函数带有两个通用的数据类型:
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;
template <class type1, class type2>
void myfunc(type1 x, type2 y)
{
cout << x << ' ' << y << endl;
}
int main()
{
myfunc(10, "hello world");
myfunc("are you ok", 360);
return 0;
}
运行输出:$ ./twogen
10 hello world
are you ok 360
在上面示例中,当编译器在 main() 中创建第一个 myfunc() 的特定实例时,编译器会使 int 和 char* 来替代占位符 type1 和 type2 ,而第 2 个特定实例则是用 char * 和 double 型来替代 type1 和 type2 。
作者: beyes 时间: 2011-9-3 21:49
标题: 重载函数模板
函数模板本身也可以被重载。比如可以创建另外一个函数模板,其参数不同于原来的函数模板。
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;
template <class X> void f(X a)
{
cout << "Inside f(X, a)\\n";
}
template <class X, class Y> void f(X a, Y b)
{
cout << "Inside f(X a, Y b)\\n";
}
int main()
{
f(10); //调用函数f(X)
f(10, 20); //调用函数 f(X,Y)
return 0;
}
运行输出:$ ./reltem2
Inside f(X, a)
Inside f(X a, Y b)
作者: beyes 时间: 2011-9-3 22:41
标题: 显式重载通用函数
我们也可以显式地重载通用函数,这个过程被称为显式特例化。如果你重载了一个通用函数将覆盖(或隐藏)通用函数中相应的特例函数。如下程序所示:
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;
template <class X> void swapargs(X &a, X &b)
{
X temp;
temp = a;
a = b;
b = temp;
cout << "Inside template swapargs.\\n";
}
//重载了通用函数swapargs()的整数类型形式
void swapargs(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
cout << "Inside template 'int' specialization.\\n";
}
int main()
{
int i = 10, j = 20;
double x = 10, y = 23.3;
char a = 'x', b = 'z';
cout << "Original i, j: " << i << ' ' << j << endl;
cout << "Original x, y: " << x << ' ' << y << endl;
cout << "Original a, b: " << a << ' ' << b << endl;
swapargs(i, j);
swapargs(x, y);
swapargs(a, b);
cout << "Swapped i, j: " << i << ' ' << j << endl;
cout << "Swapped x, y: " << x << ' ' << y << endl;
cout << "Swapped a, b: " << a << ' ' << b << endl;
return 0;
}
运行输出:$ ./reltem
Original i, j: 10 20
Original x, y: 10 23.3
Original a, b: x z
Inside template 'int' specialization.
Inside template swapargs.
Inside template swapargs.
Swapped i, j: 20 10
Swapped x, y: 23.3 10
Swapped a, b: z x
在上面程序中,当调用函数 swapargs(i, j) 时,程序调用的是被显示重载的函数 swapargs(),因为显示重载函数覆盖了通用函数整数类型的特例函数。对于这个重载函数,还有一种新语法的表示形式,如下:
[C++] 纯文本查看 复制代码
//使用新的语法来显式重载函数
template<> void swapargs<int>(int &a, int &b)
{
temp = a;
a = b;
b = temp;
}
新的语法使用了 template<> 来表示通用函数的重载,重载函数使用的数据类型被放在函数名字后面的尖括号中,如 <int> 表示重载的是整型。
作者: beyes 时间: 2011-9-3 22:55
标题: 模板函数使用标准参数
在模板函数中可以以混合方式使用标准类型参数和通用类型参数。如下示例所示:
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;
template<class X> void repeat(X data, int times)
{
do {
cout << data << "\\n";
times--;
}while(times);
}
int main()
{
repeat("This is a test", 3);
repeat(100, 5);
repeat(99.0/2,4);
return 0;
}
运行输出:$ ./temparg
This is a test
This is a test
This is a test
100
100
100
100
100
49.5
49.5
49.5
49.5
程序中,模板函数 repeat() 使用了通用类型参数 X data,还使用了标准参数 int times ,这种混用不会带来麻烦,实际上这种用法还很常见。
欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) |
Powered by Discuz! X3.2 |