C++笔记 类模板(面向对象)

在 C++ 面向对象编程中,类模板(Class Template) 是实现代码复用类型通用化 的核心特性。它允许我们定义一个 "通用模板",不指定具体数据类型,而是用类型参数占位,使用时再根据需要绑定具体类型(如 int、double、自定义类),自动生成对应类型的类。

简单来说:类模板是创建类的模具,类型是模具的参数,不同类型能快速生成不同的专属类,无需重复编写代码

一、为什么需要类模板?

面向对象编程中,我们常需要为不同数据类型实现相同的逻辑功能。例如:

一个整数栈(int Stack)

一个浮点数栈(double Stack)

一个字符串栈(string Stack)

如果不使用类模板,需要为每种类型单独写一个类,代码高度冗余、难以维护。类模板完美解决了这个问题:只写一套通用代码,编译器自动为不同类型生成对应的类,兼顾通用性和类型安全。

二、类模板的基础语法

1. 定义格式

类模板以template关键字开头,后跟类型参数列表,语法固定:

cpp 复制代码
// template:声明模板关键字
// <typename T>:模板参数列表,T是类型参数(可自定义名称,如Type、E)
// typename 也可以用 class 替代,效果完全一致
template <typename T>  
class 类名 {
    // 类的成员变量、成员函数,都可以使用类型参数T
private:
    T data;  // T是占位类型,使用时才确定具体类型
public:
    // 成员函数中使用T作为参数、返回值类型
    void setData(T value);
    T getData();
};

2. 核心规则

  1. 模板参数可以是类型参数 (用typename/class声明),也可以是非类型参数(如常量 int);
  2. 类模板的成员函数,如果在类外定义,必须也声明为模板;
  3. 类模板本身不是真正的类,实例化后才会生成具体的类(称为模板类)。

三、类模板的完整实现:以通用栈为例

栈(Stack)是经典的线性结构,核心操作是入栈、出栈、判空。我们用类模板实现支持任意类型的栈:

cpp 复制代码
#include <iostream>
// 定义类模板:通用栈
template <typename T>  // T为类型参数,代表栈存储的数据类型
class Stack {
private:
    T* arr;          // 动态数组存储元素,类型为T
    int topIndex;    // 栈顶索引
    int capacity;    // 栈容量

public:
    // 构造函数
    Stack(int cap = 10) {
        capacity = cap;
        topIndex = -1;
        arr = new T[capacity];  // 动态分配T类型数组
    }

    // 析构函数
    ~Stack() {
        delete[] arr;
    }

    // 入栈:参数类型为T
    void push(T value) {
        if (topIndex == capacity - 1) {
            std::cout << "栈已满!" << std::endl;
            return;
        }
        arr[++topIndex] = value;
    }

    // 出栈:返回值类型为T
    T pop() {
        if (topIndex == -1) {
            std::cout << "栈为空!" << std::endl;
            // 返回T类型默认值,保证类型匹配
            return T();
        }
        return arr[topIndex--];
    }

    // 获取栈顶元素
    T getTop() {
        if (topIndex == -1) return T();
        return arr[topIndex];
    }

    // 判断栈是否为空
    bool isEmpty() {
        return topIndex == -1;
    }
};

四、类模板的实例化与使用

类模板本身不是可直接使用的类,必须指定具体类型进行实例化,编译器才会生成真正的类。

1. 实例化语法

cpp 复制代码
// 类模板名<具体类型> 对象名;
Stack<int> intStack;       // 整数栈(T绑定为int)
Stack<double> doubleStack; // 浮点数栈(T绑定为double)
Stack<std::string> strStack; // 字符串栈(T绑定为string)
  1. 调用示例
cpp 复制代码
int main() {
    // 1. 使用int类型栈
    Stack<int> s1(5);
    s1.push(10);
    s1.push(20);
    std::cout << "int栈出栈:" << s1.pop() << std::endl;  // 输出20

    // 2. 使用string类型栈
    Stack<std::string> s2;
    s2.push("Hello");
    s2.push("C++ Template");
    std::cout << "string栈出栈:" << s2.pop() << std::endl;  // 输出C++ Template

    return 0;
}

运行结果

cpp 复制代码
int栈出栈:20
string栈出栈:C++ Template

五、类外实现成员函数(重点)

如果将类模板的成员函数写在类外部,必须遵循模板语法,否则编译报错:

cpp 复制代码
template <typename T>  // 必须重新声明模板参数
返回值类型 类名<T>::函数名(参数列表) {
    // 函数实现
}

示例:将栈的push函数类外实现:

cpp 复制代码
template <typename T>
void Stack<T>::push(T value) {
    if (topIndex == capacity - 1) {
        std::cout << "栈已满!" << std::endl;
        return;
    }
    arr[++topIndex] = value;
}

