面向对象的 C 语言编程 [英] Object oriented programming in C

查看:33
本文介绍了面向对象的 C 语言编程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能的重复:
你能用 C 编写面向对象的代码吗?
C 中的面向对象模式?

我记得不久前读到有人(我认为是 Linus Torvalds)谈论 C++ 是一种可怕的语言,以及如何使用 C 编写面向对象的程序.有时间反思,我没有真正了解所有面向对象的概念如何在 C 中应用.有些事情是相当明显的.例如:

I remember reading a while ago about someone (I think it was Linus Torvalds) talking about how C++ is a horrible language and how you can write object-oriented programs with C. On having had time to reflect, I don't really see how all object oriented concepts carry over into C. Some things are fairly obvious. For example:

  1. 要模拟成员函数,您可以将函数指针放在结构中.
  2. 要模拟多态性,您可以编写一个函数,该函数接受可变数量的参数并根据 sizeof 参数执行一些巫术
  1. To emulate member functions, you can put function pointers in structs.
  2. To emulate polymorphism, you can write a function that takes a variable number of arguments and do some voodoo depending on, say, the sizeof the parameter(s)

你将如何模拟封装和继承?

How would you emulate encapsulation and inheritance though?

我认为可以通过具有存储私有成员的嵌套结构来模拟封装.绕过它会相当容易,但也许可以命名为 PRIVATE 或同样明显的东西,以表明它不打算从结构外部使用.继承呢?

I suppose encapsulation could sort of be emulated by having a nested struct that stored private members. It would be fairly easy to get around, but could perhaps be named PRIVATE or something equally obvious to signal that it isn't meant to be used from outside the struct. What about inheritance though?

推荐答案

您可以使用常规函数和虚拟表 (vtables) 实现多态.这是我为编程练习发明的(基于 C++)一个非常简洁的系统:

You can implement polymorphism with regular functions and virtual tables (vtables). Here's a pretty neat system that I invented (based on C++) for a programming exercise:

构造函数分配内存,然后调用类的 init 函数,在那里初始化内存.每个 init 函数还应该包含一个静态 vtable 结构,其中包含虚拟函数指针(纯虚拟为 NULL).派生类 init 函数在执行任何其他操作之前调用超类 init 函数.

The constructors allocate memory and then call the class's init function where the memory is initialized. Each init function should also contain a static vtable struct that contains the virtual function pointers (NULL for pure virtual). Derived class init functions call the superclass init function before doing anything else.

通过实现虚函数包装器(不要与虚表指向的函数混淆)可以创建一个非常好的 API 如下(在它前面添加 static inline,如果你在标题中执行此操作):

A very nice API can be created by implementing the virtual function wrappers (not to be confused with the functions pointed to by the vtables) as follows (add static inline in front of it, if you do this in the header):

int playerGuess(Player* this) { return this->vtable->guess(this); }

可以通过滥用结构的二进制布局来实现单继承:

Single inheritance can be done by abusing the binary layout of a struct:

请注意,多重继承比较混乱,因为在层次结构类型之间进行转换时,您经常需要调整指针值.

Notice that multiple inheritance is messier as then you often need to adjust the pointer value when casting between types of the hierarchy.

其他类型特定的数据也可以添加到虚拟表中.示例包括运行时类型信息(例如,类型名称作为字符串)、链接到超类 vtable 和析构函数链.您可能需要虚拟析构函数,其中派生类析构函数将对象降级为其超类,然后递归调用它的析构函数,依此类推,直到到达基类析构函数并最终释放结构.

Other type-specific data can be added to the virtual tables as well. Examples include runtime type info (e.g. type name as a string), linking to superclass vtable and the destructor chain. You probably want virtual destructors where derived class destructor demotes the object to its super class and then recursively calls the destructor of that and so on, until the base class destructor is reached and that finally frees the struct.

封装是通过在 player_protected.h 中定义结构体并在 player_protected.c 中实现函数(由 vtable 指向)来完成的,对于派生类也是如此,但这很笨拙,而且会降低性能(因为虚拟包装器不能放在标题中),所以我建议不要这样做.

Encapsulation was done by defining the structs in player_protected.h and implementing the functions (pointed to by the vtable) in player_protected.c, and similarly for derived classes, but this is quite clumsy and it degrades performance (as virtual wrappers cannot be put to headers), so I would recommend against it.

这篇关于面向对象的 C 语言编程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