曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4319|回复: 3
打印 上一主题 下一主题

通用函数(模板函数)

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34387
跳转到指定楼层
楼主
发表于 2011-9-3 20:36:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
模板可以用来创建通用函数和通用类。顾名思义或通用类,通用函数可以将一个函数或类应用于几种不同类型的数据,而不需要显式地再函数中对每种类型的数据做特定的处理。

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 。

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34387
沙发
 楼主| 发表于 2011-9-3 21:49:28 | 只看该作者

重载函数模板

函数模板本身也可以被重载。比如可以创建另外一个函数模板,其参数不同于原来的函数模板。
[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)

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34387
板凳
 楼主| 发表于 2011-9-3 22:41:47 | 只看该作者

显式重载通用函数

我们也可以显式地重载通用函数,这个过程被称为显式特例化。如果你重载了一个通用函数将覆盖(或隐藏)通用函数中相应的特例函数。如下程序所示:
[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> 表示重载的是整型。

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34387
地板
 楼主| 发表于 2011-9-3 22:55:18 | 只看该作者

模板函数使用标准参数

在模板函数中可以以混合方式使用标准类型参数和通用类型参数。如下示例所示:
[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 ,这种混用不会带来麻烦,实际上这种用法还很常见。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-21 09:28 , Processed in 0.068726 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表