C++——模板---函数模板---类模板

1、模板python

  • 模板的引入:
    • 模板的精神:类型参数化,即类型也是一种参数。
    • template所表明的泛型编程是C++语言中的重要组成部分。C++是一门强类型语言,没法像动态语言(如python)那样,编写一段通用的逻辑,能够把任意类型的变量传进去。泛型编程弥补了这一点摆脱了类型的限制,提升了代码的可重用性。
    • 模板是创建通用的与数据类型无关的算法的重要手段,可实现代码重用。
  • 函数模板的定义与声明:---函数模板实参推演
    • 定义:
      • template<模板参数表>返回值类型 函数名(函数形参表){......}//函数体
      • 模板参数主要是模板类型参数,尖括号中不能为空。模板类型参数由typename(或class)+标识符构成。表示该标识符表明一种潜在的内置或用户自定义数据类型。
    • 声明:
      • 函数模板的声明与函数声明不一样,函数模板的声明必须含变量名。由于二者的编译过程不同。函数模板必须先转换成模板函数,再进行编译。模板定义自己不参与编译,而是编译器模板的用户使用模板时提供的类型参数生成代码,再进行编译。这一过程成为模板的实例化。用户提供不一样的类型参数就会实例化出不一样的代码。
  • 类模板的定义与声明:---类模板实例化
    • 定义:
      • template<模板参数表> class 类名 { //类定义体
        };//注意分号不可少
         templete<模板参数表>返回类型 类名<模板参数名表>:: 成员函数名1(形参表) { ......;//成员函数定义体
        }

         模板参数表有两种:模板类型参数和非模板类型参数。算法




 

2、函数模板---template关键字用于声明开始进行泛型编程-----typename关键字用于声明泛指类型----函数模板能够自动推导类型进行调用,也能够显示指定具体类型进行调用。编程

  一、普通函数模板:数据结构

    •  1 template<typename T>
       2 int compare(const T& left,const T& right)  3 {  4 if(left<rigth)  5 {return -1;}  6 if(right<left)  7 {return 1;}
        reurn 0;
      8 } 9 10 compare<int>(1,2);//使用模板函数

  二、类的成员函数模板函数

不只普通函数能够定义为模板,类的成员函数也能够定义为模板spa

    • class printer { public: template<typename T>
      void print(const T& t) { cout<<t<<endl; } } printer p; p.print<const char*>("seu");//打印seu

  • 实参推断:

为了使用方便,除了直接为函数模板指定类型参数外,还可让编译器从传递给函数的实参推断参数类型,这一功能被称为模板实参推断。指针

  • 实参推断的使用:
    • 1 compare(1,2);//推断T的类型为int
      2 compare(1.0,2.0);//推断T的类型为double
      3 p.print("absdsaf");//推断T的类型为const char *
      4 
      5 int (*pf)(const int&,const int&)=compare;//推断T的类型为int; 6 //经过把函数模板赋值给一个指定类型的函数指针,让编译器根据这个指针的类型,对模板实参进行判断

 

  三、函数模板的重载code

函数模板之间,函数模板与普通函数之间能够重载。编译器会根据调用时提供的函数参数,调用可以处理这一类型的最特殊的版本。在特殊性上,通常遵循以下顺序:orm

  • 普通函数
  • 特殊函数(限制了T的形式的,指针,引用,容器等)
  • 普通模板(对T没有任何限制的) 
  • 如何判断哪一个模板函数更加特殊,原则是:若是模板B的全部实例均可以实例化模板A,而反过来不行,那么B就比A特殊。即B的范围大于A的范围。
    •  1 template<typename T>
       2 void func(T& t) { //通用模板函数
       3     cout << "In generic version template " << t << endl;  4 }  5 
       6 template<typename T>
       7 void func(T* t) { //指针版本
       8     cout << "In pointer version template "<< *t << endl;  9 } 10 
      11 void func(string* s) { //普通函数
      12     cout << "In normal function " << *s << endl; 13 } 14 
      15 int i = 10; 16 func(i); //调用通用版本,其余函数或者没法实例化或者不匹配
      17 func(&i); //调用指针版本,通用版本虽然也能够用,可是编译器选择最特殊的版本
      18 string s = "abc"; 19 func(&s); //调用普通函数,通用版本和特殊版本虽然也均可以用,可是编译器选择最特化的版本
      20 func<>(&s); //调用指针版本,经过<>告诉编译器咱们须要用template而不是普通函数

  四、模板函数的特化blog

有时候函数模板并不能解决个别类型的问题,咱们必须对此进行定制,这就是函数模板的特化。函数模板的特化必须把全部的模板参数所有指定。

  • 1 template<>
    2 void func(int i) { 3     cout << "In special version for int "<< i << endl; 4 } 5 
    6 int i = 10; 7 func(i); //调用特化版本



 

 

3、类模板---

类模板只能显示指定类型参数,没法自动推断参数类型。声明的泛型类型参数能够出如今类模板的任意地方。类模板必须在头文件中实现,不能分开实如今不一样的文件中。

类模板适合以相同的逻辑处理不一样数据类型的数据,所以很是适合编写数据结构相关的代码。一般用来做为容器(vector)或行为(clonable)的封装。

对于一个类模板printer,只能显示的指定参数类型进行调用

  • printer<int> p(1);正确 printer p(1);错误