一、定义类模板
形式如下:
1 template<class 模板参数表>
2 class 类名{
3 // 类定义......
4 };
其中,template 是声明类模板的关键字,表示声明一个模板,模板参数可以是一个,也可以是多个,可以是类型参数 ,也可以是非类型参数。类型参数由关键字class或typename及其后面的标识符构成。非类型参数由一个普通参数构成,代表模板定义中的一个常量。
注意:
(1)如果在全局域中声明了与模板参数同名的变量,则该变量被隐藏掉。
(2)模板参数名不能被当作类模板定义中类成员的名字。
(3)同一个模板参数名在模板参数表中只能出现一次。
(4)在不同的类模板或声明中,模板参数名可以被重复使用。
二、示例
2.1 类模板实现Array队列
Array.h
#pragma once
#include <iostream>
template<class T>
class Array
{
public:
Array();
Array(int length);
~Array();
int size();
T get(int num);
T& operator [](int num);//重载[]
void set(T data, int num);
public:
T *pt_;
int length_;//长度
};
Array.cpp
#include "Array.h"
template<class T>
Array<T>::Array()
{
pt_ = nullptr;//空指针
length_ = 0;
}
template<class T>//每一个函数都必须模板
Array<T>::Array(int length)
{
this->pt_ = new T[length];
length_ = length;
}
template<class T>//每一个函数都必须模板
Array<T>::~Array()
{
length_ = 0;
delete[] this->pt_;
}
template<class T>//每一个函数都必须模板
int Array<T>::size()
{
return length_;
}
template<class T>//每一个函数都必须模板
T Array<T>::get(int num)//num是数组的下标
{
if (num >= length_ || num < 0)//报错
{
std::cout << "入参不符合要求,不能超过预定长度或者小于0" << std::endl;
this->pt_ = nullptr;
return *pt_;
}
else
{
return *(this->pt_ + num);
}
}
template<class T>//每一个函数都必须模板
void Array<T>::set(T data, int num)
{
if (num < 0 || num >= length_)
{
std::cout << "入参不符合要求,不能超过预定长度或者小于0" << std::endl;
}
else
{
*(pt_ + num) = data;
}
}
template<class T>//每一个函数都必须模板
T& Array<T>::operator [](int num)
{
if (num < 0 || num >= length_)
{
std::cout << "入参不符合要求,不能超过预定长度或者小于0" << std::endl;
this->pt_ = nullptr;
return *pt_;
}
else
{
return *(pt_ + num);
}
}
main.cpp
#include <iostream>
#include <string>
#include "Array.h"
#include"Array.cpp"
using namespace std;
template<class T>//类模板作为参数,类型无比明确
void print(Array<T> &myarray)
{
for (int i = 0; i < myarray.size(); i++)
{
std::cout << myarray[i] << std::endl;
}
}
int main()
{
Array<int> myarray(5);
for (int i = 0; i < myarray.size(); i++)
{
myarray.set(i, i);
}
print(myarray);
Array<string> myarray2(6);
std::string str1 = "jamin";
for (int i = 0; i < myarray2.size(); i++)
{
str1 += "O";
myarray2.set(str1, i);
}
print(myarray2);
system("pause");
return 0;
}
2.2 final & override
C++11 final override针对虚函数
final拒绝重载,某些情况下,接口拒绝被重写
加了final关键字的虚函数,无法被重写,预留接口
override,警示符,声明我重写父类的方法,父类没有接口,会提示出错
demo.cpp
#include<iostream>
//C++11 final override针对虚函数
//final拒绝重载,某些情况下,接口拒绝被重写
//加了final关键字的虚函数,无法被重写,预留接口
//override,警示符,声明我重写父类的方法,父类没有接口,会提示出错
class People
{
public:
//final”函数必须是虚函数
virtual void print() final //虚函数无法重写
{
std::cout << "People print\n";
}
virtual void run()
{
std::cout << "People run\n";
}
};
class Person :public People
{
public:
//警示作用,强调我覆盖了父类的方法,必须是虚函数
void run() override
{
std::cout << "Person run\n";
}
};
int main()
{
Person person1;
person1.run();
person1.print();
system("pause");
return 0;
}
2.3 类模板的继承
(1)类模板可以直接继承类模板,类型必须传递;
(2)普通类继承类模板,需要明确类型实例化类模板;
(3)类模板继承普通类,常规的操作方式;
(4)类模板当作普通类,需要模板参数对类进行实例化;
#include <iostream>
#include <string>
//模板类之间继承
//类模板可以直接继承类模板,类型必须传递
//普通类继承类模板,需要明确类型实例化类模板
//类模板继承普通类,常规的操作方式
//类模板当作普通类,需要模板参数对类进行实例化
template<class T>
class People
{
public:
T x;
People() {}
People(T t) :x(t) {}
void print()
{
std::cout << " People .... " << std::endl;
}
};
template<class T>
class Person :public People<int> //继承必须明确类型
{
public:
T y;
Person(T t1, T t2) :People(t2), y(t1)
{
}
void print()
{
std::cout << "x: " << x << " y: " << y << std::endl;
}
};
class MyClass : public People<double>
{
public:
int d = 100;
MyClass(int d1, double x1) :People(x1), d(d1)
{
}
void print()
{
std::cout << "x: " << x << " d: " << d << std::endl;
}
};
int main()
{
Person<int> person1(20, 30);
person1.print();
MyClass my_class(200, 20.5);
my_class.print();
system("pause");
return 0;
}