注意:必须写Stack<T>,不能只写Stack,因为Stack是模板,Stack<T>才是具体的类。

六、类模板的高级特性

1. 多参数类模板

一个类模板可以声明多个类型参数,适配更复杂的场景:

cpp 复制代码
// 两个类型参数:T1、T2
template <typename T1, typename T2>
class Pair {
private:
    T1 first;
    T2 second;
public:
    void set(T1 a, T2 b) {
        first = a;
        second = b;
    }
    void show() {
        std::cout << first << ", " << second << std::endl;
    }
};

// 使用:int + string 组合
Pair<int, std::string> p;
p.set(100, "成绩");
p.show();  // 输出:100, 成绩

2. 非类型模板参数

除了类型参数,类模板还支持常量参数(如整数、指针):

cpp 复制代码
// N是非类型参数(整数常量),指定数组大小
template <typename T, int N>
class Array {
private:
    T arr[N];  // 固定大小的数组
public:
    void set(int index, T value) {
        if (index >= 0 && index < N) arr[index] = value;
    }
};

// 使用:存储5个int的数组
Array<int, 5> arr;
arr.set(0, 10);

3. 类模板的特化

特化:为特定类型单独编写模板实现,覆盖通用模板逻辑。

全特化:为所有类型参数指定具体类型;

偏特化:为部分类型参数指定具体类型(仅类模板支持)。

全特化示例 :为char*类型单独实现栈:

cpp 复制代码
// 通用模板
template <typename T>
class Demo {
public:
    void show() {
        std::cout << "通用模板" << std::endl;
    }
};

// 全特化:T绑定为char*
template <>
class Demo<char*> {
public:
    void show() {
        std::cout << "char*类型特化模板" << std::endl;
    }
};

// 使用
Demo<int> d1; d1.show();  // 通用模板
Demo<char*> d2; d2.show(); // char*类型特化模板

七、类模板的核心注意事项

  1. 编译期实例化 :类模板的代码在编译时生成,不是运行时,因此效率高;
  2. 代码分离问题 :类模板的声明和实现建议写在同一个头文件(.h) 中,分开写会导致链接报错(编译器无法找到模板实现);
  3. 类型安全:实例化后严格匹配类型,不会出现类型隐式转换错误;
  4. 与函数模板的区别 :类模板是对 的通用化,函数模板是对函数的通用化,都是 C++ 泛型编程的基础。

八、类模板的应用场景

在 C++ 开发中,类模板是标准库的核心基础,我们常用的容器都是类模板实现:

std::vector<T>(动态数组)

std::list<T>(链表)

std::map<T1, T2>(键值对映射)

实际开发中,自定义通用工具类(如通用队列、通用链表、通用数据处理器)都依赖类模板。

总结

  1. 类模板本质:带类型参数的类模具,实现代码通用化,避免重复编写相同逻辑;
  2. 核心语法template <typename T> 声明,使用时指定具体类型;
  3. 关键用法:成员函数类外实现需带模板声明,支持多参数、特化;
  4. 核心价值:兼顾代码复用、类型安全、开发效率,是 C++ 面向对象与泛型编程的结合点。

掌握类模板,是从基础面向对象编程进阶到通用化、工程化 C++ 开发的关键一步。

相关推荐
AI-小柒1 小时前
磅上线!DataEyes 聚合平台正式接入 GPT-Image-2,开启多模态 AI 生成全新纪元
大数据·开发语言·数据库·人工智能·gpt·php
zhangrelay1 小时前
Lubuntu 26.04移动系统使用配置测试记录与引导修复备注
笔记·学习
jy022688791 小时前
线性代数-笔记
笔记·线性代数
小此方1 小时前
Re:从零开始的 C++ 进阶篇(四)工业级 C++ 编程:如何构建异常安全的健壮系统?(含案例分析)
运维·开发语言·c++·安全
电商API_180079052471 小时前
如何实现批量化自动化获取淘宝商品详情数据?爬虫orAPI?
大数据·c++·爬虫·自动化
❆VE❆1 小时前
python基础篇(一):使用vscode搭建python相关环境
开发语言·vscode·python
liurendonews1 小时前
刘韧微积分笔记之四:手机里的微积分
笔记·智能手机
t***5441 小时前
如何确认 Clang 是否在 Dev-C++ 中成功应用
java·开发语言·c++
神探小白牙1 小时前
3D饼图,带背景图和自定义图例(threejs)
开发语言·前端·javascript·3d·vue
楚Y6同学1 小时前
QT之下拉框自动填充功能
开发语言·c++·qt·qt开发技巧·串口下拉填充·网口下拉填充