最近,我一直在修补自己的语言,并阅读有关该主题的各种着作。
有没有人对C(或汇编程序)如何将Object Class
的概念和/或Generics
的概念编入语言有任何好的建议。 (参考Object和Generics的Java实现)
例如,在Java中,所有类都扩展了Object。那么你如何在C级代表这一点呢?是这样的:
#include <stdio.h>
typedef struct {
int stuff;
} Object;
typedef struct {
int stuff;
Object object;
} ChildClass;
int main() {
ChildClass childClass;
childClass.stuff = 100;
childClass.object.stuff = 200;
printf("%d\n", childClass.stuff);
printf("%d\n", childClass.object.stuff);
}
我甚至不确定如何开始实施像Generics这样的东西。 我也很欣赏有关程序语言设计的任何有价值的链接。 谢谢,
答案 0 :(得分:5)
看看Abelson和Sussman的Structure and Interpretation of Computer Programs。虽然它没有说明如何在C中执行它,但它确实演示了如何在运行时创建类型以及如何在不提供本机支持的语言之上构建对象系统。一旦理解了基本思想,就应该能够使用结构和函数指针来创建实现。当然,查看C ++预处理器的源代码也很有启发性。有一段时间,C ++只是C编译器的预处理器。
答案 1 :(得分:3)
我刚才发现这本书是一本有趣的读物:Object-Oriented Programming With ANSI-C(PDF)。
在C中,我通过使用struct
(用于存储类的状态)和带有指针的函数(类的方法)创建了类类结构和方法。实现继承这样的事情是可能的,但会很快变得混乱。我不是一个Java人,我不确定你应该把多少Java压到C上,它们是非常不同的语言。
这可能是最简单的对象实现形式;我写它是为了同时运行多个PID控件。
//! PID control system state variables
typedef struct {
const PID_K * K; //!< PID control parameters
int32_t e; //!< Previous error (for derivative term)
int32_t i; //!< Integrator
} PID_SYS;
void PID_Init(PID_SYS * sys, const PID_K * K)
{
sys->i = 0;
sys->e = 0;
sys->K = K;
}
int16_t PID_Step(PID_SYS * sys, int32_t e)
{
// ...PID math using "sys->" for any persistent state variables...
}
答案 2 :(得分:2)
如果您的目标是编写包含高级概念的新语言,您可能需要查看CPython源代码。 CPython是一种面向对象的编程语言,其解释器是用C语言编写的。用于C ++,D,Javascript,Go,Objective C的编译器/解释器的开源C实现,以及许多其他的存在。
答案 3 :(得分:1)
它更复杂,但你走的是正确的道路。实际的实现使用与你的代码大致相同的代码来实现继承(但它们实际上使用包含来实现它,这是非常具有讽刺意味的),以及每个实例的函数指针表(虚函数)和一些(好的,很多)帮助器宏。
请参阅gobject。
答案 4 :(得分:1)
绝对不是C,但我建议你看看Lua。
Lua的核心只有几个基本类型:数字,字符串,布尔值,函数和表(但是,除了本主题的范围之外,还有一些更多。表基本上只是一个接受键的哈希表任何类型的任何类型,也可以包含任何类型的值。
您可以通过 metatables implement OOP in Lua。在Lua中,允许一个表最多有一个metatable,可以访问under special circumstances,例如当一个表被添加或乘以另一个表时,或者当您尝试访问表中不存在的键时
使用元表,您可以通过将多个元表链接在一起,快速轻松地实现与继承相似的功能。当您尝试访问表中缺少的键时,Lua会在该表的metatable中查找名为__index
的键。因此,如果您尝试在没有此类密钥的表上访问名为foo
的密钥,Lua将在第一个元表中检查foo
。如果在那里不存在,并且metatable具有自己的元素,并且__index
已定义,它将在下一个中检查foo
,依此类推。
一旦你意识到在Lua中执行此操作非常简单,将其转换为C是非常容易实现的。当然,你的OOP将完全在运行时,但它确实会非常像OOP。