1. 从C语言栈到C++类的演进脉络
第一次用C++封装栈结构时,我被一个看似简单的问题困扰了很久——为什么需要把数据和操作强行绑在一起?毕竟用C语言的struct加上独立函数也能实现相同功能。直到在维护一个开源项目时,看到超过20个直接操作栈结构的函数散落在不同文件里,才真正理解封装的价值。
C语言的栈实现通常长这样:
c复制#define MAX_SIZE 100
typedef struct {
int data[MAX_SIZE];
int top;
} Stack;
void push(Stack *s, int val) {
if(s->top < MAX_SIZE)
s->data[s->top++] = val;
}
这种实现有三个明显的痛点:1) 数据结构与操作分离导致维护困难 2) 无法防止越界访问等非法操作 3) 缺乏类型安全。我曾参与过一个嵌入式项目,就因为某个模块直接修改了stack的top指针,导致内存溢出,排查了整整三天。
2. C++类封装的实现艺术
2.1 基础栈类封装
用C++类重新实现上述栈结构时,代码发生了质的变化:
cpp复制template<typename T>
class Stack {
private:
std::vector<T> data;
public:
void push(const T& val) {
data.push_back(val);
}
T pop() {
if(data.empty())
throw std::out_of_range("Stack is empty");
T val = data.back();
data.pop_back();
return val;
}
};
这个版本有四个关键改进:
- 使用模板支持任意类型
- 用vector替代固定数组自动管理内存
- 通过私有化数据防止外部篡改
- 异常处理机制增强健壮性
关键技巧:在嵌入式等特殊场景,可以用std::array替代vector实现静态栈,通过模板参数指定容量:
