提到面向对象编程,我们想到的就是封装、继承、多态,但是其实这几个特性并不是只有面向对象语言才能实现,面向过程的C语言也是可以支持实现这三个特性的,下面我们来具体看下

封装1

2

3

4// point.h

struct Point;

struct Point* makePoint(double x, double y);

double distance(struct Point *p1, struct Point *p2);

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21// point.c

#include "point.h"

#include

#include

struct Point {

double x, y;

};

struct Point* makePoint(double x, double y){

struct Point* p = malloc(sizeof (struct Point));

p->x = x;

p->y = y;

return p;

}

double distance(struct Point* p1, struct Point* p2){

double dx = p1->x - p2->x;

double dy = p1->y - p2->y;

return sqrt(dx*dx + dy*dy);

}

这样使用point.h 的程序就不知道 Point 的内部结构,实现了数据的封装,外部只能使用声明的两个函数,如:

1

2

3

4

5

6

7

8

9// 使用 demo

#include

#include "point.h"

int main(){

struct Point* p1 = makePoint(5, 6);

struct Point* p2 = makePoint(6, 7);

printf("%lf",distance(p1, p2));

}

继承

接着上面的代码

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#include

#include

#include "point.h"

struct NamedPoint {

double x, y;

char* name;

};

struct NamedPoint* makeNamedPoint(double x, double y, char* name){

struct NamedPoint* p = malloc(sizeof(struct NamedPoint));

p->x = x;

p->y = y;

p->name = name;

return p;

}

int main(){

struct NamedPoint* p1 = makeNamedPoint(0, 0, "origin");

struct NamedPoint* p2 = makeNamedPoint(3, 4, "new");

// 本来接受的参数只能是 Point类型的指针,这里是把 NamedPoint的指针进行强转

printf("%lf",distance((struct Point*)p1, (struct Point*)p2));

}

这是能够进行强转调用,是因为 NamedPoint 结构体的前两个成员的顺序与 Point 结构体的完全一致,所以可以进行强转,这其实就可以算是一个单继承

多态

最后我们来看一下多态,这个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#include

#include

// 定义函数指针

typedef int (*myFunc)(int, int);

// 定义函数1

int add(int n, int m){

return n + m;

}

// 定义函数2

int substract(int n, int m){

return n - m;

}

int main(){

// 为函数指针使用不同的函数实现进行调用

myFunc f = &add;

printf("%d\n", f(1, 2));

f = &substract;

printf("%d\n", f(1, 2));

}

上面的例子如果大家感受还不太明显的话,接下来看一个 redis 源码中的使用

1

2

3

4

5

6

7

8

9// dict.h

typedef struct dictType {

uint64_t (*hashFunction)(const void *key);

void *(*keyDup)(void *privdata, const void *key);

void *(*valDup)(void *privdata, const void *obj);

int (*keyCompare)(void *privdata, const void *key1, const void *key2);

void (*keyDestructor)(void *privdata, void *key);

void (*valDestructor)(void *privdata, void *obj);

} dictType;

上面这个结构中都是函数指针,可以类比为 Java 中的接口及对应函数声明

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

43

44

45

46// uint64_t (*hashFunction)(const void *key) 实现函数

uint64_t dictSdsHash(const void *key) {

return dictGenHashFunction((unsigned char*)key, sdslen((char*)key));

}

// int (*keyCompare)(void *privdata, const void *key1, const void *key2) 实现函数

int dictSdsKeyCompare(void *privdata, const void *key1, const void *key2){

int l1,l2;

DICT_NOTUSED(privdata);

l1 = sdslen((sds)key1);

l2 = sdslen((sds)key2);

if (l1 != l2) return 0;

return memcmp(key1, key2, l1) == 0;

}

// ================= 具体的类型实现 =================

/* Set dictionary type. Keys are SDS strings, values are ot used. */

dictType setDictType = {

dictSdsHash, /* hash function */

NULL, /* key dup */

NULL, /* val dup */

dictSdsKeyCompare, /* key compare */

dictSdsDestructor, /* key destructor */

NULL /* val destructor */

};

/* Sorted sets hash (note: a skiplist is used in addition to the hash table) */

dictType zsetDictType = {

dictSdsHash, /* hash function */

NULL, /* key dup */

NULL, /* val dup */

dictSdsKeyCompare, /* key compare */

NULL, /* Note: SDS string shared & freed by skiplist */

NULL /* val destructor */

};

/* Db->dict, keys are sds strings, vals are Redis objects. */

dictType dbDictType = {

dictSdsHash, /* hash function */

NULL, /* key dup */

NULL, /* val dup */

dictSdsKeyCompare, /* key compare */

dictSdsDestructor, /* key destructor */

dictObjectDestructor /* val destructor */

};

这几个类型都可以类比看做上面的接口的具体实现类,每个类有自己对应的函数实现

