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++ 开发的关键一步。

相关推荐
CheerWWW2 小时前
C++学习笔记——初始化列表、创建和实例化对象、new 关键字、隐式构造与 explicit 关键字、运算符与运算符重载
c++·笔记·学习
IT从业者张某某2 小时前
Dockerfile详解
java·开发语言
小陈phd2 小时前
多模态大模型学习笔记(二十八)—— 基于Qwen多模态大模型的城市道路积水智能检测助手实战
笔记·学习
小白学大数据2 小时前
攻克滑动拼图反爬:Python 高效爬取网页图片实战案例
开发语言·爬虫·python
煜磊2 小时前
C/C++语言部署安装_C/C++Api学习
开发语言·c++
低频电磁之道3 小时前
C++ 源码文本格式规范
开发语言·c++
大尚来也3 小时前
Java反射机制:从底层原理到Spring框架的深度实践
开发语言