自我总结,若有问题欢迎指出!谢谢。
1 语法
下面是类模板的基本语法
template<class T>
类定义
其中,中的“class”也可以替换成“typename”,只是为了 告诉编译器后面接的是某一个待传入的数据类型T。
举个例子,下面声明一个数组类的模板,数组中元素的数据类型为T,
// MyArray.hpp
template<class T>
class MyArray
{
public:
MyArray(int cap)
{
m_arrAddress = new T[cap];
m_capacity = cap;
m_size = 0;
}
~MyArray()
{
if (m_arrAddress != NULL)
{
delete[] m_arrAddress;
m_arrAddress = NULL;
}
m_capacity = 0;
m_size = 0;
}
private:
T *m_arrAddress;
int m_capacity; // 表示数组最大空间
int m_size;// 表示数组当前空间
};
2 基本用法
继承上面所声明的数组类模板,我们现在想声明一个整型数组,即
#include "MyArray.hpp"
int main()
{
MyArray<int> arr(10); // 声明了一个数组大小为10的整型数组
return 0;
}
3注意
(1)没有为类成员传入具体数据类型的模板类,其不是一个真正意义上的类,只是一个模板,因此不能进行变量声明,即
MyArray arr(10); // false!
MyArray<int> arr(10); // true!
(2)类模板中如果成员函数的返回值是也是一个类模板,则一定要说明类成员数据类型(int/double/自定义数据类型/…)
举个例子:
// MyArray.hpp
template<class T>
class MyArray
{
public:
MyArray(int cap)
{
m_arrAddress = new T[cap];
m_capacity = cap;
m_size = 0;
}
~MyArray()
{
if (m_arrAddress != NULL)
{
delete[] m_arrAddress;
m_arrAddress = NULL;
}
m_capacity = 0;
m_size = 0;
}
// 注意到,返回类型时MyArray<T>
MyArray<T>& operator=(const MyArray& arr)
{
if (this->m_arrAddress != NULL)
{
delete[] this->m_arrAddress;
this->m_arrAddress = NULL;
}
this->m_arrAddress = new T[arr.m_capacity]; // 深拷贝
this->m_size = arr.m_size;
this->m_capacity = arr.m_capacity;
for (int i = 0; i < this->m_size; i++)
{
this->m_arrAddress[i] = arr.m_arrAddress[i];
}
}
private:
T *m_arrAddress;
int m_capacity; // 表示数组最大空间
int m_size;// 表示数组当前空间
};
由上面的例子可见,当我们重载运算符“=”时,返回类型是MyArray&。
这时候有人会问,我写成MyArray&编译也没有报错,咋回事?
这个应该是编译器(我是VS2019)替我们做了优化,即在成员函数类内实现 时,如果返回值为本类的类型,可以不用加。但如果类外实现的时候,编译就会报错了!即,
// MyArray.hpp
template<class T>
class MyArray
{
public:
MyArray(int cap)
{
m_arrAddress = new T[cap];
m_capacity = cap;
m_size = 0;
}
~MyArray()
{
if (m_arrAddress != NULL)
{
delete[] m_arrAddress;
m_arrAddress = NULL;
}
m_capacity = 0;
m_size = 0;
}
MyArray& operator=(const MyArray& arr);
private:
T *m_arrAddress;
int m_capacity; // 表示数组最大空间
int m_size;// 表示数组当前空间
};
// 类外实现
template<class T>
MyArray& MyArray<T>::operator=(const MyArray& arr) // false!
{
if (this->m_arrAddress != NULL)
{
delete[] this->m_arrAddress;
this->m_arrAddress = NULL;
}
this->m_arrAddress = new T[arr.m_capacity];
this->m_size = arr.m_size;
this->m_capacity = arr.m_capacity;
for (int i = 0; i < this->m_size; i++)
{
this->m_arrAddress[i] = arr.m_arrAddress[i];
}
}
template<class T>
MyArray<T>& MyArray<T>::operator=(const MyArray& arr) // true!
{
if (this->m_arrAddress != NULL)
{
delete[] this->m_arrAddress;
this->m_arrAddress = NULL;
}
this->m_arrAddress = new T[arr.m_capacity];
this->m_size = arr.m_size;
this->m_capacity = arr.m_capacity;
for (int i = 0; i < this->m_size; i++)
{
this->m_arrAddress[i] = arr.m_arrAddress[i];
}
}
4 总结
对于类模板的使用,没有声明成员数据类型,则永远只是个模板,可以视作为一个“抽象”的类。只有声明了数据类型,才是一个 真正的类!