第七章 2.泛型编程(模板)

作用:提高程序可复用性,程序编译时自动生成相应函数

函数模板和类模板中的类型参数表中classtypename可相互替换

函数模板

  1. 格式

    template<class T1,class T2,...>
    返回值类型 模板名(参数表){
        函数体
    }
    
  2. 匹配顺序

    • 参数完全匹配的普通函数
    • 参数完全匹配的模板函数(匹配模板函数时,不会进行自动类型转换)
    • 实参经过自动类型转换 后匹配的普通函数
    • 上述匹配均不存在则报错
  3. 可通过模板函数名<类型>不通过参数实例化

  4. 模板函数也可以重载,只要形参表或类型参数表不同即可

  5. 支持函数指针类型

    #include<iostream>
    using namespace std;
    template<class T,class Pred>
    void Map(T s,T e,T x,Pred op){
    	for(;s!=e;s++,x++)  *x=op(*s);
    }
    double Square(double x){return x*x;}
    int Cube(int x){return x*x*x;}
    
    template<class T>
    void Output(T &arr){
    	for(int i=0;i<(sizeof(arr)/sizeof(*arr));++i) cout<<arr[i]<<" ";
    	cout<<endl; 
    }
    int main(){
    	int a[5]={1,2,3,4,5},b[5];
    	double d[5]={1.1,2.2,3.3,4.4,5.5},c[5];
    	Map(a,a+5,b,Square);
    	Output(b);
    	Map(a,a+5,b,Cube);
    	Output(b);
    	Map(d,d+5,c,Square);
    	Output(c);
    	return 0;
    }
    

类模板

  1. 定义方式:

    template<class T1,class T2,...>
    class ClassName{
        Member Function;
        Member Variable;
        ReturnType Func(Parameter Table);
    }
    //在类外定义成员函数
    template<class T1,class T2,...>
    ReturnType ClassName<T1,T2,...>::Func(Parameter Table){ ... }
    //通过类模板定义对象
    ClassName<T1,T2,...> Obj;
    
    //类模板的类型参数表可以包含非类型参数
    template<class T,int size>
    class Count{
        public:
        	T arr[size];
        	void Output(){
                for(int i=0;i<size;++i) cout<<arr[i]<<endl;
            }
    }
    Count<double,50> test;
    
  2. 在类模板内定义函数模板

    template<class T1>
    class Test{
    	public:
    		template<class T2>
    		void Func(T2 a){
    			cout<<a<<endl;
    		}
    };
    int main(){
    	Test<int> a;
    	a.Func("Test");
    	return 0;
    }
    
  3. 编译器由类模板生成类的过程称为类的实例化,生成的类称为模板类

  4. 同一类模板生成的不同模板类不兼容(即两个独立不同的类型)

类模板与派生

  1. 类模板从类模板派生

  2. 类模板从模板类派生

  3. 类模板从普通类派生

  4. 普通类从模板类派生

    template<class T1,class T2>
    class A{
        T1 v1;
        T2 v2;
    }
    //类模板从类模板中派生
    template<class T1,class T2> 
    class B:public A<T2,T1>{ //A模板实例化顺序不一定相同
        T1 v3;
        T2 v4;
    }
    //类模板从模板类派生
    template<class T>
    class B:public A<int,double>{}
    //类模板从普通类中派生
    class C{int a;}
    template<class T> 
    class B:public C{
        T val;
    }
    //普通类从模板类中派生
    class D:public A<int,double>{ int a;}
    

类模板与友元

  1. 函数、类、类成员函数作为类模板友元

    void Func1(){}
    class A{
        int a;
        public:
        void Func(){}
    }
    template<class T>
    class B{
        T a;
        public:
        friend void Func1(); //友元函数
        friend class A; //友元类
        friend void A::Func(); //类成员函数作为友元类
    }
    
  2. 函数模板作为类模板友元

    template<typename T1,typename T2>
    class Pair{
    	T1 key;
    	T2 value;
    public:
         Pair(T1 k,T2 v):key(k),value(v){}
         //函数模板作为类模板友元
         template<class T3,class T4> //不能写T1、T2,否则可能报错
         friend ostream& operator<< (ostream &out,const Pair<T3,T4> &p); 
    };
    template<class T1,class T2>
    ostream& operator<< (ostream& out,const Pair<T1,T2> &p){
    	return out<<"("<<p.key<<","<<p.value<<")"<<endl;
    }
    
  3. 函数模板作为类的友元

    class A{
        int v;
    public:
        A(int n):v(n){}
        template<class T>
        friend void Print(const T& p); 
    }
    template<class T>
    void Print(const T& p){cout<<p.v;}
    int main(){
        A a(10);
        Print(a);
        return 0;
    }
    
  4. 类模板作为类模板友元

    template<class T>
    class A{
        T v;
        public:
        A(int n):v(n){}
        template<class T2> //不能写成T,可能报错
        friend class B;
    }
    template<class T>
    class B{
       public:
            void Func(){
                A<int> o(10);
                cout<<o.v<<endl;
            }
        }
    

类模板中的static成员

  1. 统一类模板的不同类型的实例static相互独立,相同类型示例共用

    class A{
    	static int count;
    	public:
    		void PrintCnt(){ cout<<count<<endl; }
    		A(){count++;}
    		~A(){count--;}
    		A(A&){count++;}
    };
    template<> int A<int>::count=0; //类模板中static变量声明方式
    template<> int A<double>::count=0;
    int main(){
    	A<int> a,c;
    	a.PrintCnt(); //2
    	A<double> b;
    	b.PrintCnt(); //1
    	return 0;
    }
    
posted @ 2020-04-04 15:33  DreamEagle  阅读(195)  评论(0编辑  收藏  举报