C++模板初阶:泛型编程的强大工具

C++模板初阶:泛型编程利器

目录

C++模板初阶:泛型编程的强大工具

1. 泛型编程简介

2. 函数模板

2.1 函数模板概念

2.2 函数模板格式

2.3 函数模板原理

2.4 函数模板实例化

隐式实例化

显式实例化

2.5 模板参数匹配原则

3. 类模板

3.1 类模板定义格式

3.2 类模板实例化

总结


C++模板初阶:泛型编程的强大工具

1. 泛型编程简介

在C++编程中,我们经常需要为不同类型实现相同功能的函数。例如,实现一个通用的交换函数:

void Swap(int& left, int& right) {
    int temp = left;
    left = right;
    right = temp;
}

void Swap(double& left, double& right) {
    double temp = left;
    left = right;
    right = temp;
}

void Swap(char& left, char& right) {
    char temp = left;
    left = right;
    right = temp;
}

使用函数重载虽然可行,但存在明显缺点:

  1. 代码复用率低 - 每增加一个新类型就需要编写一个新函数
  2. 可维护性差 - 一个错误可能影响所有重载版本

​泛型编程​​应运而生,它允许我们编写与类型无关的通用代码,是代码复用的一种重要手段。模板正是泛型编程的基础。

2. 函数模板

2.1 函数模板概念

函数模板代表了一个函数家族,它与类型无关,使用时根据实参类型产生特定的类型版本。

2.2 函数模板格式

template<typename T1, typename T2, ..., typename Tn>
返回值类型 函数名(参数列表) {}

例如,通用交换函数模板:

template<typename T>
void Swap(T& left, T& right) {
    T temp = left;
    left = right;
    right = temp;
}

注意:

  • typename是定义模板参数的关键字
  • 也可以用class代替typename(但不能用struct

2.3 函数模板原理

函数模板本身不是函数,而是编译器生成具体函数的模具。编译器在编译阶段根据传入的实参类型推演模板参数,生成对应的函数代码。

例如,当使用double类型调用Swap时,编译器会生成专门处理double的代码;对于char类型也是如此。

2.4 函数模板实例化

使用不同类型的参数调用函数模板称为​​实例化​​,分为两种方式:

隐式实例化

让编译器根据实参自动推演模板参数类型:

template<class T>
T Add(const T& left, const T& right) {
    return left + right;
}

int main() {
    int a1 = 10, a2 = 20;
    double d1 = 10.0, d2 = 20.0;
    Add(a1, a2);    // T被推演为int
    Add(d1, d2);    // T被推演为double
    
    // Add(a1, d1);  // 错误:无法确定T应为int还是double
    Add(a1, (int)d1); // 解决方案1:强制类型转换
    return 0;
}
显式实例化

在函数名后的<>中指定模板参数的实际类型:

int main() {
    int a = 10;
    double b = 20.0;
    Add<int>(a, b);  // 显式指定T为int
    return 0;
}

如果类型不匹配,编译器会尝试隐式转换,失败则报错。

2.5 模板参数匹配原则

  1. ​非模板函数优先​​:当非模板函数和同名函数模板都匹配时,优先调用非模板函数
// 专门处理int的加法函数
int Add(int left, int right) {
    return left + right;
}

// 通用加法函数模板
template<class T>
T Add(T left, T right) {
    return left + right;
}

void Test() {
    Add(1, 2);       // 调用非模板函数
    Add<int>(1, 2);  // 调用模板生成的版本
}
  1. ​更优匹配原则​​:如果模板能产生更好匹配的函数,则选择模板版本

  2. ​类型转换限制​​:模板函数不允许自动类型转换,而普通函数可以

3. 类模板

3.1 类模板定义格式

template<class T1, class T2, ..., class Tn>
class 类模板名 {
    // 类内成员定义
};

示例:栈类模板

#include <iostream>
using namespace std;

template<typename T>
class Stack {
public:
    Stack(size_t capacity = 4) {
        _array = new T[capacity];
        _capacity = capacity;
        _size = 0;
    }
    
    void Push(const T& data);
    
private:
    T* _array;
    size_t _capacity;
    size_t _size;
};

// 类模板成员函数定义
template<class T>
void Stack<T>::Push(const T& data) {
    // 实现代码
}

注意:模板的声明和定义通常放在同一个文件中,分离到.h和.cpp文件可能导致链接错误。

3.2 类模板实例化

类模板实例化与函数模板不同,必须在类模板名后跟<>并指定具体类型:

Stack<int> intStack;     // 实例化为int类型的栈
Stack<double> dblStack;  // 实例化为double类型的栈

类模板名本身不是真正的类,实例化后的结果才是真正的类类型。

总结

C++模板是泛型编程的核心工具,它能够:

  • 提高代码复用率
  • 增强代码可维护性
  • 保持类型安全

掌握函数模板和类模板的使用是成为高级C++程序员的重要一步。在实际开发中,合理使用模板可以大幅减少重复代码,提高开发效率。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值