类模板和函数模板的实例化详解

泛型编程:编写与类型无关的通用代码,实现代码复用。 模板是泛型编程的基础

类模板和函数模板都是模板,并不是真正的函数和类,只有给了模板参数才能实例化出函数和类

a.类模板有两种给模板参数的方式1.显式给2.缺省给

b.函数模板有三种给模板参数方式:1.显式给 2.缺省给 3.推导给

调用函数时,参数列表中如果有模板参数,则编译器可以通过函数参数推导模板参数

1. 类模板(Class Template)

类模板用于定义 与类型无关的类,使用时需要显式或隐式指定模板参数来实例化具体的类。

(1) 定义类模板

cpp

template <typename T>  // T 是模板参数
class MyVector {
private:
    T* data;
    size_t size;
public:
    MyVector(size_t n) : data(new T[n]), size(n) {}
    ~MyVector() { delete[] data; }
    T& operator[](size_t i) { return data[i]; }
};

(2) 实例化类模板

类模板 必须显式或隐式(缺省)提供模板参数,编译器才能生成具体的类:

cpp

// 方式1:显式指定模板参数
MyVector<int> vec1(10);  // 实例化 MyVector<int>

// 方式2:使用缺省模板参数(如果类模板定义了缺省值)
template <typename T = double>  // 缺省类型为 double
class MyContainer { /*...*/ };

MyContainer<> vec2;  // 实例化 MyContainer<double>

2. 函数模板(Function Template)

函数模板用于定义 与类型无关的函数,模板参数可以通过 显式指定、缺省值或编译器推导 确定。

(1) 定义函数模板

cpp

template <typename T>  // T 是模板参数
T max(T a, T b) {
    return (a > b) ? a : b;
}

(2) 调用函数模板

函数模板的模板参数可以通过 三种方式 确定:

方式1:显式指定

cpp

int a = 3, b = 5;
cout << max<int>(a, b);  // 显式指定 T = int
方式2:缺省模板参数(C++11 起支持)

cpp

template <typename T = int>  // 缺省类型为 int
T getDefault() { return T{}; }

auto x = getDefault<>();  // 使用缺省值 T = int
方式3:编译器自动推导

如果函数参数中使用了模板参数,编译器可以通过 实参类型 推导模板参数:

cpp

double c = 2.5, d = 3.7;
cout << max(c, d);  // 编译器推导 T = double

推导规则

  • 如果所有实参类型一致,T 被推导为该类型。

  • 如果实参类型不一致(如 max(3, 4.5)),可能推导失败(除非使用 std::common_type 或 C++17 的 auto 参数)。


3. 关键区别:类模板 vs 函数模板

特性类模板函数模板
实例化方式必须显式或隐式提供模板参数可显式指定、缺省或编译器推导
缺省参数支持支持(C++11)支持(C++11)
类型推导不支持(必须指定类型)支持(可通过参数推导)

4. 进阶技巧

(1) 模板参数自动推导(C++17)

C++17 引入了 类模板参数推导(CTAD),允许编译器根据构造函数参数推导类模板参数:

cpp

std::pair p(1, 3.14);  // 推导为 std::pair<int, double>
std::vector v = {1, 2, 3};  // 推导为 std::vector<int>

(2) 非类型模板参数

模板参数可以是 类型(typename T 或 值(如 int N

cpp

template <typename T, int N>
class Array {
    T data[N];
public:
    T& operator[](int i) { return data[i]; }
};

Array<int, 10> arr;  // N = 10

(3) 可变参数模板(Variadic Templates)

支持任意数量和类型的模板参数:

cpp

template <typename... Args>
void print(Args... args) {
    (std::cout << ... << args) << "\n";  // C++17 折叠表达式
}

print(1, "hello", 3.14);  // Args 被推导为 int, const char*, double

5. 总结

  • 泛型编程 通过 模板 实现代码复用,编写与类型无关的代码。

  • 类模板

    • 必须显式或隐式(缺省)提供模板参数。

    • 不支持类型推导(C++17 前)。

  • 函数模板

    • 支持 显式指定、缺省值、编译器推导 三种方式。

    • 类型推导依赖于函数参数。

  • 现代 C++ 扩展了模板能力(如 CTAD、可变参数模板等)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值