zoukankan      html  css  js  c++  java
  • 第七章 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. 在类模板内定义函数模板

      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;
      }
      
  • 相关阅读:
    Android开发使用Glide获取图片背景色淡绿色解决办法
    Android 获取 View 宽高的常用正确方式,避免为零
    Android之自定义View来接收输入法输入的内容
    FileProvider使用详解(拍照、安装APP、共享文件)
    简明 homebrew
    更优雅地使用命令行
    一篇长文说 git 基础
    chrome 浏览器的使用技巧
    前端学命令行
    cocos 碰撞系统
  • 原文地址:https://www.cnblogs.com/DreamEagle/p/12632072.html
Copyright © 2011-2022 走看看