C++菜鸟学习笔记——模板与泛型编程

来源:互联网 发布:帝国cms目录 编辑:程序博客网 时间:2024/05/15 00:12

 template <typename T> ...//建议

template <class T> ...

inline函数模板:
template <typename T> inline T max(const T&,const T&);

函数模板:
template <typename T>
int compare(const T& v1,const T& v2)
{
     if(v1<v2) return -1;
     if(v2<v1) return 1;//这里最好用<,因为只涉及到一个'<'符号的重载
     return 0;
}

函数模板的使用:
int main()
{
     cout<<compare(1,0)<<endl;//T is int;
     
     string s1="hi",s2="world";
     cout<<compare(s1,s2)<<endl;//T is string
}

类模板:
template <typename Type> class Queue{
public:
     Queue();
     Type &front();
     //...
private:
     //...
};

类模板的使用:
Queue<int> qi;                         //type is int;
Queue<vector<double>> qc;     //type is vector<double>

模板形参不能重复定义:
template <typename V,typename V> V max(const V&,const V&);//error
也不能省略定义:
template <typename V1, V2> V1 max(const V1&,const V2&);//error

很有趣的一个例子:
template <typename T,size_t N> void array_init(T (&parm)[N])
{
     for(size_t i=0;i!=N;++i)
     {
          parm[i]=0;
     }
}

使用:
int x[42];
double y[40];
array_init(x);
array_init(y);    //有意思的是,数组大小也被传进去

下面2中方法的使用:
template <typename T> T fobj(T,T);
template <typename T> T fref(const T&,const T&);
...
int a[10],b[42];
fobj(a,b);          //ok,call fobj(int*,int*)
fref(a,b);          //error,arguments aren't converted to pointer

用模板初始化函数指针:
template <typename T> int compare(const T&,const T&);
...
int (*pf)(const int&,const int&)=compare;

初始化的时候必须注意唯一性(确定性):
void func(int (*)(const string&,const string&));
void func(int (*)(const int&,const int&));
...
func(compare);//error:which instantiation of compare?

返回类型中使用模板参数的一个习惯问题:
template <typename T1,typename T2,typename T3>
T1 sum(T2,T3);//建议,因为模板参数匹配是从左到右的
long val=sum<long>(i,lng);//可以省略T2,T1的说明
...
T3 sum(T2,T1);
long val=sum<long,int,long>(i,lng);//必须说明所有的模板参数

类外部定义成员模板:
template <typename T> template <typename V>
void Queue<T>::assign(V beg,V end){
     //...
}

一个完整的Queue类:
template <typename Type> class Queue;
template <typename T>
std::ostream& operator<<(std::ostream&,const Queue<T>&);
template <typename Type> class QueueItem{
     friend class Queue<Type>;
     friend std::ostream& operator<< <Type>(std::ostream&,const Queue<T>&);

     QueueItem(const Type &t):item(t),next(0){}

     Type item;
     QueueItem *next;
};

template <typename Type> class Queue{
      friend std::ostream& operator<< <Type>(std::ostream&,const Queue<T>&);
public:
     Queue():head(0),tail(0){}
     template <typename T> Queue(T beg,T end):head(0),tail(0){ copy_elems(beg,end);}
     Queue(const Queue &q):head(0),tail(0){ copy_elems(q)}
     Queue& operator=(const Queue&);

     ~Queue(){ destroy();}

     template <typename T> viod assign(T,T);
     Type& front() { return head->item;}
     const Type &front() const { return head->item;}
     void push(const Type&);
     void pop();
     bool empty() const { return head==0;}
private:
     QueueItem<Type> *head;
     QueueItem<Type> *tail;
     
     void destroy();
     void copy_elems(const Queue&);
     template <T> void copy_elems(T,T);

};

//另外,还有一些模板特化的问题,属于高级主题