C++与C语言实现Stack的对比分析
面向对象编程有三大特性:封装、继承和多态。通过下面C和C++实现Stack的代码对比,我们可以初步了解封装的概念。
目录
一、主要差异对比
1、封装性体现
2、语法便利性
3、代码组织
二、C语言实现Stack分析
1、数据结构定义
2、核心函数实现
初始化函数
销毁函数
压栈操作
其他操作
3、C实现特点
三、C++实现Stack分析
1、类定义
2、核心成员函数实现
初始化函数
压栈操作
其他操作
四、主要区别分析
1、封装性
C++实现:
C语言实现:
2、语法便利性
C++优势:
3、代码组织
C++:
C:
五、实现思路详解
C语言实现思路
C++实现思路
六、两种实现的对比总结
七、深入理解封装
八、总结
一、主要差异对比
1、封装性体现
-
C++实现:将数据和相关操作函数都封装在类内部,通过
public
和private
访问限定符进行访问控制-
数据成员(
_a
,_capacity
,_top
)设为private
,外部无法直接访问和修改 -
操作接口(
Push
,Pop
,Top
等)设为public
,作为类的外部接口 -
封装本质是一种更严格、更规范的管理方式,避免了数据被随意修改的风险
-
-
C实现:数据和函数分离,结构体成员完全公开,可以直接访问和修改
2、语法便利性
-
this指针:C++成员函数隐式传递this指针,调用时不需要显式传递对象地址
-
缺省参数:如
Init(int n = 4)
可以简化初始化调用 -
类型系统:不需要typedef,直接使用类名作为类型
-
命名空间:使用
std
命名空间避免命名冲突
3、代码组织
-
C++:相关数据和操作集中在一个类中,结构更清晰
-
C:数据和操作分离,需要通过指针显式传递结构体
二、C语言实现Stack分析
1、数据结构定义
typedef int STDataType;
typedef struct Stack {STDataType* a; // 动态数组指针int top; // 栈顶指针int capacity; // 栈容量
} ST;
2、核心函数实现
初始化函数
void STInit(ST* ps) {assert(ps);ps->a = NULL;ps->top = 0;ps->capacity = 0;
}
-
接收Stack结构体指针
-
将数组指针初始化为NULL,top和capacity设为0
销毁函数
void STDestroy(ST* ps) {assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}
-
释放动态分配的内存
-
重置所有成员变量
压栈操作
void STPush(ST* ps, STDataType x) {assert(ps);// 检查并扩容if (ps->top == ps->capacity) {int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity * sizeof(STDataType));if (tmp == NULL) {perror("realloc fail");return;}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] = x;ps->top++;
}
-
检查容量不足时进行扩容
-
初始容量为0时分配4个元素空间,否则容量翻倍
-
将元素放入栈顶并更新top指针
其他操作
bool STEmpty(ST* ps); // 判断栈是否为空
void STPop(ST* ps); // 弹出栈顶元素
STDataType STTop(ST* ps); // 获取栈顶元素
int STSize(ST* ps); // 获取栈大小
3、C实现特点
-
数据和操作分离
-
每次操作都需要传递Stack指针
-
结构体成员可以直接访问和修改
-
需要手动管理内存
三、C++实现Stack分析
1、类定义
class Stack {
public:// 成员函数void Init(int n = 4); // 初始化,带默认参数void Push(STDataType x);void Pop();bool Empty();int Top();void Destroy();private:// 成员变量STDataType* _a;size_t _capacity;size_t _top;
};
2、核心成员函数实现
初始化函数
void Init(int n = 4) {_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a) {perror("malloc申请空间失败");return;}_capacity = n;_top = 0;
}
-
使用默认参数简化调用
-
直接访问成员变量(不需要传递对象指针)
压栈操作
void Push(STDataType x) {if (_top == _capacity) {int newcapacity = _capacity * 2;STDataType* tmp = (STDataType*)realloc(_a, newcapacity * sizeof(STDataType));if (tmp == NULL) {perror("realloc fail");return;}_a = tmp;_capacity = newcapacity;}_a[_top++] = x;
}
-
扩容逻辑与C版本相同
-
直接访问成员变量,代码更简洁
其他操作
void Pop() { assert(_top > 0); --_top; }
bool Empty() { return _top == 0; }
int Top() { assert(_top > 0); return _a[_top - 1]; }
void Destroy() { free(_a); _a = nullptr; _top = _capacity = 0; }
四、主要区别分析
1、封装性
C++实现:
-
将数据和操作数据的函数都封装在类内部
-
使用访问限定符(
public
/private
)控制访问权限 -
数据成员通常设为
private
,防止外部直接修改 -
提供公共接口(
public
方法)来操作数据
C语言实现:
-
数据和函数分离
-
结构体成员可以直接访问和修改
-
需要通过函数参数显式传递结构体指针
2、语法便利性
C++优势:
-
缺省参数:
Init(int n = 4)
可以省略参数调用 -
this指针:成员函数自动获取当前对象指针,无需显式传递
-
作用域解析:类名直接作为类型名,无需
typedef
-
命名空间:使用
namespace
避免命名冲突
3、代码组织
C++:
-
相关数据和函数组织在一个类中
-
更符合"高内聚"的设计原则
-
代码可读性和维护性更好
C:
-
数据和函数分离
-
需要手动管理数据和函数的关系
-
容易产生命名冲突
五、实现思路详解
C语言实现思路
-
数据结构定义:
-
使用结构体
ST
存储栈的数组指针、栈顶位置和容量 -
typedef
定义栈元素类型,便于修改
-
-
函数设计:
-
每个操作函数都需要显式接收栈结构体指针
-
使用断言(assert)检查指针有效性
-
动态内存管理完全手动控制
-
-
使用方式:
-
必须先声明结构体变量
-
每个操作都需要传递结构体地址
-
需要显式初始化和销毁
-
C++实现思路
-
类设计:
-
将数据和操作封装在
Stack
类中 -
成员变量设为
private
保护数据 -
成员函数提供操作接口
-
-
自动关联:
-
成员函数自动关联到对象实例
-
通过
this
指针隐式访问成员数据 -
无需显式传递对象指针
-
-
资源管理:
-
仍使用手动内存管理(后续可改进为RAII)
-
提供完整的初始化、销毁接口
-
-
使用便利性:
-
对象创建后直接调用方法
-
方法调用更直观简洁
-
缺省参数简化常见用例
-
六、两种实现的对比总结
特性 | C实现 | C++实现 |
---|---|---|
数据与操作 | 分离 | 绑定在类中 |
访问控制 | 无,可直接访问所有成员 | 通过访问限定符控制 |
对象传递 | 需要显式传递指针 | 隐式this指针传递 |
类型定义 | 需要typedef | 类名即类型 |
初始化 | 需要单独调用初始化函数 | 可带默认参数 |
内存管理 | 手动 | 手动(后续可用构造函数/析构函数改进) |
代码组织 | 分散 | 集中 |
七、深入理解封装
封装不仅仅是把数据和函数放在一起,更重要的是:
-
访问控制:通过
public
/private
限制对内部数据的直接访问 -
接口抽象:对外提供简洁的操作接口,隐藏实现细节
-
数据保护:防止外部代码随意修改内部状态,保证数据一致性
-
实现隔离:内部实现变更不影响外部代码
在这个Stack实现中,C++版本通过类机制实现了基本的封装,但还只是封装的初级阶段。后续可以进一步改进:
-
使用构造函数和析构函数自动管理资源(RAII)
-
添加const成员函数保证不修改对象状态
-
考虑异常安全
-
实现拷贝控制和移动语义
八、总结
通过对比可以看出:
-
C++的类机制提供了更好的封装性,这是最核心的区别
-
C++语法提供了许多便利特性,简化了代码编写
-
当前实现中,底层逻辑和算法基本相同,主要区别在组织方式
-
这只是C++封装的初步展示,后续还有更多强大特性
随着深入学习,特别是了解STL中的stack实现后,会更能体会C++的强大之处。STL stack采用适配器模式,基于deque/list/vector等容器实现,展现了更高层次的抽象和设计。