同在csdn看到的一篇文章,觉得不错,做个笔记。
文章原址请转http://blog.csdn.net/sunxx1986/article/details/6619144
在C++中有好几个这样的术语,但是我们很多时候用的并不正确,几乎是互相替换混淆使用。
函数指针——指针函数
数组指针——指针数组
类模板——模板类
函数模板——模板函数
1.函数指针——指针函数
函数指针的重点是指针。表示的是一个指针,它指向的是一个函数,例子:
int (*pf)();
指针函数的重点是函数。表示的是一个函数,它的返回值是指针。例子:
int* fun();
2.数组指针——指针数组
数组指针的重点是指针。表示的是一个指针,它指向的是一个数组,例子:
int (*pa)[8];
指针数组的重点是数组。表示的是一个数组,它包含的元素是指针。例子;
int* ap[8];
3.类模板——模板类(class template——template class)
类模板的重点是模板。表示的是一个模板,专门用于产生类的模子。例子:
template <typename T>
class Vector
{
…
};
使用这个Vector模板就可以产生很多的class(类),Vector <int> 、Vector <char> 、Vector < Vector <int> > 、Vector <Shape*> ……。
模板类的重点是类。表示的是由一个模板生成而来的类。例子:
上面的Vector <int> 、Vector <char> 、……全是模板类。
这两个词很容易混淆,我看到很多文章都将其用错,甚至一些英文文章也是这样。将他们区分开是很重要的,你也就可以理解为什么在定义模板的头文件.h时,模板的成员函数实现也必须写在头文件.h中,而不能像普通的类(class)那样,class的声明(declaration)写在.h文件中,class的定义(definition)写在.cpp文件中。
关于一个缺省模板参数的例子:
template <typename T = int>
class Array
{
…
};
第一次我定义这个模板并使用它的时候,是这样用的:
Array books;//我认为有缺省模板参数,这就相当于Array <int> books
上面的用法是错误的,编译不会通过,原因是Array不是一个类。正确的用法是Array <> books;
这里Array <> 就是一个用于缺省模板参数的类模板所生成的一个具体类。
4.函数模板——模板函数(function template——template function)
函数模板的重点是模板。表示的是一个模板,专门用来生产函数。例子:
template <typename T>
void fun(T a)
{
…
}
在运用的时候,可以显式(explicitly)生产模板函数,fun <int> 、fun <double> 、fun <Shape*> ……。
也可以在使用的过程中由编译器进行模板参数推导,帮你隐式(implicitly)生成。
fun(6);//隐式生成fun <int>
fun(8.9);//隐式生成fun <double>
fun(‘a’);// 隐式生成fun <char>
Shape* ps = new Cirlcle;
fun(ps);//隐式生成fun <Shape*>
模板函数的重点是函数。表示的是由一个模板生成而来的函数。例子:
上面显式(explicitly)或者隐式(implicitly)生成的fun <int> 、fun <Shape*> ……都是模板函数。
关于模板本身,是一个非常庞大的主题,要把它讲清楚,需要的不是一篇文章,而是一本书,幸运的是,这本书已经有了:David Vandevoorde, Nicolai M. Josuttis写的《C++ Templates: The Complete Guide》。可惜在大陆买不到纸版,不过有一个电子版在网上流传。
模板本身的使用是很受限制的,一般来说,它们就只是一个产生类和函数的模子。除此之外,运用的领域非常少了,所以不可能有什么模板指针存在的,即指向模板的指针,这是因为在C++中,模板就是一个代码的代码生产工具,在最终的代码中,根本就没有模板本身存在,只有模板具现出来的具体类和具体函数的代码存在。
但是类模板(class template)还可以作为模板的模板参数(template template parameter)使用,在Andrei Alexandrescu的《Modern C++ Design》中的基于策略的设计(Policy based Design)中大量的用到。
template < typename T, template <typename U> class Y>
class Foo
{
…
};
从文章的讨论中,可以看到,名字是非常重要的,如果对名字的使用不恰当的话,会引起很多的麻烦和误解。我们在实际的程序中各种标识符的命名也是一门学问,为了清晰易懂,有时候还是需要付出一定的代价。
最后提醒:在本文的几个术语中,语言的重心在后面,前面的词是作为形容词使用的。