天天看点

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

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(,);
  int ret_2 = add(,);

  cout<<"ret_1:" << ret_1<<endl;
  cout<<"ret_2:" << ret_2<<endl;
  return ;
}
           

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

类模板

类模板使用户可以为类定义一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值能取任意类型,它跟函数模板类似

类模板是对一批成员数据类型不同的类的抽象,程序员只要为这一批类所组成的整个类家族创建一个类模板,给出一套程序代码,就可以用来生成多种具体的类

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

类模板的定义

templete <模板参数表>  //参数表可以是多个
class 类名{
    //类成员声明
};

//在类模板以外定义其成员

templete <模板参数表>
类型名 类名<模板参数表> ::函数名(参数表){

}
           

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

/*
 * ===========================================================================
 *
 *       Filename:  caculatorTemplate.h
 *    Description:  
 *        Version:  
 *        Created:  年月日 时分秒
 *       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(,)<<endl;
  return ;
}
           

注意

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(){
      array[top_pointer] = ;
    }
    void push(const T& t);
    T pop();
    T getIndexType(int index);
 private:
    //C++中一般使用的是枚举类型来定义常量
     enum {ssize = };
     T array[ssize];
     int top_pointer;
  };

/* *
 *模板类必须将定义在头文件中
 * */

template <class T>
void Stack<T>::push(const T &t){ 
  if(top_pointer < ){
    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 < ){
    return array[];
  }else{
    return array[--top_pointer];
  }
}


template<class T>
T Stack<T>::getIndexType(int index){
   if(index < ) {
     cout<<"error index"<<endl;
     return array[];
   } else {
      if(index > top_pointer){
        cout<<"error index"<<endl;
        return array[];
      }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();
  stack.push();
  stack.push();
  stack.push();
  stack.push();
  stack.push();
  stack.push();

  cout<<stack.pop()<<endl;
  cout<<stack.getIndexType()<<endl;

  return ;
}
           

注意:

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

继续阅读