一、函数模板
- 范型编程技术支持程序员创建函数和类的蓝图(即模板,template),而不是具体的函数和类。
- 这些模板可以没有任何类型:它们可以处理的数据并不仅限于某种特定的数据类型。
- 当程序需要用到这些函数中的某一个时,编译器将根据模板即时生成一个能够对特定数据类型进行处理的代码版本。泛型编程技术可以让程序员用一个解决方案解决多个问题。
- 在泛型编程技术里,我们仍然需要编写自己的函数和类,但不必限定它们所使用的数据类型。只需要使用一个占位符(通常用字母T来表示),然后用这个占位符来编写函数。当程序需要这段代码时,你提供数据类型,编译器将根据你的模板即时生成实用的代码。简单的说,就是编译器把模板里的每一个T替换为所提供的数据类型。
- 例:定义一个名为foo()的函数模板:
template <class T> void foo(T param){ //do something } |
需注意的地方:
-第一行代码里,在尖括号里有一个class T,用来告诉编译器:字母T将在接下来的函数里代表一种不确定的数据类型。
-关键字class并不意味着这个是类,这只是一种约定俗成的写法。
-在告诉计算机T是一种类型之后,就可以像对待一种普通数据类型那样使用它了。
6.例:交换
template <class T> void swap(T &a,T &b){ T temp = a; a=b; b=temp; } |
7.在创建模板时,还可以用template<typename T>来代替
Template<class T>,它们的含义是一样的。
8.不要把函数模板分成原型和实现两个部分。如果编译器看不到模板的完整代码,它就无法正确地生成代码。
9.为了明确地表明swap()是一个函数模板,还可以使用swap<int>(i1,i2)语法来调用这个函数。这将明确地告诉编译器它应该使用哪一种类型。
10.如果某个函数对所有数据类型都将进行同样的处理,就应该把它编写为一个模板。
11. 如果某个函数对不同的数据类型将进行不同的处理,就应该对它进行重载。
二、类模板
1、
template <class T> class MyClass{ MyClass(); Void swap(T &a,T &b); } |
构造器的实现将是下面这样:
MyClass<T>::MyClass(){ //初始化操作 } |
因为MyClass是一个类模板,所以不能只写出MyClass::MyClass(),编译器需要你在这里给出一种与MyClass()配合使用的数据类型,必须在尖括号里提供它。因为没有确定的数据类型可以提供,所以使用一个T作为占位符即可。
2、实现栈的操作
#include<iostream> #include<string>
template <class T> class Stack{ public: Stack(unsigned int size=100); //构造器,默认大小为100 ~Stack(); //析构器 void push(T value); T pop();
private: unsigned int size; unsigned int sp; T *data; };
template <class T> Stack<T>::Stack(unsigned int size){ this->size=size; data=new T[size]; sp=0; }
template <class T> Stack<T>::~Stack(){ delete []data; }
template <class T> void Stack<T>::push(T value){ data[sp++]=value; }
template <class T> T Stack<T>::pop(){ return data[--sp]; }
int main(){ Stack<int> intStack(100); intStack.push(1); intStack.push(2); intStack.push(3);
std::cout<<intStack.pop()<<"\n"; std::cout<<intStack.pop()<<"\n"; std::cout<<intStack.pop()<<"\n";
return 0; } |
3、如果类模板需要一种以上的类型,根据具体情况多使用几个占位符即可。
Template <class T,class U> Class Myclass{ //... } 实例化: Myclass<int,float>myclass; |
三、内联模板
- 内联即inline。引入内联函数的目的是为了解决程序中函数调用的效率问题。
- 内联函数从源代码层看,有函数的结构,而在编译后,却不具备函数的性质。编译时,类似宏替换,使用函数体替换调用处的函数名。
- 例:
inline int add(int x,int y){ return x+y; } |
在程序中,调用其函数时,该函数在编译时被替代,而不像一般函数那样是在运行时被调用。
4、在创建类模板时,避免类声明和类定义相分离的一个好办法是使用内联方法。在类里,内联方法的基本含义是在声明该方法的同时还对它进行定义。