C++泛型编程

C++泛型编程

         STL(Standard Template Library)主要由两种组件组成:1)容器,包括vectorlistmap等;2)操作上述容器的泛型算法,包括find()sort()等。

         泛型算法提供了许多可作用于容器类及数组类型上的操作。这些算法之所以被称为泛型,因它们与它们所要操作的元素类型无关。

         泛型算法通过function template技术,达到与操作对象的类型相互独立;此外采用一对iterator(first以及last)来标识所要迭代的元素范围,即不直接操作容器本身,从而实现与容器无关。

        本文以下内容通过引入查找算法,从解决问题的角度来剖析C++泛型编程思想,同时本文主要侧重于泛型编程思想、思维,但并不关注泛型算法本身。

         1.查找算法

         若此值存在于vector中,则返回一个指针指向该值;反之则返回0,以表示该值并不存在于vector中。

int* find(const vector<int> &vec, int value)
{
     for(int i=0; i<vec.size(); ++i)
         if(vec[i] == value)
            return &vec[i];
            
     return 0;
}

         2. 函数模板

         若要此函数能处理任何类型,即与操作对象类型无关,则引入函数模板,以function template形式呈现。需要指出,该定义存在equality(相等)运算符。

template <typename elemType>
elemType* find(const vector<elemType> &vec, const elemType &value)
{
     for(int i=0; i<vec.size(); ++i)
         if(vec[i] == value)
            return &vec[i];
            
     return 0;
}

        3.指针运算

        若要该函数能处理vectorarray内的任意类型元素,即与容器本身无关,需要指出,该元素类型的equality运算符皆已定义。很自然考虑到采用函数重载来实现,但本文不建议采用重载方式来实现。

         本文采取化整为零的策略,将问题简单化的方式。由于vectorarray为连续性容器,可以采用指针来指定容器起始位置,此外通过增加一个参数,用来表示容器的结束位置,从而使容器类型从参数类型中消失。以下存在两种解决方式,其本质内容是一致的。

           1) 非标兵方式

template <typename elemType>
elemType* find(const elemType *lt, int size, const elemType &value)
{
     if(!lt || size <1) return 0;
     
     for(int i=0; i<size; ++i, ++lt)
         if(*lt == value)
            return lt;
            
     return 0;
}

         2) 标兵方式       

template <typename elemType>
elemType* find(const elemType *first, const elemType *last, const elemType &value)
{
     if(!first || !last) return 0;
     
     for(; first!=last; ++first)
         if(*first == value)
            return first;
            
     return 0;
}

       4.迭代器Iterator

        对于泛型编程,上述讨论忽略了非连续性容器,如list,但指针的算术运算并不适用于list。因此,为了真正做到与容器无关,我们引入迭代器Iterator

template <typename IteratorType, typename elemType>
IteratorType find(const IteratorType first, const IteratorType last, const elemType &value)
{
    for(; first!=last; ++first)
         if(*first == value)
            return first;
            
     return last;
}

         find()的实现使用了底部元素类型的equality运算符,若底部元素所属类型并未提供该运算符,或者用户希望赋予该运算符不同意义,则上述find()的弹性就稍显不足了。解决方案存在两个:1)传入一个函数指针,取代原来固有的equality运算符;2)运用所谓的function object

          以下采用传入函数指针方式实现。

template <typename IteratorType, typename elemType>
IteratorType find(const IteratorType first, const IteratorType last, const elemType &value, bool (*fun)(elemType, elemType))
{
    for(; first!=last; ++first)
         if(fun(value, *first))
            return first;
            
     return last;
}

        5. 函数对象

        函数对象(function object)是某种class的实例对象,这类class对函数调用运算符做了重载操作,如此则可使function object被当成一般函数来使用。

template <typename IteratorType, typename elemType, typename Fun>
IteratorType find( IteratorType first, IteratorType last,  elemType &value, Fun fun)
{
   while((first=find_if(first, last, bind2nd(fun, value)))!=last)
	 return first;

   return last;
}

           6.源码测试    
         为验证本文给出的C++泛型编程思想,限于时间因素,仅对函数对象部分进行验证。

         测试源代码如下:

#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;

template <typename IteratorType, typename elemType, typename Fun>
IteratorType find( IteratorType first, IteratorType last,  elemType &value, Fun fun)
{
   while((first=find_if(first, last, bind2nd(fun, value)))!=last)
	  return first;

   return last;
}

int main()
{
    int ia[8]={1,1,2,3,5,8,13,21};
    int data =0;
    for(int i =0; i<3; i++)
    {
        cout<<"input the data:"<<endl;
        cin>>data;
	int*p=find(ia, ia+8, data, equal_to<int>());
	if(p==ia+8)
           cout<<"fail!"<<endl;
	else
	   cout<<*p<<endl;
     }

	return 0;
}


由于数组也是容器,因此本文采用数组进行测试也无可厚非。

测试结果如下:

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值