共计 3045 个字符,预计需要花费 8 分钟才能阅读完成。
泛型:指在多种数据类型上皆可操作的含义。泛型编程的代表作品 STL 是一种高效、泛型、可交互操作的软件组件
泛型编程最初诞生于 C ++ 中,目的是为了实现 C ++ 的 STL(标准模板库)。
模板的精神:类型参数化
话不多说,看例子吧。
一个函数模板
// template<typename T> 既可以与函数同行, 也可以将函数另起一行来书写
// T 即为泛化的类型
// T 获取类型的过程, 称为模板的实例化
// 函数模板通过具体类型产生不同的函数, 编译器会对函数模板进行两次编译:
// 在声明的地方对模板代码本身进行编译(类型检查), 在调用的地方对参数替换后的代码进行编译(代码生成)
// 泛型的特性:
// 1. 先实例化, 再调用
// 2. 严格匹配, 不存在隐式转化
// 3. 尺有所短, 寸有所长
// 算法 sort 就是支持类型泛化的代表排序算法
include <iostream>
using namespace std;
template<typename T> void myswap(T &a, T &b){
T t = a;
a = b;
b = t;
}
int main()
{
long a = 2; long b = 3;
myswap<long>(a, b);
cout<<a<<b<<endl; //32
string m = "aaa";
string n= "bbb";
myswap<string>(m, n);
cout<<m<<n<<endl;
// 如果自定义类型呢?
int x = 1; char y = 2;
// myswap(x, y); // 严格类型匹配
return 0;
}
函数模板的特殊化
// 函数模板的使用场景:
// 只适用于函数的参数个数相同 而类型不同, 且函数体相同的情况.
include <iostream>
include <string.h>
using namespace std;
template<typename T>
int compare(T &a, T &b){
if(a > b)
return 1;
else if(a < b)
return -1;
else {return 0;}
}
// 比较指针的大小
//template<>
//int compare<const char >(const char &a, const char * &b){
// return strcmp(a, b);
//}
int main()
{
int a = 3;int b = 5;
cout<<compare(a, b)<<endl; //-1
string str1 = "abc", str2 = "abc";
cout<<compare(str1, str2)<<endl; //0
//char * 与 const char * 亦属于不匹配
const char *p1 = "abc", *p2 = "def";
cout<<compare(p1, p2)<<endl; //-1
cout<<compare(p2, p1)<<endl; //1
return 0;
}
类模板 & 友元
//mylist.hpp
ifndef MYLIST_H
define MYLIST_H
include <iostream>
include <ostream>
using namespace std;
namespace listspace{
template<class ItemType>
class GenericList;
template<class ItemType>
ostream & operator<<(ostream &out, GenericList<ItemType>& list);
template<class ItemType>
class GenericList{
public:
GenericList(int max);
~GenericList();
int length() const;
void add(ItemType new_item);
bool full() const;
void erase();
// 类模板的友元
friend ostream & operator<< <>(ostream & out, GenericList<ItemType>& list);
private:
ItemType *_item;
int _maxLength;
int _curIdx;
};
}
endif
ifndef MYLIST_CPP
define MYLIST_CPP
include <iostream>
include <cstdlib>
include “mylist.h”
using namespace std;
namespace listspace {
template<class ItemType>
GenericList<ItemType>::GenericList(int max)
:_maxLength(max), _curIdx(0){_item = new ItemType[max];
}
template<class ItemType>
GenericList<ItemType>::~GenericList(){
delete [] _item;
}
template<class ItemType>
int GenericList<ItemType>::length() const{
return (_curIdx);
}
template<class ItemType>
void GenericList<ItemType>::add(ItemType new_item){
if(full()){
cout<<"Error: adding to a full list.\n";
exit(1);
}else{_item[_curIdx] = new_item;
_curIdx = _curIdx + 1;
}
}
template<class ItemType>
bool GenericList<ItemType>::full() const{
return (_curIdx == _maxLength);
}
template<class ItemType>
void GenericList<ItemType>::erase(){
_curIdx = 0;
}
template<class ItemType>
ostream & operator<<(ostream &out, GenericList<ItemType> & list){
for(int i = 0; i < list._curIdx; i++){out<<list._item[i];
}
return out;
}
}
endif
//main.cpp
include <iostream>
include “mylist.hpp”
// 类模板中的友元
// 1 在声明处
// 2 在类外的定义处
//@1 在类中声明 <> 表明, 是个声明
//@2 在类外实现
//@3 在类的声明的前面, 作前向声明, 并且在其前作类的前向声明
// 模板通常会将声明和实现, 放在一个文件中, 即 hpp 中
//C/C++ 中的编译模式是, 按文件进行编译, 在任何需要实例化的地方, 都需要看到模板的全貌
using namespace std;
using namespace listspace;
int main()
{
GenericList<int> first_list(2);
first_list.add(1);
first_list.add(2);
cout<<first_list<<endl;
GenericList<char> seconde_list(10);
seconde_list.add('A');
seconde_list.add('B');
seconde_list.add('C');
cout<<seconde_list<<endl;
return 0;
}
OK. 上述例子都搞清楚的的话,STL 算是入门了。