C++模板函数
类模板是为了减少重复工作量而出现的一种进制,当一个类的功能类似只是类型不同时,一个通用的类模板可以根据使用者的需要而生成具体类型的类,从而减少功能重复的代码。
C++在STL中大量使用了类模板,很多迭代器与算法的实现都离不开泛型编程与类模板的支持。所以掌握类模板的基本使用是很重要的。
#include
#include
using namespace std;
template <typename T>
class DEMO {
public:
DEMO(T data) {
this->data = data;
}
~DEMO() {
}
int GetData() {
return this->data;
}
private:
T data;
};
template <typename T,typename T1>
class DEMO1 {
public:
DEMO1() {
}
~DEMO1();
private:
T data;
T1 ch;
};
int main(void) {
DEMO<int> demo(5); //显示的指定类型为int
DEMO1<int, char> demo1(); //显示的指定类型分别为int,char
cout << "data=" << demo.GetData() << endl;
system("pause");
return 0;
}
类模板的定义与使用使用的是和模板函数一样的关键字。即先声明template,在使用typename声明虚拟类型。
与模板函数不同的是,类模板不能被自动推导出类型,只能显示的指定具体的类型。如上面代码中的 DEMO< int > demo(5),该模板类被显示的指定为int型。
在类内部声明成员函数,在类外部定义成员函数时,只要成员函数参数列表中出现了类限定域说明,模板类作为返回类型,模板类作为参数类型,那么就要在成员函数之前声明 template <类型形式参数表>,并且在模板类后加上虚拟参数列表。
#include
#include
using namespace std;
template <typename T>
class DEMO {
public:
DEMO(T data);
~DEMO();
DEMO operator+(int sum);
int PrintData(DEMO& demo);
private:
T data;
};
template<typename T> //出现了类限定域说明
DEMO<T>::DEMO(T data)
{
this->data = data;
}
template<typename T> //出现了类限定域说明
DEMO<T>::~DEMO()
{
}
template<typename T> //出现了作为返回值类型的模板类类型
DEMO<T> DEMO<T>::operator+(int sum)
{
return *this;
}
template<typename T> //出现了作为参数类型的模板类类型
int DEMO<T>::PrintData(DEMO<T>& demo)
{
cout << "data=" << demo.data << endl;
return 0;
}
int main(void) {
DEMO<int> demo(5), demo1(15);
demo.PrintData(demo1);
demo + 5;
system("pause");
return 0;
}
DEMO< T >中的< T >是虚拟参数列表。
总结来说,只要看到了模板类的类名关键字出现在成员函数参数列表中,就要在成员函数之前声明 template <类型形式参数表>,并且在模板类类名后加上虚拟参数列表。
分为三种情况。一:子类是模板类,父类是普通类;二:父类是模板类,子类是普通类;三:父类与子类都是模板类。其中第一种情况与两个普通类的继承是一样的。就不说了。
1.父类是模板类,子类是普通类:
#include
#include
using namespace std;
template <typename T>
class FATHER {
public:
FATHER(T data) {
this->data = data;
}
~FATHER() {
}
private:
T data;
};
class SON:public FATHER<int> { //显示的指明父类的具体类型
public:
SON(int data):FATHER<int>(data) {
this->data = data;
}
~SON() {
}
int GetData() {
return data;
}
private:
int data;
};
int main(void) {
SON son(15);
cout << "data=" << son.GetData() << endl;
system("pause");
return 0;
}
子类是一般类,父类是模板类,继承时必须在子类里实例化父类的类型参数。其实这很好理解,因为在子类对象构造之前,会先调用父类的构造函数,父类为模板类,要想实例化,需要有指定的类型。
2.父类与子类都是模板类:
#include
#include
using namespace std;
template <typename T>
class FATHER {
public:
FATHER(T data) {
this->data = data;
}
~FATHER() {
}
private:
T data;
};
template <typename T1>
class SON:public FATHER<T1> { //使用子类的模板类型传递到父类中,也可以使用具体的类型
public:
SON(int data):FATHER<int>(data) {
this->data = data;
}
~SON() {
}
int GetData() {
return data;
}
private:
T1 data;
};
int main(void) {
SON<int> son(15);
cout << "data=" << son.GetData() << endl;
system("pause");
return 0;
}
当子类与父类都是模板类时,继承时也必须在子类里实例化父类的类型参数,值得注意的是,此时实例化的类型参数可以使用子类的模板类型。即让父类与子类在实例化后拥有一样的具体类型。当然也可以使用其它的具体类型。
类的static数据成员需在类内定义,在类外初始化。
对于普通类,各个对象之间共享同一个static变量。而模板类使用不同类型实例化后生成的其实是不同的类(虽然类名一样,但在编译器内部其实是采用不同的标识),它们各自拥有不同的static数据成员。因此它们实例化后的对象使用的也是不同的static成员。
看一个例子:
#include
#include
using namespace std;
template <typename T>
class DEMO {
public:
DEMO(int mask) {
this->mask = mask;
}
~DEMO() {
}
static int data;
private:
int mask;
T tmp;
};
template <typename T> //初始化static数据成员
int DEMO<T>::data = 0;
int main(void) {
DEMO<int> demo(0), demo1(1);
DEMO<char> demo2(2), demo3(3);
cout << "被修改后前demo的data的值:" << demo.data << endl;
cout << "被修改后前demo1的data的值:" << demo1.data << endl;
cout << "被修改后前demo2的data的值:" << demo2.data << endl;
cout << "被修改后前demo3的data的值:" << demo3.data << endl;
cout << endl;
demo.data = 555;
demo2.data = 666;
cout << "被修改后的demo的data的值:" << demo.data << endl;
cout << "被修改后的demo1的data的值:" << demo1.data << endl;
cout << "被修改后的demo2的data的值:" << demo2.data << endl;
cout << "被修改后的demo3的data的值:" << demo3.data << endl;
system("pause");
return 0;
}
设计一个vector容器,可以储存int,char ,float,double等基础类型。可以使用[]访问容器中元素,支持两个容器之间的直接赋值,支持用一个容器构造另一个容器。
可以先自己思考,答案我放在另一篇博客。
模板类实现vector容器