C语言面向对象的简便方法

都知道C语言是面向过程的,但是现在软件规模越来越大,通过面向对象的方式可以简化开发。业余时间想了个简单的方法,在C中使用一部分面向对象的基本功能。由于C语言自身的限制,并不完善,只能将就用,聊胜于无,如果大家有好的想法可以一起讨论。

首先还是老规矩上代码: http://files.cnblogs.com/GhostZCH/object.rar

面向对象有三个基本属性:封装、继承和多态。 此处一一讲解处理方法。

1. 封装,基本思想就是用结构体代替类,属性没什么好说的,方法就麻烦点只能用函数指针了,基本思想和JS差不多,“函数就是对象的一个属性”。 缺点试试无法控制访问的私有和公用。由于C没有this指针,只好在每个函数都增加一个void*的参数将自己传进去。

1 /************************************************************************/
 2 /*         object    基类                                               */
 3 /************************************************************************/
 4 
 5 
 6 typedef struct stObj OBJECT_STRU;
 7 
 8 typedef char* (*ToString_PF)(void *pObj, char *pcStrBuf);
 9 typedef unsigned int ClassID;
10 
11 struct stObj
12 {
13     ClassID m_uiCID;
14     ToString_PF pfToString;
15 };
16 
17 char* OBJ_ToString(void *pObj, char *pcStrBuf)
18 {
19     sprintf(pcStrBuf, "ClassName:%s;ClassID:%06u", "Object", ((OBJECT_STRU *)pObj)->m_uiCID);
20     return pcStrBuf;
21 }
22 
23 OBJECT_STRU *new_Object()
24 {
25     OBJECT_STRU* pstObj = (OBJECT_STRU*)malloc(sizeof(OBJECT_STRU));
26 
27     if ( NULL == pstObj )
28     {
29         return NULL;
30     }
31 
32     pstObj->m_uiCID = CID_OBJ;
33     pstObj->pfToString = OBJ_ToString;
34 
35     return pstObj;

36 }

2继承:继承的方法是用类似组合的方式,将父类结构体作为子类的第一个属性,注意,这里必须是第一个,这样后面的强制类型转换才会有效。通过强制转换转换成父类。

1 /************************************************************************/

2 /*         animal    子类一                                             */
 3 /************************************************************************/
 4 
 5 typedef struct stAnimal
 6 {
 7     // 父类实体,必须放在第一个,强制转换才有效,利用这种方法产生继承的效果
 8     OBJECT_STRU m_stBaseObj; 
 9 
10     // 新增属性
11     char acName[NAME_LEN];  
12     
13     // 也可增加新增方法
14     // int (* pfGetAge)();
15 }ANIMAL_STRU;
16 
17 // 覆盖父类方法
18 char* ANM_ToString(void *pObj, char *pcStrBuf)
19 {
20     sprintf(pcStrBuf, "Classname:%s; AnimalName:%s; ClassID:%06u", 
21         "Animal", 
22         ((ANIMAL_STRU *)pObj)->acName,
23         ((ANIMAL_STRU *)pObj)->m_stBaseObj.m_uiCID);
24     return pcStrBuf;
25 }
26 
27 ANIMAL_STRU *new_Animal()
28 {
29     ANIMAL_STRU* pstObj = (ANIMAL_STRU*)malloc(sizeof(ANIMAL_STRU));
30     
31     if ( NULL == pstObj )
32     {
33         return NULL;
34     }
35     
36     pstObj->m_stBaseObj.m_uiCID = CID_ANM;
37     pstObj->m_stBaseObj.pfToString = ANM_ToString; // 覆盖父类方法,产生多态效果
38     pstObj->acName[0] = ‘\0‘;
39     
40     return pstObj;
41 }
42

三,多态,通过挂载不同的函数指针实现

1 ==========
 2 
 3 /************************************************************************/
 4 /*         测试                                                         */
 5 /************************************************************************/
 6 
 7 int main()
 8 {
 9     char acStrBuf[200] = {0};
10 
11     OBJECT_STRU *pObj = NULL;
12     ANIMAL_STRU *pAnm = NULL;
13     PLANT_STRU  *pPlt = NULL;
14 
15     // 定义父类
16     OBJECT_STRU *pObj_animal = NULL;
17     OBJECT_STRU *pObj_plant  = NULL;
18 
19     // 父类函数和属性调用
20     pObj = new_Object();
21     printf("[ID = %u][ ToString = %s ]\n", pObj->m_uiCID, pObj->pfToString(pObj, acStrBuf) );
22     free(pObj);
23     pObj = NULL;
24    
25     // 子类函数和属性调用
26     pAnm = new_Animal();
27     strcpy(pAnm->acName,"Panda");
28     printf("%s\n", pAnm->m_stBaseObj.pfToString(pAnm, acStrBuf) );
29     free(pPlt);
30     free(pAnm);
31     pPlt = NULL;
32     pAnm = NULL;
33 
34     // 子类函数和属性调用
35     pPlt = new_Plant();
36     strcpy(pPlt->acName,"Tree");
37     printf("%s\n", pPlt->m_stBaseObj.pfToString(pPlt, acStrBuf) );
38 
39 
40     /************************************************************************/
41     /*  多态测试                                                            */
42     /************************************************************************/
43 
44     // 定义父类
45     // OBJECT_STRU *pObj_animal = NULL;
46     // OBJECT_STRU *pObj_plant  = NULL;
47 
48     // 初始化子类
49     pObj_animal = (OBJECT_STRU *)new_Animal();
50     pObj_plant  = (OBJECT_STRU *)new_Plant();
51 
52     // 执行相同的函数产生不同的效果
53     printf("%s\n", pObj_animal->pfToString(pObj_animal, acStrBuf) );
54     printf("%s\n",  pObj_plant->pfToString(pObj_plant , acStrBuf) );
55 
56     getchar();
57 
58     free(pObj_animal);
59     free(pObj_plant );
60 
61     return 0;
62 }
63

