C++中的模板

1. 概念

模板是对类型的抽象,为了更好的实现多态的思想。

模板分为类模板和函数模板。

2. 函数模板

就是在函数之前声明一下模板,然后执行的时候,函数自行判断推导类型。

int add(int a, int b) {
    return a + b;
}

double add(double a, double b){
    return a + b;
}
// 如 add函数,要写多个版本

现在使用模板,只要一个函数模板就可以。

template <typename T>
T add(T a, T b){
	return a + b;
}

// template 是模板声明的关键字。
// typename 是为了定义类型参数,也可以用 class。
// T 是参数类型,名字不重要。

当执行 add 时,会根据参数,自行判断类型。

3. 显式实例化和隐式实例化

显式就是说明是什么类型,隐式就是让其自行推导。

add<int>(5, 9); //显式
add(5, 9); //隐式

我声明的这个是函数模板,在执行的时候,编译期就会被实例化为一个函数,也就是模板函数。

函数模板 -------> 经过参数推导,实例化为 ------> 模板函数。

4. 特化

函数模板可以和模板函数共存,发生重载。

函数模板之间也可以发生重载。

template <typename T>
T add(T a, T b) {
    cout << "T add(T, T)" << endl;
    return a + b;
}

int add(int a, int b) {
    cout << "int add(int, int)" << endl;
    return a + b;
}
// 这种情况下,如果 add(5, 9) 运行,调用的是 int add(int, int) 的版本。

因为函数模板要推导成模板函数,现在已经有了模板函数,就直接调用模板函数了。

也就是说,模板函数优先级高于函数模板。 模板函数 > 函数模板。

但,怎么知道这是一个模板函数?表示它是函数模板的一个特例?

// 前面加上一个 template <> 表示它是函数模板的一个特化版本即可。
template <>
int add(int a, int b) {
    cout << "int add(int, int)" << endl;
    return a + b;
}

5. 非类型参数

模板中存在一种非类型参数。可以当作形参使用。

  template <typename T, int num = 10> 
  T mul(T elem) {
      return elem * num;
  }
 // 此中的 num 就是一个非类型参数。注意,非类型参数只能是整型。   double, float 不行。

6. 可变参数

类型可以声明多个,参数也可以声明多个。

如:

  // 多个类型 和 形参
  template <typename T1, typename T2, typename T3> 
  void demo(T1 t1, T2 t2, T3 t3) {
      cout << t1 << " " << t2 << " " << t3 << endl;
  }

可以使用模板的可变类型参数。

template <typename ...T>
void demo(T ...elem){
//    输出 所有elem 的值可以利用递归print()
    print(elem...);
}

template <typename T, typename ...Arg>
void print(T e, Arg ...args){
    cout << e << " ";
    print(args...);
}

void print(){
    return;
}

... 在前为打包,

... 在后为解包。

7. 类模板

类模板就是在类上声明的模板。

注意,类外定义的成员要带上模板

template <typename T>
class Example {
public: 
    void p();
};        

template <typename T>
void Example<T>::p() {
    cout << endl; 
}     

代码:

#include <iostream>
using namespace std;

template <typename T>
T add(T a, T b) {
    cout << "T add(T, T)" << endl;
    return a + b;
}

int add(int a, int b) {
    cout << "int add(int, int)" << endl;
    return a + b;
}

template <typename T, int num = 10>
T mul(T elem) {
    return elem * num;
}

// 多个类型 和 形参
template <typename T1, typename T2, typename T3>
void print(T1 t1, T2 t2, T3 t3) {
    cout << t1 << " " << t2 << " " << t3 << endl;
}

template <typename T, typename... Arg>
void print(T e, Arg... args) {
    cout << e << " ";
    print(args...);
}

void print() {
    return;
}

template <typename... T>
void demo(T... elem) {
    // 输出 所有elem 的值可以利用递归print()
    print(elem...);
}

template <typename T>
class Example {
public:
    void p();
};

template <typename T>
void Example<T>::p() {
    cout << endl;
}

void test0() {
    demo(1, 2, 3, 4, 5, 9);
}

int main(int argc, char* argv[]) {
    test0();
    return 0;
}

posted @ 2023-07-26 22:30  zxinlog  阅读(54)  评论(0)    收藏  举报