跳到主要内容

泛型编程与模板

类模板

类模板也是公共逻辑的抽象,通常用来作为容器(例如:vector)或者行为的封装

基础的类模板

类模板的实现

template <typename T> 
class C {
// code
}

示例

template <typename T>
class example {
public:
//构造函数
example(T a, T b) {
this->a = a;
this->b = b;
}
//运算符重载
example<T> operator+(example &e) {
example<T> tmp(this->a+e.a, this->b+e.b);
return tmp;
}
private:
T a;
T b;
}

int main()
{
//实例化对象时必须声明模板类型,因为要分配内容
example<int> a(10,20);
example<int> b(20,30);
example<int> c = a + b;
return 0;
}

类模板的特化与偏特化

类似于函数模板的重载,可以通过特化(偏特化)类模板来实现对特殊需求的处理

  • 类模板的特化与偏特化需要模板名称相同并且特化列表<>中的参数个数与原始模板相对应
  • 一个类模板可以有多个特化,编译器会自动实例化那个最特殊的版本
#include <typeinfo>
template<typename T> //基本模板
class C {
public:
void info() {
// code
}
};
template<> //特化
class C<int> {
public:
void info() {
// code
}
};
template<typename T> //偏特化
class C<T*> {
public:
void info() {
// code
}
};
template<typename T, typename U> //另外一种偏特化
class C<T(U)> {
public:
void info() {
// code
}
};

int func(int i) {
// code
}

int main(){
C<float> c1;
C1.info(); // 调用基础模板
C<int> c2;
C2.info(); // 调用 int 特化模板
C<float*> c3;
C3.info(); // 调用 T* 特化模板
C<decltype(func)> c4;
c4.info(); // 调用函数特化模板
}

类模板成员特化

除了可以特化类模板之外,还可以对类模板中的成员函数和普通静态成员变量进行特化

template<typename T>  
class C {
public:
void info() {
// code
}
static int value;
};

template<typename T>
int C<T>::value = 10;

template<>
int C<int>::value = 100; //普通静态成员变量的int特化

template<>
void C<int>::info() { //成员函数的int特化
// code
}

模板类的继承

模板类同样可以实现继承

需要注意的是

  • 如果父类自定义了构造函数,记得子类要使用构造函数列表来初始化
  • 继承的时候,如果子类不是模板类,则必须指明当前的父类的类型,因为要分配内存空间
  • 继承的时候,如果子类是模板类,要么指定父类的类型,要么用子类的泛型来指定父类

示例

template <typename T>
class Parent {
public:
Parent(T p){
this->p = p;
}
private:
T p;
};

//如果子类不是模板类,需要指明父类的具体类型
class ChildOne : public Parent<int> {
public:
ChildOne(int a,int b):Parent(b){
this->cone = a;
}
private:
int cone;
};

//如果子类是模板类,可以用子类的泛型来表示父类
template <typename T>
class ChildTwo : public Parent<T> {
public:
ChildTwo(T a, T b):Parent<T>(b) {
this->ctwo = a;
}

private:
T ctwo;
};
```