挣扎来自面向对象的土地?

当我遇到编程问题时,我自然会开始将它们分解为我脑子里的逻辑对象。 谁有责任,谁拥有什么,谁来自什么,等等。

我正在与C斗争。我只是不知道如何用程序语言做事。

有经验的C程序员可以帮助解释我在设计时如何考虑我的程序吗?

例如,我想编写自己的Semaphore类。 我自然需要一个队列的数据结构,我也想自己编写。 如果我需要在Java或C#中执行此操作,我可以简单地启动一个快速的Queue类并在我的Semaphore类中创建它的新实例。

但在C中,没有对象。 那么我是否必须内联我的Queue数据结构的所有行为?

有人可以帮我“搞定”吗?

相关 : 在c中规划和组织应用程序开发的最佳方法是什么?

我会修改S. Lott的答案,使用不透明指针来执行结构成员的数据隐藏:

  1. 使用普通的OO设计定义您的类。
  2. 你的类的成员变量进入C语言结构。
  3. 在头文件中,您不希望公开对象的成员变量(因为它们在OO语言中是“私有的”)。 相反,使用不透明指针,即
    typedef struct mystruct_s *mystruct_t; // first argument to all your methods
  4. 对于您想要“公开”的所有方法,请将其签名放在.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,例如模板,运算符覆盖,数据隐藏等。

  1. C ++“struct”(可能仍然)等同于“class”,所有成员都是“public”。
  2. 成员函数可以实现为结构中的函数指针; 这可以提供封装和多态性。 除非您使用工厂,否则构造函数存在于全局范围内。 析构函数可以是成员函数。
  3. 使用访问器成员函数(如getColor())setColor()可以缓解内部差异并提供一些数据隐藏。 如果你真的想要,你可以使用Brian Bondy建议隐藏宏。
  4. 实际上有很多FOSS库提供标准容器 – 哈希表,动态数组,链表等。

我第二次建议做“穷人在C中的OO”。 我也认为你可能会花些时间看看Perl的OO是如何工作的。 基本上OO是在Perl中通过让解释器为每个方法提供实例作为隐式第一参数来完成的。 您将希望在C中明确地执行相同的操作,并使用真正非常好的代码组织,因为编译器不会为您强制执行良好的封装。

顺便说一句,您可以通过使用不透明指针强制保持结构的成员私有。 我似乎记得GNU编程标准和建议包括一种技术,通过基本上将所有内容转换为void *来传递它,然后使用typedef来命名应该传递的每个特定类型的不透明指针。 (即每个“class级”)

相关你能用C编写面向对象的代码吗?

你也可以用C做派生类:

C中的派生类 – 您最喜欢的方法是什么?