欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-20 15:45:26
[TOC] 作用:提高程序可复用性,程序编译时自动生成相应函数 函数模板和类模板中的类型参数表中 和`typename`可相互替换 函数模板 2. 格式 3. 匹配顺序 参数完全匹配的普通函数 参数完全匹配的模板函数(匹配模板函数时,不会进行自动类型转换) 实参经过自动类型转换 后匹配的普通函数 上 ......

目录

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

函数模板和类模板中的类型参数表中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. 在类模板内定义函数模板

    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;
    }