C++程序笔记——模板

函数模板

概述

  • 当有多个函数,他们除了形参列表的数据类型和返回类型不同之外,在函数体中所执行的操作完全相同,可以使用函数模板来对其进行统一的代替。
  • 通过模板函数,减少重复的代码的出现,方便编程

函数模板的底层原理

  • 首先程序在编译时候,在没有调用函数模板代指的函数的时候,并不会的会模板函数产生相关的执行代码。
  • 当程序调用函数模板指代的函数的时候,会将特定的数据类型换入到函数模板中进行替换,将函数模板转成对应的模板函数,并生成相关的执行代码。
  • 不调用,无执行代码;调用,生成特定数据类型的执行代码。

实例

  • 编写程序,功能是查找一维数组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是一样的效果
    在这里插入图片描述
    在这里插入图片描述
  • 主要是形式化的定义,记住这些格式即可

猜你喜欢

转载自blog.csdn.net/Blackoutdragon/article/details/108910662