一、模板概述
1.1 核心概念
模板是 C++泛型编程的核心机制,提供与类型无关的代码复用能力。
1.2 核心关键字
二、函数模板
2.1 基础语法
template <typename T>返回值类型 函数名(参数列表){// 通用逻辑,不依赖具体类型}
2.2 基础实战案例:通用最大值
#include<iostream>#include<string>using namespace std;template <typename T>inline T const& Max(T const& a, T const& b){return a < b ? b : a;}intmain(){cout << Max(39, 20) << endl;cout << Max(13.5, 20.7) << endl;cout << Max(string("Hello"), string("World")) << endl;return 0;}
2.3 通用交换函数
#include<iostream>using namespace std;template<typename T>void swapData(T &a, T &b){T temp = a;a = b;b = temp;}intmain(){int a = 10, b = 20;double x = 3.14, y = 6.66;swapData(a, b);swapData(x, y);return 0;}
2.4 多参数函数模板
#include<iostream>using namespace std;template<typename T1, typename T2>void printTwoData(T1 a, T2 b){cout << a << " | " << b << endl;}intmain(){printTwoData(100, "C++模板");printTwoData(9.99, false);return 0;}
2.5 函数模板调用方式
2.6 函数模板限制
三、类模板
3.1 基础语法
template <classT>class 类名{public:T 成员变量;T 成员函数(T val);};
3.2 通用栈类实战
#include<iostream>#include<vector>#include<stdexcept>using namespace std;template <class T>class Stack{private:vector<T> elems;public:voidpush(T const&);voidpop();T top()const;boolempty()const{ return elems.empty(); }};// 类外实现成员函数必须携带模板头template <class T>void Stack<T>::push(T const& elem){elems.push_back(elem);}template <class T>void Stack<T>::pop(){if (empty()) throw out_of_range("栈为空");elems.pop_back();}template <class T>T Stack<T>::top() const{if (empty()) throw out_of_range("栈为空");return elems.back();}intmain(){Stack<int> intStack;Stack<string> strStack;return 0;}
3.3 自定义通用数组类
#include<iostream>using namespace std;template<class T>class MyArray{private:T arr[100];int size;public:MyArray() : size(0) {}voidadd(T val){ arr[size++] = val; }T get(int idx){ return arr[idx]; }};intmain(){MyArray<int> intArr;MyArray<string> strArr;intArr.add(666);strArr.add("模板编程");return 0;}
3.4 类模板默认参数
#include<iostream>using namespace std;// 设置默认类型为 inttemplate<class T = int>class Demo{public:T num;};intmain(){Demo<> d1; // 使用默认 intDemo<double> d2; // 自定义类型return 0;}
四、模板特化
4.1 全特化
对单一具体类型完全重写模板实现,优先级最高。
#include<iostream>#include<cstring>using namespace std;// 通用模板template<class T>class Compare{public:boolisEqual(T a, T b){return a == b;}};// char* 全特化版本template<>class Compare<char*>{public:boolisEqual(char* a, char* b){return strcmp(a, b) == 0;}};
4.2 偏特化(局部特化)
仅约束部分参数、指针、const 等修饰,仅类模板支持偏特化。
#include<iostream>using namespace std;// 通用模板template <typename T>class DataDeal{public:voidprint(){ cout << "普通类型处理" << endl; }};// 指针类型偏特化template <typename T>class DataDeal<T*>{public:voidprint(){ cout << "指针类型偏特化处理" << endl; }};intmain(){DataDeal<int> d1;DataDeal<int*> d2;d1.print();d2.print();return 0;}
4.3 特化优先级
全特化 > 偏特化 > 通用模板
五、可变参数模板(C++11)
5.1 语法说明
5.2 递归展开打印案例
#include<iostream>using namespace std;// 递归终止voidprintArgs(){cout << endl;}// 可变参数模板template<typename T, typename... Args>void printArgs(T first, Args... args){cout << first << " ";printArgs(args...);}intmain(){printArgs(10, 3.14, "C++", 'A', true);return 0;}
5.3 可变参数类模板
template<typename... Args>classTupleWrap;template<typename T, typename... Args>classTupleWrap<T, Args...>{private:T val;TupleWrap<Args...> next;public:TupleWrap(T v, Args... rest) : val(v), next(rest...) {}void show() { cout << val << " "; next.show(); }};template<>classTupleWrap<> { public: void show(){} };
六、模板继承
6.1 普通类继承类模板
#include<iostream>using namespace std;template<typename T>class Base{protected:T data;public:voidsetData(T d){ data = d; }T getData(){ return data; }};// 普通子类指定具体类型class Son : public Base<int>{public:voidfunc(){ cout << getData() << endl; }};
6.2 模板继承模板(泛型继承)
#include<iostream>using namespace std;template<typename T>class Parent{protected:T num;};template<typename T>class Child : public Parent<T>{public:// 依赖名称必须加 this->voidsetNum(T n){ this->num = n; }voidshow(){ cout << this->num << endl; }};
关键规则:模板继承中访问父类成员,必须加
this->消除编译器依赖歧义。
七、函数模板重载与特化
7.1 重载规则
普通函数 > 模板特化 > 通用模板
#include<iostream>using namespace std;template<typename T>void func(T t) { cout << "通用模板" << endl; }// 普通函数重载voidfunc(int t){ cout << "普通函数" << endl; }// 全特化template<>void func<double>(double d) { cout << "double 特化" << endl; }
八、分离编译问题(工程重点)
8.1 问题现象
类模板头文件声明、cpp 文件实现,编译正常,链接报错。
8.2 根本原因
模板为延迟实例化,仅在被使用时生成代码;
单独编译 cpp 文件不会实例化模板,链接时找不到函数实现。
夜雨聆风