skaiuijing

有过面向对象语言学习经历的小伙伴们在使用c语言的过程中,往往会羡慕这些面向对象语言的特性。

其实c语言能够模拟这些高级语言的特性。

例如,在c++中,this指针是一个非常方便的指针,但是在c语言也可以模拟做到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <string.h>

typedef struct {
char name[50];
int age;

void (*setName)(struct Person* self, const char* name);
void (*setAge)(struct Person* self, int age);
void (*printInfo)(struct Person* self);
} Person;

void setName(Person* self, const char* name) {
strncpy(self->name, name, sizeof(self->name));
}

void setAge(Person* self, int age) {
self->age = age;
}

void printInfo(Person* self) {
printf("Name: %s\n", self->name);
printf("Age: %d\n", self->age);
}

void createPerson(Person* p) {
p->setName = setName;
p->setAge = setAge;
p->printInfo = printInfo;
}

int main() {
Person person;
createPerson(&person);

person.setName(&person, "liming");
person.setAge(&person, 25);
person.printInfo(&person);

return 0;
}

通过函数指针和self指针的定义和传递,我们模拟了类和方法的实现。也就是说,在c语言中,我们也可以非常方便的实现增删查改。

createPerson函数成功初始化了数据结构中的方法,将函数的地址赋值给数据结构中的函数指针,使其成为了该结构体的方法。

1
2
3
4
5
void createPerson(Person* p) {
p->setName = setName;
p->setAge = setAge;
p->printInfo = printInfo;
}

可能有小伙伴很疑惑:这样做到底有什么好处?我们也可以直接在main函数对person进行操作啊?

首先我们要明白: 程序 = 数据结构 + 算法

数据结构是程序中非常重要的一部分,它往往存储重要的数据,并且作用于各个文件,但是对数据结构的初始化、赋值等操作,在函数出现多重嵌套时,代码容易出现可读性变差等问题,这个时候,穿梭在各个函数及文件中的self指针,无时无刻不在提醒着我们数据结构的存在及重要性。

self的存在,就是在绑定数据结构和方法,将特定的操作与数据结构绑定起来

通过定义self指针,我们可以非常方便的设置数据结构的各个成员,完成初始化等操作,我们不必在main函数中直接对数据结构的成员进行赋值,而是把这一切都放在函数中进行,当函数的嵌套非常深时,程序的可读性变得乱七八糟时,self的重要性就能体现出来了。

其实c语言的文件就是一个弱类,我们可以充分学习面向对象的思想对程序进行模块化、对象化处理,然后在编写c语言时充分利用文件作用域和函数的命名以及函数指针来实现类和方法。