在界说类的时分,继承和组合能够满足大部分需求。可是关于某些场景,比如用来贮存目标的容器类,针对不同的贮存目标类型,容器类都需求供给相同的代码完成。假如运用类模版,能够将贮存目标类型作为参数传给容器类,这样就能够运用一套容器类代码。

类模版语法

类模版的语法如下,<>包起来的是模版参数列表,能够有多个参数,用逗号分隔。

template <typename T>
类声明

template关键字,表明界说模板

typename :关键字,表明一个类型参数

T变量名,其值代表一个类型。在类中运用。该变量名一般用大写表明。

成员函数,也需求以相同的模板声明开头,而且类限定符也要包含模版参数。

template <typename T>
void ClassName<T>::func() {
}

界说类模版

界说一个容器类Stack

template <typename T>
class Stack {
private:
    T items[10];
    int top;
public:
    Stack();
    bool isEmpty();
};
template <typename T>
Stack<T>::Stack() {
    top = 0;
}
template <typename T>
bool Stack<T>::isEmpty() {
    return top == 0;
}

运用类模版

有2种运用类模版的方式,编译器会生成一个特定版本的类,这叫做实例化

  • 指定模版的类型,而且用它界说一个或许多个目标。假如没有生成目标,类模板不会实例化。这叫做隐式实例化。
  • 运用template和类型来界说一个类,不论有没有生成目标,类模版都会实例化。这叫做显现实例化。

示例如下:

template class Stack<std::string>;      // 显现实例化
void test6() {
    Stack<int> s1;      // 隐式实例化Stack<int>
    if (s1.isEmpty()) {
        std::cout << "Stack<int> s1 is empty: " << std::endl;
    }
    Stack<double> *s2;      // 没有实例化,由于没有生成目标
    s2 = new Stack<double>();   // 实例化Stack<double>
    delete s2;
}

类模版的声明和完成写在头文件

一般情况下,在hpp文件声明一个类的成员函数或许成员数据,在cpp文件完成成员函数。

同样地,在array.hpp声明一个类模版:

#ifndef array_hpp
#define array_hpp
template <typename T>
class Array {
private:
    int count;
public:
    Array();
};
#endif

array.cpp界说成员函数模版:

template <typename T>
Array<T>::Array() {
    count = 0;
}

main.cpp运用该类模版,编译器应该生成int类型的Array类,而且运用结构函数创建一个目标a

#include <iostream>
#include "array.hpp"
int main(int argc, const char * argv[]) {
    Array<int> a;
    return 0;
}

可是,编译这些代码,会发生过错:

Undefined symbol: Array<int>::Array()

这是由于类模版和成员函数模版,并不是类和成员函数。前者是一种指令,告知编译器怎么生成后者。

类模版以及成员函数模版,不能分隔编译,一般是将他们都放到hpp文件。代码就能够正常运转。

#ifndef array_hpp
#define array_hpp
template <typename T>
class Array {
private:
    int count;
public:
    Array();
};
template <typename T>
Array<T>::Array() {
    count = 0;
}
#endif

阅览原文,重视[空与一],获取更多C++常识。