C++系列 --- 类模板概念,类模板定义和使用
今天呢,我们一起来学习下模板与泛型中的知识点,类模板的概念,类模板的定义与使用,希望大家通过本节的学习,可以对类模板有一个清晰的理解!
1、概述
用类模板来实例化一个特定的类;
编译器不能为类模板推断模板参数类型,所以为了使用类模板,我们必须在模板名后面用<>来提供额外的信息,这些信息其实就是对应着模板类参数列表里面的参数;
类模板实现同一套代码,可以应付不同的数据类型,这样就显得精简多了。
2、类模板定义
template<typename 形参名1,typename 形参名2,......typename 形参名n>
class 类名
{
};
实例
myvector类模板 模仿vector
实例化类模板的时候,必须有类的全部信息,包括类模板中成员函数的函数体;
myvector.h文件
#ifndef __MYVECTOR__
#define __MYVECTOR__
// 定义类模板
// 名字为T的模板参数,
// 用来表示myvector这个容器
// 所保存的元素类型
template<typename T>
class myvector
{
public:
// 迭代器 vector iterator
typedef T* myiterator;
public:
// 构造函数
myvector();
// 赋值运算符重载,在类模板内部使用模板名,
// 并不需要提供模板参数
myvector& operator=(const myvector&);
//myvector<T>& operator=(const myvector<T>&);
public:
// 迭代器的起始位置
myiterator mybegin();
// 迭代器的最后一个元素的下一个位置
myiterator myend();
//类模板的成员函数
public:
// 把函数的函数体(函数具体实现)
// 放在类模板的定义中
//void myfunc() {};
void myfunc();
};
// 类模板函数在类外部实现
template<typename T>
void myvector<T>::myfunc()
{
// ......
return;
}
// 重载赋值运算符,<T>表示
// 返回的是一个实例化了的myvector
template<typename T>
myvector<T>& myvector<T>::operator=(const myvector&)
{
return *this;
}
#endif
main.cpp文件
#include <iostream>
#include "myvector.h"
using namespace std;
int main(int argc, char** argv)
{
// 这个时候,编译器给生成一个具体的类
myvector<int> tmpvec1;
myvector<double> tmpvec2;
myvector<string> tmpvec2;
}
myvector是类模板名,它不是一个类名,类模板是用来实例化类类型的;所以myvector<int>,myvector<double>才是类型名(实例化的类型);所以,一个实例化的类型,总会用尖括号<>包含着模板参数。
3、类模板的成员函数
类模板成员函数,可以写在类模板定义中,这种写在类模板定义中的函数会被隐式的声明为inline函数;
类模板被实例化之后,模板的每个实例都会有自己版本的成员函数,所以,类模板的成员函数具有和这个类模板相同的模板参数;
如果你把类模板成员函数的定义写在类模板的外边,那么这个成员函数的模板参数就必须体现出来;
定义在类模板之外的成员函数必须以关键字template开头,后面接类模板参数列表,同时,在类名后面要用尖括号<>把模板参数列表里面的所有模板参数名列出来,如果是多个模板参数,用逗号分隔;
类外实现成员函数的定义
// 类模板函数在类外部实现
template<typename T>
void myvector<T>::myfunc()
{
// ......
return;
}
一个类模板虽然肯能有很多的成员函数,但是,当你实例化模板之后,如果你后续没有使用到某个函数,则这个成员函数不会被实例化,说白了,就是一个实例化的模板,它的成员函数只有在使用的时候才被实例化。
4、模板类名字的使用
// 类模板名字的使用,即T的使用
// 重载赋值运算符,<T>表示
// 返回的是一个实例化了的myvector
template<typename T>
myvector<T>& myvector<T>::operator=(const myvector&)
{
return *this;
}
5、非类型模板参数
实例:
myarray.h文件
#ifndef __MYARRAY__
#define __MYARRAY__
template<typename T,int size = 10>
class myarray
{
private:
T arr[size];
public:
void myfunc();
};
template<typename T, int size>
void myarray<T,size>::myfunc()
{
cout << size << endl;
return;
}
#endif
int size = 10,即为非类型模板参数
main.cpp文件
#include <iostream>
#include "myarray.h"
using namespace std;
int main(int argc, char** argv)
{
myarray<int, 100> tmparray1;
tmparray1.myfunc(); // 100
myarray<int> tmparray2;
tmparray2.myfunc(); //10
system("pause");
return 0;
}
实验结果
实验结果非类型模板参数的一些限制:
(1)浮点型不能左非类型模板参数,比如float,double
(2)类类型一般也不允许左非类型模板参数
好了,今天的C++模板与泛型学到这里就结束了,希望大家可以认真理解哦!!
我是奕双,现在已经毕业将近两年了,从大学开始学编程,期间学习了C需要编程,C++需要编程,Win32编程,MFC编程,毕业之后进入一家图像处理相关领域的公司,掌握了用OpenCV对图像进行处理,如果大家对相关领域感兴趣的话,可以关注我,我这边会为大家进行解答哦!如果大家需要相关学习资料的话,可以私聊我哦!