一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情。
一、类模板
💦 类模板的定义格式
template<class T1, class T2, ..., class Tn>
class 类模板名
{
//类内成员定义
};
栈的泛型问题 ❓
typedef int STDataType;
class Stack
{
private:
STDataType* _a;
int _top;
int _capacity;
};
int main()
{
Stack st1;//int
Stack st2;//double
return 0;
}
📝说明
这里想让 st1 是 int,st2 是 double,显然这里做不到。C 语言中的 typedef 只是增强程序的可维护性,不能解决泛型的问题。
类模板解决栈泛型 ❓
struct TreeNode
{
};
template<class T>
class Stack
{
private:
T* _a;
int _top;
int _capacity;
};
int main()
{
Stack<TreeNode>st1;//TreeNode*
Stack<int>st2;//int
return 0;
}
📝说明
对于函数模板可以根据实参去推演形参的类型,但是类在用的时候,首先是定义对象,所以类模板的使用都是显示实例化。
Stack< TreeNode* >st1 和 Stack< int >st2 用的是一个类 ❓
它们的模板参数不同,用的不是同一个类。
调试后发现,st1 里的 _a 是 TreeNode* 类型, st2 里的 _a 是 int* 类型。
💦 类模板的实例化
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。
//Stack类名,Stack<int>才是类型
Stack<int>s1;
Stack<double>s2;
struct TreeNode
{};
template<class T>
class Stack
{
public:
Stack(int capacity = 4)
: _a(new T[capacity])
, _top(0)
, _capacity(capacity)
{}
~Stack()
{
delete[]_a;
_a = nullptr;
_top = _capacity = 0;
}
//类里面声明,类外面定义呢???
void Push(const T& x);
private:
T* _a;
int _top;
int _capacity;
};
template<class T>
void Stack<T>::Push(const T& x)//指定域,且需要声明模板
{}
int main()
{
Stack<TreeNode*>st1;//TreeNode*
Stack<int>st2;//int
return 0;
}
📝说明
在类模板里声明,类模板外定义,与以前的不同。
普通类,类名就是类型
类模板,类名不是类型,类型是 Stack
函数/类模板不支持把声明写到 .h,定义写到 .cpp 的方式,会报链接错误,原因后面会详细讲。
.h里实例化了,Stack.cpp里没有实例化,test.cpp去找的时候,只有声明,没有定义。所以解决方法就是声明和定义不要分离,当然要分离也有方法,但是这种方法比较 low,在模板的进阶会详细学习。