文章目录
函数模板
概述
- 当有多个函数,他们除了形参列表的数据类型和返回类型不同之外,在函数体中所执行的操作完全相同,可以使用函数模板来对其进行统一的代替。
- 通过模板函数,减少重复的代码的出现,方便编程
函数模板的底层原理
- 首先程序在编译时候,在没有调用函数模板代指的函数的时候,并不会的会模板函数产生相关的执行代码。
- 当程序调用函数模板指代的函数的时候,会将特定的数据类型换入到函数模板中进行替换,将函数模板转成对应的模板函数,并生成相关的执行代码。
- 不调用,无执行代码;调用,生成特定数据类型的执行代码。
实例
-
编写程序,功能是查找一维数组a中的第一个值为x的元素的下标。如果不存在该元素就返回-1
-
functionTemplate.h文件
#ifndef _FUNCTIONTEMPLATE_H
#define _FUNCTIONTEMPLATE_H
#include <iostream>
using namespace std;
template <typename T> T maxElement(T a,T b)
{
return a>b?a:b;
}
/*
description:search the element x in the array a.
return the index where it firstly appear.
*/
template <typename T> int findElement(T a[],T x,int n)
{
for(int i = 0;i < n;i ++)
{
if(a[i] == x) return i;
}
return -1;
}
/*
description:show different type of array
*/
template <typename T> void show(T a[],int n)
{
for(int i =0;i < n;i ++)
{
cout<<a[i]<<" ";
}
cout<<endl;
}
#endif // _FUNCTIONTEMPLATE_H
- main测试文件
#include <iostream>
#include "functionTemplate.h"
using namespace std;
int main()
{
int a[6];
double b[6];
char c[6];
for(int i = 0;i < 6; i++)
{
a[i] = i;
b[i] = i;
c[i] = 'a' + i;
}
show(a,6);
cout<<endl;
show(b,6);
cout<<endl;
show(c,6);
cout<<endl;
cout<<findElement(a,3,6)<<endl;
cout<<findElement(b,(double)3,6)<<endl;
cout<<findElement(c,'d',6)<<endl;
return 0;
}
分析总结
- 函数模板是方便编程,减少了重复代码的书写,对于底层的程序运作,程序的执行代码仍旧是那么长
- 函数模板经过程序调用,传入了特定类型的参数,实例化成对应的模板函数
类模板
概述
- 对于仅仅只有特定的数据类型不同的类,可以使用模板类去替代所有的类。
- 比如,C++中的vector就有各种数据类型的vector,整型的,浮点型的等等,但是其功能和函数都是一致的,所以没有必要根据不同数据类型,写大量近似的数据类型。使用模板类来代替
定义
类定义
类体外的成员函数的定义
使用
C++程序运行实例
- 编写一个模板类Array
- 成员:为模板类型的一维数组
- 成员函数:
- 获取自身的长度getLength()
- 获取特定索引的元素getElement()
- 修改所有的元素为一个统一的值setElement()
Array.h文件
#ifndef _ARRAY_H
#define _ARRAY_H
using namespace std;
template <typename T,int length>
class Array
{
private:
T buffer[length];
public:
T getElement(int i)
{
return buffer[i];
}
int getLength()
{
return sizeof(buffer)/sizeof(T);
}
void setElement(T x);
};
template <typename T,int length>
void Array<T,length>::setElement(T x)
{
for(int i = 0 ;i < getLength();i ++)
{
buffer[i] = x;
}
}
#endif // _ARRAY_H
main函数测试文件
#include <iostream>
#include "Array.h"
using namespace std;
int main()
{
Array<int,10> a;
Array<double,20> b;
Array<char,30> c;
cout<<"the length of object a is:"<<a.getLength()<<endl;
cout<<"the length of object b is:"<<b.getLength()<<endl;
cout<<"the length of object c is:"<<c.getLength()<<endl;
a.setElement(100);
b.setElement(12.5);
c.setElement('\n');
cout<<"the third element fo the array a is :"<<a.getElement(3)<<endl;
cout<<"the third element fo the array b is :"<<b.getElement(3)<<endl;
cout<<"the third element fo the array c is :"<<c.getElement(3)<<endl;
return 0;
}
注意
- 需要将类的模板声明和类模板成员函数的定义放在同一个头文件
关于模板类的静态成员
- 在模板类中定义了静态成员,也不会为其分配内存空间,需要在类体外进行的声明和定义
- 需要将模板类实例化之后,才能够创建对应的类的静态对象,所有的实例化成员共享要给类的静态成员
模板实例
函数模板实例
概述
设计两个的函数模板,其功能分别是返回两个值中的较大者和返回多个值中的较大者。要求不仅能够处理整型、实型等数值性数据,而且能够省却处理字符串
C++程序实例
- 描述:设计两个函数模板,其功能分别是返回两个值中的较大者和
返回多个值中的较大者。要求不仅能够处理整型、实型等数值型数据,而且能够正确处理字符串。 - functemplate.h文件
#ifndef _FUNCTIONTEMPLATE_H
#define _FUNCTIONTEMPLATE_H
#include <iostream>
using namespace std;
template <typename T> T maxElement(T a,T b)
{
return a>b?a:b;
}
template <typename T> T maxElement(T a[],int size)
{
cout<<"template <typename T>T maxElement is being used!"<<endl;
T max = a[0];
for(int i = 1;i < size; i++)
{
max = maxElement(max,a[i]);
}
return max;
}
#endif
- functiontemplate.cpp文件
#include "functionTemplate.h"
#include <string.h>
using namespace std;
char *maxElement(char *a,char *b)
{
cout<<"char *maxElement(char *a,char *b) is being used"<<endl;
if(strcmp(a,b))
{
return a;
}
return b;
}
- main函数测试文件
#include <string.h>
#include <iostream>
#include "functionTemplate.h"
using namespace std;
int main()
{
int nArr[] = {
3,5,7,16,9,2};
double dArr[] = {
3.5,7.2,4.3,6.8};
char cArr[] = {
'a','b','c','d'};
char *sArr[] = {
"Guolong","chening","wuhaolong"};
cout<<maxElement(3,5)<<endl;
cout<<maxElement(3.5,5.2)<<endl;
cout<<maxElement('a','b')<<endl;
cout<<maxElement(sArr[0],sArr[1])<<endl;
cout<<maxElement(nArr,6)<<endl;
cout<<maxElement(dArr,4)<<endl;
cout<<maxElement(cArr,4)<<endl;
cout<<maxElement(sArr,3)<<endl;
return 0;
}
- 运行结果
分析与总结
- 在上述的问题中不能,模板函数并不能实现字符串的比较,所以只能通过对函数的重定义进行来实现,在cpp文件中实现函数
- 使用模板函数确实能够的极大的减少代码的复用率,提高编码效率
类模板程序实例
-
描述:数组Array的实现
- 成员:数组的指针 和 数组的实际长度
- 成员函数:带参数的构造函数(参数为对应的长度)、析构函数、下标符号的重载(返回特定索引的元素引用)、输出当前的元素和增加数组的长度
-
Arraytemplate.h文件
#ifndef _ARRAYTEMPLATE_
#include <iostream>
using namespace std;
template <class T>
class Array
{
private:
T *m_pArray;
int m_nSize;
public:
Array(int nSize);
~Array();
T& operator[](int index);
int Size(){
return m_nSize;}
bool addNewElement(int nAddSize);
void display();
};
//construct the array without any initialization
template<class T>
Array<T>::Array(int nSize)
{
m_nSize = nSize;
m_pArray = new T[nSize + 1];
}
//destructor of the class
template <class T>
Array<T>::~Array()
{
delete []m_pArray;
}
//the overload of the operator[]
template <class T>
T& Array<T>::operator[](int index)
{
if(index >= m_nSize || index < 0)
{
cout<<"error:out of edge!"<<endl;
//use the superfluous space to store the illegal value;
index = m_nSize;
m_pArray[index] = 0;
}
return m_pArray[index];
}
//show the array
template <class T>
void Array<T>::display()
{
for(int i = 0;i < m_nSize;i ++)
{
cout<<m_pArray[i]<<" ";
}
cout<<endl;
}
//mix the two array together
template <class T>
bool Array<T>::addNewElement(int nAddSize)
{
if(nAddSize <= 0)
{
cout<<"the new array you add must over zero!"<<endl;
return false;
}
T *pNewArray = new T[m_nSize + nAddSize];
if(pNewArray == NULL)
{
cout<<"Error:arrange the memory absortively"<<endl;
return false;
}
for(int i = 0 ;i < m_nSize;i ++)
{
pNewArray[i] = m_pArray[i];
}
delete []m_pArray;
m_pArray = pNewArray;
m_nSize = m_nSize + nAddSize;
return true;
}
#endif // _ARRAYTEMPLATE_
- main测试文件
#include <iostream>
#include "Arraytemplate.h"
using namespace std;
int main()
{
Array<int> intArray(10);
Array<double> doubleArray(10);
Array<char> charArray(10);
for(int i = 0;i < 10; i++)
{
intArray[i] = 1 + i;
doubleArray[i] = 2.5 + i;
charArray[i] = 'a' + i;
}
intArray.display();
doubleArray.display();
charArray.display();
intArray[10] = 20;
intArray.display();
intArray.addNewElement(1);
intArray[10] = 20;
intArray.display();
return 0;
- 测试结果
分析与总结
- 在模板形参列表中使用typename和class是一样的效果
- 主要是形式化的定义,记住这些格式即可