挣扎来自面向对象的土地?
当我遇到编程问题时,我自然会开始将它们分解为我脑子里的逻辑对象。 谁有责任,谁拥有什么,谁来自什么,等等。
我正在与C斗争。我只是不知道如何用程序语言做事。
有经验的C程序员可以帮助解释我在设计时如何考虑我的程序吗?
例如,我想编写自己的Semaphore类。 我自然需要一个队列的数据结构,我也想自己编写。 如果我需要在Java或C#中执行此操作,我可以简单地启动一个快速的Queue类并在我的Semaphore类中创建它的新实例。
但在C中,没有对象。 那么我是否必须内联我的Queue数据结构的所有行为?
有人可以帮我“搞定”吗?
相关 : 在c中规划和组织应用程序开发的最佳方法是什么?
我会修改S. Lott的答案,使用不透明指针来执行结构成员的数据隐藏:
- 使用普通的OO设计定义您的类。
- 你的类的成员变量进入C语言结构。
- 在头文件中,您不希望公开对象的成员变量(因为它们在OO语言中是“私有的”)。 相反,使用不透明指针,即
typedef struct mystruct_s *mystruct_t; // first argument to all your methods
- 对于您想要“公开”的所有方法,请将其签名放在.h文件中。 方法体应该进入.c文件,“private”方法应该只在.c文件中定义,并且也声明为静态,因此它们的符号不会与其他文件中定义的符号冲突。
使用此方法不需要像下划线那样的聪明命名约定,但这意味着所有成员变量都是私有的。 函数可以是公共函数或私有函数,虽然公共函数它们是全局命名空间的一部分,因此您可能希望使用“package”名称来限定其名称,如mystruct_push()
, mystruct_pop()
等。
如果调用者或库负责调用malloc()
和free()
您还需要明确。 很可能你会有mystruct_t *create()
和void destroy(mystruct_t *target)
方法。
你仍然可以用C来思考面向对象
您只需要创建一个结构和一组函数,这些函数将指向该结构的实例的指针作为其第一个参数。
至于多态性,您可以将结构的大小作为结构的第一个成员传递,因此您知道如何强制转换它。
这里有一个很好的使用ANSI-C的面向对象编程的pdf 。
我有一段时间从程序转向OO思考,所以我感受到了你的痛苦。
我发现,为了学习如何创建对象,最好考虑一下它们对调用者的看法。 从另一个角度来看,同样的方法可能对您有所帮助。 考虑组件的API是什么样的。 一种好方法是研究现有的C API(我使用标准Java API作为OO API的一组示例)。
您习惯使用类似这样的队列组件:
import some.package.Queue; Queue q = new Queue(); q.add(item);
在典型的C api中,你会期待更像:
#include // provides queue, make_queue(), queue_add(), others queue q = make_queue(); // queue is probably a struct, or a struct* queue_add(q,item);
每当你发现自己在物体中思考时,进行类似的转换。
你可以使用指向函数等的指针,在C中创建类似对象的结构 – 但是成千上万的C程序员已经无需管理。
祝好运!
查看Lua C api 。 就C接口设计而言,它一直是我的指路明灯。 每个函数都将Lua状态作为一个主要参数,成为你的“this”。 inheritance有点棘手,但是Chipmunk设法做了很好的工作,暴露了采用通用形状结构的函数,并计算出通过“klass”实际调用哪个函数的细节。 您可以经常利用void *使函数采用与OO中重载方式不同的类型(结构)。 它有时会感觉有点hackish但效果很好。
最初C ++只是一个从C ++源代码编写C代码的编译器; 然后由本机C编译器编译,链接等。
因此,所有OOP方法都可以在C中使用 – 只是编译器不会帮助您,并且不提供所有编译时function,例如模板,运算符覆盖,数据隐藏等。
- C ++“struct”(可能仍然)等同于“class”,所有成员都是“public”。
- 成员函数可以实现为结构中的函数指针; 这可以提供封装和多态性。 除非您使用工厂,否则构造函数存在于全局范围内。 析构函数可以是成员函数。
- 使用访问器成员函数(如getColor()) , setColor()可以缓解内部差异并提供一些数据隐藏。 如果你真的想要,你可以使用Brian Bondy建议隐藏宏。
- 实际上有很多FOSS库提供标准容器 – 哈希表,动态数组,链表等。
我第二次建议做“穷人在C中的OO”。 我也认为你可能会花些时间看看Perl的OO是如何工作的。 基本上OO是在Perl中通过让解释器为每个方法提供实例作为隐式第一参数来完成的。 您将希望在C中明确地执行相同的操作,并使用真正非常好的代码组织,因为编译器不会为您强制执行良好的封装。
顺便说一句,您可以通过使用不透明指针强制保持结构的成员私有。 我似乎记得GNU编程标准和建议包括一种技术,通过基本上将所有内容转换为void *来传递它,然后使用typedef来命名应该传递的每个特定类型的不透明指针。 (即每个“class级”)
相关你能用C编写面向对象的代码吗?
你也可以用C做派生类:
C中的派生类 – 您最喜欢的方法是什么?
使用glib,c库与oop http://library.gnome.org/devel/glib/2.20/