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(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;
}

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值