时间: 09-08

C语言面向对象的简便方法的相关文章

Java实现文本文件按条件过滤的简便方法

程序开发中经常会碰到处理文本文件中数据的情况,这里通过一个例子来看用java实现文本文件按条件过滤的方法:从文本文件employee.txt中读取员工信息,从中找出1981年1月1日(含)之后出生的女员工. 文本文件empolyee.txt的格式如下: EID   NAME       SURNAME        GENDER  STATE        BIRTHDAY        HIREDATE         DEPT         SALARY 1       Rebecca  

深入理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)

最近看了一下java 8的一些新特性,其中最重要的莫过于Lambda表达式了,通过一阵子的学习,原本准备自己写一篇博客的,后来阅读了一位学长翻译过来的博客(原文是Brain Goetz的State of Lambda,下面会给出原文链接),觉得写的十分完美,把我想要写的和我没想到的都罗列了出来,就把这个分享给大家了. 注:原译文见  http://lucida.me/blog/java-8-lambdas-insideout-language-features/ 英语原版见:http://cr.

面向对象的思维方法

我是从学习Java编程开始接触OOP(面向对象编程),刚开始使用Java编写程序的时候感觉很别扭,因为我早以习惯用C来编写程序,很欣赏C的简洁性和高效性,喜欢C简练而表达能力丰富的风格,特别忍受不了Java运行起来慢吞吞的速度,相对冗长的代码,而且一个很简单的事情,要写好多类,一个类调用一个类,心里的抵触情绪很强. 我对Java的面向对象的特性琢磨良久,自认为有所领悟,也开始有意识的运用OOP风格来写程序,然而还是经常会觉得不知道应该怎样提炼类,面对一个具体的问题的时候,会觉得脑子里千头万绪的,

在VC下显示JPEG、GIF格式图像的一种简便方法

在VC下显示JPEG.GIF格式图像的一种简便方法 一. 引言  JPEG图像压缩标准随然是一种有损图像压缩标准,但由于人眼视觉的不敏感,经压缩后的画质基本没有发生变化,很快便以较高的压缩率得到了广泛的认可.GIF格式虽然仅支持256色但它对于颜色较少的图像有着很高的压缩率,甚至超过JPEG标准,也得到了广泛的认同.但作为众多程序员的一个重要的开发工具--Microsoft Visual C++ 6.0的MFC库却仅对没有经过任何压缩的BMP位图文件有着良好的支持,可以读取.显示.存储甚至在内存

面向对象的开发方法(总结)

面向对象分为面向对象的分析(OOA),面向对象的设计(OOD)和面向对象的程序设计(OOP). OOA的是利用抽象构造问题的对象模型 OOD是设计对象和对象之间的关系,如层次和集成:对象之间的通信方式,例如消息.对OOA的结果进行细化,使其可以被OOP接收 OOP指对系统功能的编码 面向对象是当前主流的开发方法,拥有很多不同的分支体系, 如OMT(对象建模技术),OOSE(面向对象的软件工程)和booch方法所同意为的统一建模语言.除此之外,还有caod/yourdon方法 1.基本概念 对象,

Go语言开发(四)、Go语言面向对象

Go语言开发(四).Go语言面向对象 一.结构体和方法 1.结构体的定义 在结构体中可以为不同项定义不同的数据类型.结构体是由一系列具有相同类型或不同类型的数据构成的数据集合.结构体定义需要使用type和struct语句.struct语句定义一个新的数据类型,结构体有中有一个或多个成员.type语句设定了结构体的名称.结构体的格式如下: type struct_variable_type struct { member definition; member definition; ... mem

C语言中常用计时方法总结

转自:http://blog.csdn.net/fz_ywj/article/details/8109368 C语言中常用计时方法总结 1. time() 头文件:time.h 函数原型:time_t time(time_t * timer) 功能:返回以格林尼治时间(GMT)为标准,从1970年1月1日00:00:00到现在的此时此刻所经过的秒数. 用time()函数结合其他函数(如:localtime.gmtime.asctime.ctime)可以获得当前系统时间或是标准时间. 用difft

c语言面向对象编程

#include <stdio.h> #include <stdlib.h> /*  *  *   1.  简单实现模拟虚函数表实现c语言面向对象的设计  *   2.  为实现:  函数注册调用  *   3.            通过文件实现函数注册调用  */ //封装 typedef struct _Shape Shape; //模拟虚函数表 struct ShapeClass {     void (*construct)(Shape* self); //构造函数   

附录A培训实习生-面向对象基础(3):方法重载

就上一篇代码而言,你如果写Cat cat = new Cat();会直接报错错误 : 1       “Cat”方法没有采用“0”个参数的重载 E:\大话设计模式学习\BigDesignPatterns\附录A培训实习生之面向对象基础\动物运动会\AnimalGames\Form1.cs       20     23     AnimalGames 原因就是必要给小猫起名字.如果当真需要不起名字也要生出小猫来,可以采用方法重载. 方法重载提供了创建同名的多个方法的能力,但这些方法需使用不同的参