- 八、模板
- 1、类型模板1-模板函数
- 例36、template(1)
- 2、类型模板2-模板类
- 例37、template(2)
- 3、非类型模板
- 例38、template(3)
- 4、特化
- 例39、template(4)
假如我现在想实现简单的加法运算,那么就要考虑数据的类型。先考虑只有两种情况:整数的和小数的。
于是就可以确定案例函数有add(1, 2)和add(1.1, 2.3),如下
#include#include using namespace std; int add(int a, int b) { return a+b; } double add(double a, double b) { return a+b; } int main() { cout<< add(1, 2) < 执行结果
@ubuntu:/mnt/hgfs/ub2$ g++ template1.cpp @ubuntu:/mnt/hgfs/ub2$ ./a.out 3 3.4 @ubuntu:/mnt/hgfs/ub2$然后就发现这个add()函数只是类型不同,实现方式都是一样。这时候模板的妙处就展现出来了。
如下
#include#include using namespace std; template XXX add(XXX a, XXX b) { return a+b; } int main() { cout<< add(1, 2) < 执行结果一样
@ubuntu:/mnt/hgfs/ub2$ g++ template2.cpp @ubuntu:/mnt/hgfs/ub2$ ./a.out 3 3.4 @ubuntu:/mnt/hgfs/ub2$2、类型模板2-模板类 例37、template(2)回顾之前的例11 、例23 、例25 的arr.h
#ifndef _ARR_ #define _ARR_ class ARR{ public: ARR():tail(0){ } void addtail(int data); void show(void); private: int data[100]; int tail; }; #endif发现私有成员data[100] 的数据类型是固定死了的(int),后面凡是数据都得整型int处理,比如3.7就会当成3,使数据出错。为了变得通用,就可以使用模板来处理,从而灵活运用。案例如下
arr.h
#ifndef _ARR_ #define _ARR_ templateclass ARR{ public: ARR():tail(0){ } void addtail(XXX data); void show(void); private: XXX data[100]; int tail; }; #endif arr.cpp
#include "arr.h" #include#include using namespace std; template void ARR ::addtail(XXX data) { this->data[tail++] = data; } template void ARR ::show(void) { int i = 0; for(; i main.cpp
#include "arr.h" int main() { ARRarr; arr.addtail(1); arr.addtail(3); arr.addtail(6); arr.addtail(9); arr.show(); } 运行结果
@ubuntu:/mnt/hgfs/ub2/ARR1$ ls arr.cpp arr.h main.cpp @ubuntu:/mnt/hgfs/ub2/ARR1$ g++ *.cpp /tmp/ccm4VpzB.o: In function `main': main.cpp:(.text+0x39): undefined reference to `ARR::addtail(int)' main.cpp:(.text+0x4d): undefined reference to `ARR ::addtail(int)' main.cpp:(.text+0x61): undefined reference to `ARR ::addtail(int)' main.cpp:(.text+0x75): undefined reference to `ARR ::addtail(int)' main.cpp:(.text+0x84): undefined reference to `ARR ::show()' collect2: error: ld returned 1 exit status @ubuntu:/mnt/hgfs/ub2/ARR1$ 出现这个问题是因为在C++中不支持模板分两部分来写(arr.c 和arr.h )
所以需要把这两个整合到一块去(整合到arr.h 中),成如下的arr.h
#ifndef _ARR_ #define _ARR_ #includeusing namespace std; template class ARR{ public: ARR():tail(0){ } void addtail(XXX data); void show(void); private: XXX data[100]; int tail; }; template void ARR ::addtail(XXX data) { this->data[tail++] = data; } template void ARR ::show(void) { int i = 0; for(; i main.cpp 保持之前那样
#include "arr.h" int main() { ARRarr; arr.addtail(1); arr.addtail(3); arr.addtail(6); arr.addtail(9); arr.show(); } 运行结果
@ubuntu:/mnt/hgfs/ub2/ARR2$ ls a.out arr.h main.cpp @ubuntu:/mnt/hgfs/ub2/ARR2$ g++ main.cpp @ubuntu:/mnt/hgfs/ub2/ARR2$ ./a.out 1,3,6,9, @ubuntu:/mnt/hgfs/ub2/ARR2$然后假设我添加的是浮点数,可以改写如下
#include "arr.h" int main() { #if 0 ARRarr; arr.addtail(1); arr.addtail(3); arr.addtail(6); arr.addtail(9); #endif ARR arr; arr.addtail(1.7); arr.addtail(3.5); arr.addtail(6.8); arr.addtail(9.6); arr.show(); } 执行结果依然没问题
@ubuntu:/mnt/hgfs/ub2/ARR2$ ls a.out arr.h main.cpp @ubuntu:/mnt/hgfs/ub2/ARR2$ g++ main.cpp @ubuntu:/mnt/hgfs/ub2/ARR2$ ./a.out 1.7,3.5,6.8,9.6, @ubuntu:/mnt/hgfs/ub2/ARR2$这就是模板的魅力!!!
3、非类型模板template例38、template(3)class List{ public: List(); ~List(); private: T arr[SIZE]; int num; }; 参照例37,把数组大小也变为模板方式
arr.h
#ifndef _ARR_ #define _ARR_ #includeusing namespace std; template class ARR{ public: ARR():tail(0){ } void addtail(XXX data); void show(void); private: XXX data[SIZE]; int tail; }; template void ARR ::addtail(XXX data) { this->data[tail++] = data; } template void ARR ::show(void) { int i = 0; for(;i main.cpp
#include "arr.h" int main() { ARRarr;//类型为int,size为100 arr.addtail(1); arr.addtail(3); arr.addtail(6); arr.addtail(9); arr.show(); ARR arr1;//类型为double,size为1000 arr1.addtail(1.7); arr1.addtail(3.5); arr1.addtail(6.8); arr1.addtail(9.6); arr1.show(); } 执行结果
@ubuntu:/mnt/hgfs/ub2/ARR3$ ls a.out arr.h main.cpp @ubuntu:/mnt/hgfs/ub2/ARR3$ g++ main.cpp @ubuntu:/mnt/hgfs/ub2/ARR3$ ./a.out 1,3,6,9, 1.7,3.5,6.8,9.6, @ubuntu:/mnt/hgfs/ub2/ARR3$4、特化特化
template <> class List{ public: List(); ~List(); private: int arr[100]; int num; };偏特化
template例39、template(4)class C{ public: A a; B b; }; class C {//特化B为int 类型,至于A什么类型并没有没有特化,这种有针对的特化就是偏特化 }; 在例36中我们已经实现int类型和double类型公用的模板,但现在遇到个判断真假的逻辑加法运算需求(全真才为真,否则为假)。
然后发现这个模板不管用了。
#include#include using namespace std; template XXX add(XXX a, XXX b) { return a+b; } int main() { #if 0 cout<< add(1, 2) < 运行结果
@ubuntu:/mnt/hgfs/ub2$ g++ template3.cpp @ubuntu:/mnt/hgfs/ub2$ ./a.out 1 @ubuntu:/mnt/hgfs/ub2$根据需求,一真一假结果为假即为0,而这里是1,所以是错误的。于是我们可以使用特化来解决此问题。
#include#include using namespace std; template XXX add(XXX a, XXX b) { return a+b; } template <> bool add(bool a, bool b) { if(a == true && b == true) return true; return false; } int main() { #if 0 cout<< add(1, 2) < 运行结果
@ubuntu:/mnt/hgfs/ub2$ g++ template3.cpp @ubuntu:/mnt/hgfs/ub2$ ./a.out 0 1 @ubuntu:/mnt/hgfs/ub2$