所以不是使用了面向对象的语言,写出的代码就是面向对象的,而使用了面向过程的语言写出来的代码就不行,只不过面向对象的语言对面向对象提供了更好的支持,写起来更方便,更安全而已。代码质量的好坏不是仅仅靠使用了什么高级语言就可以的,要想提升代码质量还是需要我们去不断思考和实践的

c语言错误封装,C语言实现的封装,继承,多态相关推荐

  1. c语言错误c1021,c语言经典错误

    C语言命语法错误大全 C语言命语法错误大全 fatalerrorC1004: unexpectedendoffilefound 未找到文件末尾(可能是括号匹配问题) fatalerrorC1021: ...

  2. c语言错误writing,C语言编译器的错误信息

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 Not a valid expression format type 不合法的表达式格式 Not an allowed type 不允许使用的类型 Num ...

  3. c语言错误stray,C语言20条编程中遇到的错误提示(4页)-原创力文档

    C语言20条编程中遇到的错误提示 代码: 编译器提示错误:error: 'else' without a previous 'if' 错误原因解读:'else'的前面没有匹配的'if' 代码: 编译器 ...

  4. c语言错误2015,C语言2015(回答).doc

    C语言2015(回答) 一.单项选择题 1.以下不是C语言特点的是( B ). A)C语言简洁.紧凑 B) 能够编制出功能复杂的程序 C)C语言可以直接对硬件进行操作 D) C语言移植性好 2.以下不 ...

  5. c语言错误指导,c语言编程指导.pdf

    高质量C++/C 编程指南 文件状态 文件标识: [ ] 草稿文件 当前版本: 1.0 [ √] 正式文件 作 者: 林锐 博士 [ ] 更改正式文件 完成日期: 2001 年7 月24 日 高质量C ...

  6. c语言错误re,c语言malloc之后再realloc的有关问题

    C/C++ code#include #include #include "../Status.h" #define STACK_INIT_SIZE 5 //堆栈初始大小 #def ...

  7. c语言错误spawning,C语言一直出现Error spawning cl.exe的解决办法

    这几天这个问题一直困扰着我,我考二级三|级时用过的VisualC++软件拷贝到别人电脑上后,一直出现这个问题.因为在准备计算机四级,我好久没用过这个软件了.开始我有点不相信,今天我验证了一下,结果如下 ...

  8. c语言错误c4047,c语言错误 apos;int apos; differs in levels of indirection from apos;int *apos;...

    用数组编的多项式乘法,但是不会合并同类项 从同学那参考了合并的方法,但是有错误 比较着急!! 下面是程序 #include #define N 100 void multiply(int a[],in ...

  9. c语言错误c4430,C 语言 typedef 与 #define 比较

    Alvin typedef 与 #define 的区别 1. 执行时间不同 关键字 typedef 在编译阶段有效,由于是在编译阶段,因此 typedef 有类型检查的功能. #define 则是宏定 ...

最新文章

  1. 【CTF】实验吧 奇怪的短信
  2. 点阵大屏语音感应时计——人体感应
  3. 机器人图形变变变_幼儿园大班数学活动《图形变变变》PPT课件教案下载 - 快思幼教网...
  4. 2012-02-14 貌似情人节
  5. UE4 身体部件换装实现
  6. atitit.二进制数据无损转字符串网络传输
  7. 计算机四级网络题型,全国计算机四级考试题型
  8. python数学实验与建模pdf_Python数学实验与建模(4)
  9. 产品读书《引爆点:如何引发流行》
  10. [leetcode 3sum】 三数之和问题 @python
  11. DLL load failed: %1 不是有效的 Win32 应用程序的解决办法
  12. EasyExcel导出设置表头字体样式和批注
  13. 磁珠和电感在解决EMI和EMC的不同应用
  14. 2023届深信服C++A卷笔试
  15. 读书百客:《宿新市徐公店》评赏
  16. 国际贸易术语解释通则(DES 目的港船上交货(……指定目的港))
  17. [LOJ2568][可并堆]APIO2016:烟花表演
  18. Java期末考试试题及参考答案(10)
  19. H264编解码SPS、PPS参数说明
  20. 3COM 交换机端口的监听配置 ZT

热门文章

  1. 求约瑟夫环问题最后胜利者的一般解法以及数学推导方法
  2. Vue脚手架搭建简单步骤
  3. MySQL知识树 集合操作
  4. BZOJ4428 : [Nwerc2015]Debugging调试
  5. PowerShell 笔记
  6. [bzoj1700]: [Usaco2007 Jan]Problem Solving 解题
  7. Windows Store 开发总结——文件操作
  8. 关于--在 System.Threading.ThreadAbortException 中第一次偶然出现的“mscorlib.dll”类型的异常(转)...
  9. Html前端基础(这些基础标签你必须知道!)
  10. Node.js下载安装及各种npm、cnpm、nvm、nrm配置(保姆式教程---提供全套安装包)---npm的安装与配置(2)