`

模板和泛型编程???从P269继续

 
阅读更多

参考书 <C++ By Dissection>

 

In C++, there are 3 different ways to employ generic coding techniques:

         void* pointers,

         Templates,

         Inheritance.

 

一、为什么使用模板进行泛型编程更好

 

举例:通用数组拷贝

 

方法一、二:使用void* 和 template

可以用void*或template来实现“通用数组拷贝 ”,但是后者 有以下优势——

(1)按元素拷贝,不依赖平台,增强可移植性

        void*因为不知道每个元素的大小elementSize,只能将elementSize作为参数传入,但C++中类型的长度依赖平台,因此移植性不好。

(2)若源和目的数组类型不同,提供类型保护 (编译时报错unification error)。

        void*不能满足这个要求。

#include <iostream>
using namespace std;

//ordinary
int transfer1(int from[], int to[], int size){
    for(int i=0;i<size;i++){
            to[i]=from[i];
    }
    return size;
}

//void* generic assignment function
int transfer2(void* from, void* to, int elementSize, int size){
    int nBytes=elementSize*size;
    
    for(int i=0;i<nBytes;i++){
            static_cast<char*>(to)[i]=static_cast<char*>(from)[i];
    }
    return size;
}

//template generic assignment function
template<class T>
int transfer3(T* from, T* to, int size){
    for(int i=0;i<size;i++){
            to[i]=from[i];
    }
    return size;
}

template<class T>
void printArr(T from[], int size){
     for(int i=0;i<size;i++)
             cout<<from[i]<<"\t";
     cout<<endl;
}

int main(void){
    int a[10]={1,2,3,4,5,6,7,8,9,10},b[10];
    double c[20]={10,9,8,7,6,5,4,3,2,1},d[20];

    transfer1(a,b,10);
    printArr(b,10);
    
    //使用void* 只能逐字节拷贝
    transfer2(c,d,8,10);
    printArr(d,10);
    
    //使用模板,可以仍然逐元素拷贝 
    d[1]++;
    transfer3(d,c,10);
    printArr(c,10);
    
    //相比void*,template仍然提供类型保护(type-safety) 
    transfer3(a,c,10);  //报错
    transfer2(a,c,4,10); //不报错
    
    system("pause");
    return 0;
}

 

方法三:使用宏定义

我来评价一下宏定义实现泛型编程的优势和劣势——

 

(1)宏定义优势:

简单性(Simplicity)、习惯性(familiarity)、高效性(Efficiency)。

其中,习惯性是由于在C编程中使用宏(macros)的传统;高效性主要因为没有函数调用的开销。

 

(2)宏定义劣势:

没有类型保护(type-safety)、预期外的计算(unanticipated evaluations)、范围问题(Scoping problem)

其中,与使用模板对比,解释一下“预期外的计算”。例如,计算立方,

可以使用宏

#define CUBE(X)  ((X)*(X)*(X))

可以使用模板

template<class T> T cube(T x) {return x*x*x;}

现在需要计算(sqrt(7))³

如果使用宏,CUBE(sqrt(7)),因为是直接文本替换,计算了三次sqrt(7);

如果使用函数,cube(sqrt(7)),则只调用一次sqrt(7)。

这样一来,虽然宏没有函数调用的开销(使用对战的机制),但是重复的计算使得它的优势得不偿失:(

 

#include <iostream>
using namespace std;

#define COPY(A,B,N)\
        {int i; \
        for(i=0;i<(N);++i) (B)[i]=(A)[i];}

template<class T>
void printArr(T from[], int size){
     for(int i=0;i<size;i++)
             cout<<from[i]<<"\t";
     cout<<endl;
}

int main(void){
    int a[10]={1,2,3,4,5,6,7,8,9,10},b[10];
    double c[20]={10,9,8,7,6,5,4,3,2,1},d[20];
    
    COPY(a,b,10);
    printArr(b,10);
    
    system("pause");
    return 0;
}
 

二、使用模板

 

1. Template Class 模板类


2. Function Templates 函数模板
Many functions have the same code body, regardless of type(例如上面的例子)

 

 

 

 

 

分享到:
评论

相关推荐

    java开源包1

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    java开源包11

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    java开源包2

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    java开源包3

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    java开源包6

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    java开源包5

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    java开源包10

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    java开源包4

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    java开源包8

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    java开源包7

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    java开源包9

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    java开源包101

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    Java资源包01

    使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息队列系统。 Java文件上传组件 COS FAT文件系统读写类库 fat32-lib ...

    JAVA上百实例源码以及开源项目源代码

    在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天...

    JAVA上百实例源码以及开源项目

    在有状态SessionBean中,用累加器,以对话状态存储起来,创建EJB对象,并将当前的计数器初始化,调用每一个EJB对象的count()方法,保证Bean正常被激活和钝化,EJB对象是用完毕,从内存中清除…… Java Socket 聊天...

Global site tag (gtag.js) - Google Analytics