C++学习:模板编程(泛型)

来源:互联网 发布:2017年全球数据总量 编辑:程序博客网 时间:2024/06/05 22:45

C++学习:模板编程

  1. 函数模板
  2. 类模板

简介:
众所周知,C++这门语言是集面向过程,面向对象,以及泛型编程于一体的,之前讲了面向过程,面向对象,在这里,简单讲讲泛型编程.
泛型:也就是无类型,也就是可以容纳支持的所有类型.类似java中的ArrayList集合类一样,在创建的时候去声明类型,就可以对该类型的对象进行集中的管理操作.泛型编程的出现是为了是解决过多冗余的代码而生,想想如果做一个算法的函数,要支持所有类型的,在没有泛型之前可能要将所有类型都需要重新写一遍,那么如果通过泛型编程的话,这个时候就可以大大的降低我们的代码量.
泛型编程是独立于特定类型的方式的编写代码
而模板用于表达逻辑结构相同,但是具体元素类型不同的数据对象的通用行为
这也就是泛型编程的好处,在底层代码中,泛型的应用是十分广泛的

模板是泛型编程的基础;
通过模板可以快速的建立具有类型安全的类库集合和函数集合,使用模板可以操作不同的数据类型,从而避免需要为每一个数据类型产生一个特定的类或者函数


提示:

博主:章飞_906285288
博客地址;http://blog.csdn.net/qq_29924041


函数模板

在之前的文章中,应该有过关于泛型的简单介绍,在这里做个统筹汇总,在C++中叫函数模板,在java中也就直接叫泛型编程.

所谓函数模板:实际上是建立一个通用函数,它所用到的数据的类型(包括返回值类型、形参类型、局部变量类型)可以不具体指定,而是用一个虚拟的类型来代替(实际上是用一个标识符来占位),等发生函数调用时再根据传入的实参来逆推出真正的类型。这个通用函数就称为函数模板(Function Template)。

函数模板的定义类型:
注意:
返回值类型,形式参数类型,局部变量类型都可以用虚拟类型来代替

定义函数模板的一般形式为:template < typename T> 返回值类型 函数名 (参数表) {}

或者:

template < class T> 返回值类型 函数名 (参数表) {}

如一下函数所示:

#include<iostream>using namespace::std;namespace zzf{  //定义加减乘除的泛型函数模板,这个时候就不需要判断类型了,对于对象的话,如果这个对象对这些运算符进行重载过的话,  //同样是支持这些运算的  //template <typename T>  template <class T>  T add(T a,T b){    return a + b;  } template <typename T>   T del(T a,T b){    return a - b;  } template <class T>  T mul(T a,T b){    return a * b;  } template <class T>  T div(T a,T b){    return a / b;  }}using namespace::zzf; int main(int argc,char* argv[]){  float ret_1 = add(10.002,20.0006);  int ret_2 = add(10,5);  cout<<"ret_1:" << ret_1<<endl;  cout<<"ret_2:" << ret_2<<endl;  return 0;}

在上述的代码中,采用的就是无类型的泛型函数模板形式.


类模板

类模板使用户可以为类定义一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值能取任意类型,它跟函数模板类似
类模板是对一批成员数据类型不同的类的抽象,程序员只要为这一批类所组成的整个类家族创建一个类模板,给出一套程序代码,就可以用来生成多种具体的类

类模板就是将要处理的对象的类型参数化,是程序能够处理不同的对象(数据类型)

类模板的定义

templete <模板参数表>  //参数表可以是多个class 类名{    //类成员声明};//在类模板以外定义其成员templete <模板参数表>类型名 类名<模板参数表> ::函数名(参数表){}

对上面的函数进行简单封装

/* * =========================================================================== * *       Filename:  caculatorTemplate.h *    Description:   *        Version:  1.0 *        Created:  20170625222620秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#ifndef __CACULATORTEMPLATE_H__#define __CACULATORTEMPLATE_H__template <class T>class Caculator{  public:    Caculator(){    }    T add(T a,T b){      return a + b;    }    T del(T a,T b){      return a - b;    }    T mul(T a,T b){      return a * b;    }    T div(T a,T b){      return a / b;    }    ~Caculator(){    }  private:};#endif

测试代码

/* * =========================================================================== * *       Filename:  caculatorTemplateTest.cpp *    Description:   *        Version:  1.0 *        Created:  2017年06月25日 22时31分22秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#include<iostream>#include"caculatorTemplate.h"using namespace::std;int main(int argc,char* argv[]){ //创建类的实例,注意,这个是需要指定类型T的,生成类的模板  Caculator<int> cacultor;  cout<<cacultor.add(10,20)<<endl;  return 0;}

注意
1:在创建类的模板时候,是需要去指定具体的类型的
2:类模板和模板类的区别:
类模板是模板的定义,不是一个实实在在的类,定义中使用的参数是通用类型参数
模板类是实实在在的类,是类模板的实例化.类中的参数被实际类型所代替
类模板是模板,模板类是类,模板是使用.类是定义

案例代码:打造属于自己的堆栈管理的模板类

/* * =========================================================================== * *       Filename:  stack.h *    Description:   *        Version:  1.0 *        Created:  2017年06月26日 21时48分06秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#ifndef __STACK_H__#define __STACK_H__namespace zzf{#include<iostream>using namespace::std;template <class T>class Stack{  public:    Stack():top_pointer(0){      array[top_pointer] = 0;    }    void push(const T& t);    T pop();    T getIndexType(int index); private:    //C++中一般使用的是枚举类型来定义常量     enum {ssize = 100};     T array[ssize];     int top_pointer;  };/* * *模板类必须将定义在头文件中 * */template <class T>void Stack<T>::push(const T &t){   if(top_pointer < 0){    cout << "error top_pointer"<<endl;  }else{    if(top_pointer < ssize){        array[top_pointer] = t;        top_pointer++;    }  }}template <class T>T Stack<T>::pop(){  if(top_pointer < 0){    return array[0];  }else{    return array[--top_pointer];  }}template<class T>T Stack<T>::getIndexType(int index){   if(index < 0) {     cout<<"error index"<<endl;     return array[0];   } else {      if(index > top_pointer){        cout<<"error index"<<endl;        return array[0];      }else{        return array[index];      }   }}}#endif
/* * =========================================================================== * *       Filename:  stackTest.cpp *    Description:   *        Version:  1.0 *        Created:  2017年06月26日 21时59分50秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#include<iostream>#include"stack.h"using namespace::std;using namespace::zzf;int main(int argc,char* argv[]){  Stack<int> stack;  stack.push(2);  stack.push(4);  stack.push(5);  stack.push(6);  stack.push(8);  stack.push(12);  stack.push(18);  cout<<stack.pop()<<endl;  cout<<stack.getIndexType(3)<<endl;  return 0;}

注意:
在模板类中,函数的声明和定义都需要在头文件中进行,否则会出现未定义的引用的错误

原创粉丝点击