模板和泛型编程???从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(例如上面的例子)

 

 

 

 

 

你可能感兴趣的:(编程)