在C方向
什么是一组漂亮的预处理器黑客(兼容ANSI C89 / ISO C90),它在C中启用某种丑陋(但可用)的面向对象?
我熟悉几种不同的面向对象的语言,所以请不要回答“Learn C ++!”这样的答案。 我读过“面向对象编程与ANSI C”(当心: PDF格式 )和其他一些有趣的解决方案,但我最感兴趣的是你们:-)!
另请参阅可以在C中编写面向对象的代码吗?
C对象系统(COS)听起来很有前途(它仍然是alpha版本)。 为了简单和灵活性,它试图尽量减少可用的概念:统一的面向对象编程包括开放类,元类,属性元类,泛型,多方法,委托,所有权,异常,契约和闭包。 有一份草稿文件(PDF)描述了它。
C中的例外是在其他OO语言中发现的TRY-CATCH-FINALLY的C89实现。 它配备了测试套件和一些示例。
Laurent Deniau,这在C语言的OOP上工作很多
我建议不要使用预处理器(ab)来尝试使C语法更像另一种更面向对象的语言。 在最基本的层面上,您只需使用普通结构作为对象并通过指针传递它们即可:
struct monkey
{
float age;
bool is_male;
int happiness;
};
void monkey_dance(struct monkey *monkey)
{
/* do a little dance */
}
要获得继承和多态等事情,你必须努力工作。 您可以通过让结构的第一个成员是超类的实例来进行手动继承,然后您可以自由地转向指向基类和派生类的指针:
struct base
{
/* base class members */
};
struct derived
{
struct base super;
/* derived class members */
};
struct derived d;
struct base *base_ptr = (struct base *)&d; // upcast
struct derived *derived_ptr = (struct derived *)base_ptr; // downcast
要获得多态性(即虚拟函数),可以使用函数指针和函数指针表(也称为虚拟表或vtables):
struct base;
struct base_vtable
{
void (*dance)(struct base *);
void (*jump)(struct base *, int how_high);
};
struct base
{
struct base_vtable *vtable;
/* base members */
};
void base_dance(struct base *b)
{
b->vtable->dance(b);
}
void base_jump(struct base *b, int how_high)
{
b->vtable->jump(b, how_high);
}
struct derived1
{
struct base super;
/* derived1 members */
};
void derived1_dance(struct derived1 *d)
{
/* implementation of derived1's dance function */
}
void derived1_jump(struct derived1 *d, int how_high)
{
/* implementation of derived 1's jump function */
}
/* global vtable for derived1 */
struct base_vtable derived1_vtable =
{
&derived1_dance, /* you might get a warning here about incompatible pointer types */
&derived1_jump /* you can ignore it, or perform a cast to get rid of it */
};
void derived1_init(struct derived1 *d)
{
d->super.vtable = &derived1_vtable;
/* init base members d->super.foo */
/* init derived1 members d->foo */
}
struct derived2
{
struct base super;
/* derived2 members */
};
void derived2_dance(struct derived2 *d)
{
/* implementation of derived2's dance function */
}
void derived2_jump(struct derived2 *d, int how_high)
{
/* implementation of derived2's jump function */
}
struct base_vtable derived2_vtable =
{
&derived2_dance,
&derived2_jump
};
void derived2_init(struct derived2 *d)
{
d->super.vtable = &derived2_vtable;
/* init base members d->super.foo */
/* init derived1 members d->foo */
}
int main(void)
{
/* OK! We're done with our declarations, now we can finally do some
polymorphism in C */
struct derived1 d1;
derived1_init(&d1);
struct derived2 d2;
derived2_init(&d2);
struct base *b1_ptr = (struct base *)&d1;
struct base *b2_ptr = (struct base *)&d2;
base_dance(b1_ptr); /* calls derived1_dance */
base_dance(b2_ptr); /* calls derived2_dance */
base_jump(b1_ptr, 42); /* calls derived1_jump */
base_jump(b2_ptr, 42); /* calls derived2_jump */
return 0;
}
这就是你如何在C中进行多态性。这不是很好,但它可以完成这项工作。 有一些棘手的问题涉及基类和派生类之间的指针转换,只要基类是派生类的第一个成员,它们就是安全的。 多重继承要困难得多 - 在这种情况下,为了在除第一个以外的基类之间进行处理,您需要根据正确的偏移手动调整指针,这非常棘手且容易出错。
另一个(棘手的)你可以做的事情是在运行时改变一个对象的动态类型! 你只需重新分配一个新的vtable指针。 您甚至可以有选择地更改某些虚拟功能,同时保留其他功能,创建新的混合类型。 只是要小心创建一个新的vtable,而不是修改全局vtable,否则会意外地影响给定类型的所有对象。
我曾经与一个C库一起工作,这个C库的实现方式让我觉得非常优雅。 他们用C语言编写了一种定义对象的方法,然后继承它们,使它们像C ++对象一样可扩展。 基本的想法是这样的:
继承很难描述,但基本上是这样的:
struct vehicle {
int power;
int weight;
}
然后在另一个文件中:
struct van {
struct vehicle base;
int cubic_size;
}
然后,你可以在记忆中创建一辆面包车,并被代码使用,只知道车辆:
struct van my_van;
struct vehicle *something = &my_van;
vehicle_function( something );
它运行得很漂亮,.h文件定义了你应该能够对每个对象做什么。
链接地址: http://www.djcxy.com/p/79151.html上一篇: orientation in C