梳理STL学习过程中的笔记
学STL,首先要搞清楚什么是模板
函数模板
或者是用 <Class T>都是一样的
1 template <typename T>2 3 int function(const T& a, const T& b)4 5 {6 7 ... ...8 9 }10 11 template <typename T>12 13 inline int function(const T& a)14 15 {16 17 ... ...18 19 }怎么使用呢?
直接填值就可以了
编译器根据值的类型进行判断,不用多操心
函数模板的实例化
1 function(1, 2);2 3 CString str1, str2;4 5 function(str1, str2);推断类型的时候不带强制类型转换的 否则怎么推断呢
在模板函数内部, 是可以强制类型转换的
比如模板函数调用某个库函数的时候,传给库函数的类型不完全吻合时
PS:
VC++中有<string.h>文件,它就是C中的那个; 而<cstring>文件实际上只是在一个命名空间std中include了<string.h>,这是因为C++要减少名称污染;
类模板
和函数模板完全一样 只是实例化的时候方式不同
实例化的时候 会被强制类型转换的
1 template <typename T>2 3 class Stack4 5 {6 7 push(T& a);8 9 ... ...10 11 }类的实例化
1 Queue<int> qs;形成一个int代替形参表的类类型
并产生该类型的一个对象 qs
====================================================================
外界定义的和形参一样的 会在模板内部屏蔽掉
1 typedef double T2 3 template <typename T>4 5 int function(T& a )6 7 {8 9 外界定义的T会被隐藏掉10 11 }内部不允许再次使用形参做变量名
1 template <typename T>2 3 int function(T& a )4 5 {6 7 typedef double T; // 非法8 9 }形参中每一种类型前面都要加typename或者class
类型的子类型
T是一个类型 SubT是T类型的子类型
什么是子类型?
就是比如T是一个类
1 template <class T>2 3 class Cls4 5 {6 7 typedef int SubT;8 9 } 在定义的时候 1 template <typename T>2 3 T fun(T& a)4 5 {6 7 T::SubT* p; // 系统不知道SubT是子类型 会以为是T的静态成员变量 认为是两者的乘积(T::SubT)*(p)8 9 } 所以要声明 1 template <typename T>2 3 T fun(T& a)4 5 {6 7 typename T::SubT* p; // SubT是一种类型8 9 } 当然SubT也可以被另一种形参所笼罩 1 template <class T,class U>2 3 class Cls4 5 {6 7 typedef U SubT;8 9 } 很无语吧!==========================================================
现在看看非类型模板形参是怎么回事儿
1 #include <iostream> using namespace std; 2 template <class T,int N>3 int getDim(const T (&a)[N]) 4 { 5 return N;6 } 7 8 int main() 9 { 10 double d[234]; 11 cout << getDim(d); 12 return 0; 13 } 14 15由于有这样的定义
1 const T (&a)[N]所以实例化的时候 &a 实例化为d N实例化为234
相当于形参表为 <double, 234>
只是传递的时候只需要传递 d 就可以了
为什么只需要传递d呢 因为d是函数getDim的参数 类型和个数都由d自己的属性来确定
数组d的类型被自动识别 把T实例化为double类型
类型为int的N被自动识别 实例化为数组d的单元数
类的等价性???
==============================================================================
数组的引用传递
1 void print(int (&arr)[10]); // 需要指定数组长度,长度不一致将不匹配2 int main()3 {4 int i[2];5 int k[10];6 print(i);// error7 print(k);//OK8 }所以在模板中认为数组引用传递的时候 如果两个数组的长度不同 他们是不同的类型
1 template <typename T>2 T fref(T &, T&)3 {4 ... ...5 }6 int a[5];7 int b[10];8 fref(a, b);// error类型不同更复杂一点的实例化应用是 用函数指针指向某个实例化的模板 这样模板就实例化为那个指针的类型
1 template <typename T>2 int compare(const T&, const T&);3 4 int (*pf)(const int&, const int&) = compare;