类模板实例化后得到的是一个具体的、可编译的类类型,即编译期生成的独立类型(如stack),具备继承、static成员、模板参数等完整类特性,且不同模板参数组合产生互不兼容的类型。

类模板实例化后得到的是一个**具体的、可编译的类类型**,不是函数、不是别名、也不是运行时对象——它在编译期就成为一个完全等价于手写类的实体,只是名字带模板参数(如 Stack<int></int>)。
类模板实例化 ≠ 创建对象
很多人混淆“实例化类模板”和“定义该类的对象”。前者是让编译器生成一个新类型,后者才是分配内存、调用构造函数。比如:
-
template<class t int n> class Stack { ... };</class>—— 这只是模板定义,不产生任何代码 -
Stack<int> s;</int>—— 这行触发隐式实例化,编译器生成Stack<int></int>这个完整类,并用它定义对象s -
Stack<int>* p;</int>—— 仅声明指针,不触发实例化(C++标准规定:只有用到类定义体时才必须实例化)
显式实例化(template class)的作用
显式实例化语句:template class Stack<double>;</double>,它的效果是:
- 强制编译器立即生成
Stack<double></double>的完整类定义(包括所有成员函数声明) - 但不生成成员函数的函数体代码,除非这些函数被实际调用(类模板的成员函数是“按需实例化”的)
- 常用于分离编译:把模板定义放在 .cpp 中,靠显式实例化导出特定类型,避免链接错误
- 若某成员函数从未被调用,即使显式实例化了类,该函数体也不会出现在目标文件中
实例化后的类与普通类几乎无区别
一旦 Stack<int></int> 被实例化,它就具备以下特性:
- 可以作为基类继承:
class MyStack : public Stack<int> { ... };</int> - 支持
static成员:每个实例化版本有自己独立的static变量,如Stack<int>::count</int>和Stack<string>::count</string>互不干扰 - 可取地址、可作为模板参数、可参与 SFINAE —— 它就是个正规类类型
- 注意:非类型模板参数(如
int N)在实例化后变成编译期常量,不能被修改
最易忽略的一点:类模板实例化是编译期行为,且每个不同参数组合都生成独立类型;哪怕两个实例化结果逻辑上完全一样(比如 Pair<int bool></int> 和另一个一模一样的 Pair<int bool></int>),它们也是同一类型,但和 Pair<bool int></bool> 完全无关——类型系统不推断等价性,只认字面参数序列。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











