在界说类的时分,继承和组合能够满足大部分需求。可是关于某些场景,比如用来贮存目标的容器类,针对不同的贮存目标类型,容器类都需求供给相同的代码完成。假如运用类模版,能够将贮存目标类型作为参数传给容器类,这样就能够运用一套容器类代码。
类模版语法
类模版的语法如下,<>
包起来的是模版参数列表,能够有多个参数,用逗号分隔。
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++常识。