前言
这几天正在学习C++, 学到了面向对象, 突然想到前几天写的期末项目, 自己就已经潜移默化的运用了面向对象的思想. 于是就开始思考, 能否在C语言中实现面向对象编程. C语言本身不支持面向对象, 这给实现过程带来了很多的麻烦, 但好在也能通过一些方法硬造出来.
类和对象
1. 创建类
C++中, 类通过class来实现. 在C语言中, 可以通过结构体模拟class来实现类的包装, 我们以实现一个不可变长的栈为例:- typedef struct {
- int* content;
- int top;
- int size;
- } Stack;
复制代码 此时Stack结构体中包含了栈相关的数据
关于类方法, 由于结构体中不能放置函数, 因此需另寻方法. 首先想到的是函数指针, 以pop为例:- void pop();
- typedef struct{
- int *content;
- int top;
- int size;
- void (*pop)();
- } Stack;
复制代码 聪明的你应该发现了问题: pop() 函数的实现需要知道Stack中的content及top数据, 而直接通过.调用函数指针时, 函数无法知道是哪个Stack类型的变量调用了他, 因此必须通过参数的方式告知函数是哪个Stack对象调用了他, 因此这里需要把方法写在结构体外面:- typedef struct{
- int *content;
- int top;
- int size;
- } Stack;
- // Stack.pop()
- void stack_pop(Stack *s);
复制代码 这里在方法名前加上stack_防止命名冲突.
由于C语言中无法声明一个变量是private的还是public的, 因此就全靠自觉了()
补全Stack相关的操作:- ```c#include #include #include // class Stack// privatetypedef struct {
- int* content;
- int top;
- int size;
- } Stack;// publicStack stack_init(int size);void stack_quit(Stack* s);bool stack_push(Stack* s, int target);bool stack_pop(Stack* s);int stack_top(const Stack* s);void stack_is_empty(const Stack* s);void stack_is_full(const Stack* s);// class
复制代码 此处传入的Stack变量为指针形式可以加快运行速度, 节省内存, 并使函数能够修改传入结构体的值.
在声明Stack类型对象后, 需调用stack_init函数来初始化对象; 在对象不需要再使用时, 需调用stack_quit函数来释放对象:- int main(){
- Stack *stack_1;
- stack_1 = stack_init(100);
-
- ...
- stack_quit(stack_1);
- }
- Stack *stack_init(int size){
- Stack *s = (Stack *)malloc(sizeof(Stack));
- s -> content = (int *)malloc(sizeof(int) * size);
- s -> size = size;
- s -> top = 0;
- return s;
- }
- void stack_quit(Stack *s){
- free(s -> content);
- free(s);
- }
复制代码 相较于C++, 有一个方便之处: 传入参数名不需要保证和类中变量名相同了. 这使得类中变量的命名更加自由了.
继承
假设我们需要实现一个类, 能够实现栈的功能, 并记录每次更改的时间:- // class timer
- // private
- typedef struct{
- Stack *stack;
- time_t time;
- } Timer;
- // public
- Timer timer_init(int size);
- void timer_get_time(Timer *t);
- void timer_quit(Timer *t);
- // class
复制代码 可以看到, Timer类内包含Stack类的对象. 如果想要使用Stack类的方法, 只需要用.取出Timer中的stack, 对其使用Stack类的方法. 例如timer_init就可以使用stack_init方法来初始化其中的Stack对象:- Timer timer_init(int size){
- Timer t;
- t -> stack = (Stack *)malloc(sizeof(Stack));
- t -> stack = stack_init(size);
- t -> time = 0;
- return t;
- }
- void timer_quit(Timer *t){
- stack_quit(t -> stack);
- free(t -> stack);
- free(t);
- }
复制代码 也可以使用Stack中的其他类方法:- int main(){
- Timer *timer_1;
- timer_1 = timer_init(100);
- stack_push(timer_1.stack, 114514);
- timer_get_time(timer_1);
- return 0;
- }
复制代码 多态
考虑Stack的另一个子类:- // class
- // private
- typedef struct{
- Stack *stack;
- char *msg;
- } Msger;
- // class
复制代码 如果想要实现一个函数, 能够打印出Msger中的msg和Timer中的time, 应该如何实现?
C语言中, 想要实现像这样的多态, 似乎只能通过声明多个函数:- void timer_print(Timer *t){
- printf("Time = %ud", t -> time);
- }
- void msger_print(Msger *m){
- printf("Message: %s", m -> msg);
- }
复制代码 只能算勉强实现了多态.
学生党的第一篇文章(), 想必有很多疏漏之处, 恳请不吝赐教
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |