如何在C中模拟OO风格的多态?
有没有办法用C
编程语言编写类OO代码?
也可以看看:
- 你能用C编写面向对象的代码吗?
- C中的面向对象
通过search“[c] oo”find。
第一个C ++编译器(“带类的C”)实际上会生成C代码,所以这绝对是可行的。
基本上,你的基类是一个结构; 派生的结构必须在第一个位置包含基本结构,以便指向“派生”结构的指针也将成为基本结构的有效指针。
typedef struct { data member_x; } base; typedef struct { struct base; data member_y; } derived; void function_on_base(struct base * a); // here I can pass both pointers to derived and to base void function_on_derived(struct derived * b); // here I must pass a pointer to the derived class
函数可以作为函数指针结构的一部分,所以像p-> call(p)这样的语法成为可能,但是你仍然必须显式的将指针传递给函数本身。
常用的方法是用指向函数的指针来定义结构体。 这定义了可以在任何types上调用的“方法”。 然后子types在这个共同的结构中设置自己的function,并返回它。
例如,在linux内核中有struct:
struct inode_operations { int (*create) (struct inode *,struct dentry *,int, struct nameidata *); struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); ... };
每个注册types的文件系统然后注册自己的函数来create
, lookup
和其余function。 其余代码可以使用通用的inode_operations:
struct inode_operations *i_op; i_op -> create(...);
C ++离C不远
类是具有隐藏指针的函数,指针指向一个称为VTable的函数指针表。 Vtable本身是静态的。 当types指向具有相同结构的Vtables,但指针指向其他实现时,则会得到多态性。
build议将函数中的调用逻辑封装为以struct为参数,以避免代码混乱。
你还应该在函数中封装结构实例化和初始化(这相当于一个C ++构造函数)和删除(C ++中的析构函数)。 无论如何,这些都是好的做法。
typedef struct { int (*SomeFunction)(TheClass* this, int i); void (*OtherFunction)(TheClass* this, char* c); } VTable; typedef struct { VTable* pVTable; int member; } TheClass;
要调用该方法:
int CallSomeFunction(TheClass* this, int i) { (this->pVTable->SomeFunction)(this, i); }
我看了大家的答案,想出了这个:
#include <stdio.h> typedef struct { int (*get)(void* this); void (*set)(void* this, int i); int member; } TheClass; int Get(void* this) { TheClass* This = (TheClass*)this; return This->member; } void Set(void* this, int i) { TheClass* This = (TheClass*)this; This->member = i; } void init(TheClass* this) { this->get = &Get; this->set = &Set; } int main(int argc, char **argv) { TheClass name; init(&name); (name.set)(&name, 10); printf("%d\n", (name.get)(&name)); return 0; }
我希望能回答一些问题。
由Ian Piumarta和VPRI的 Alessandro Warth撰写的文章“ Open Reusable Object Models”的附录B是GNU C中Object模型的一个实现,大约有140行代码。 这是一个迷人的阅读!
以下是使用C( 语句expression式 )的GNU扩展将消息发送到对象的macros的未caching版本:
struct object; typedef struct object *oop; typedef oop *(*method_t)(oop receiver, ...); //... #define send(RCV, MSG, ARGS...) ({ \ oop r = (oop)(RCV); \ method_t method = _bind(r, (MSG)); \ method(r, ##ARGS); \ })
在同一个文档中,查看object
vtable
, vtable_delegated
和symbol
结构以及_bind
和vtable_lookup
函数。
干杯!
文件函数fopen,fclose,fread是C中的OO代码的例子,而不是类中的私有数据,它们在用于封装数据的FILE结构上工作,C函数用作成员类函数。 http://www.amazon.com/File-Structures-Object-Oriented-Approach-C/dp/0201874016
在Wikipedia中:在编程语言和types理论中,多态性(来自希腊语πολύς,polys,“many,much”和μορφή,morphē,“form,shape”)是为不同types实体提供单一接口。
所以我想说在C中实现它的唯一方法是使用可变参数以及一些(半)自动types的信息pipe理。 例如在C ++中,你可以写(对不起):
void add( int& result, int a1, int a2 ); void add( float& result, float a1, float a2 ); void add( double& result, double a1, double a2 );
在C中,除了其他的解决scheme之外,你可以做的最好的是这样的:
int int_add( int a1, int a2 ); float float_add( float a1, fload a2 ); double double_add( double a1, double a2 ); void add( int typeinfo, void* result, ... );
那么你需要:
- 使用枚举/macros来实现“typeinfo”
- 用stdarg.h来实现后者的function
- 告别C静态types检查
我几乎可以肯定,多态的任何其他实现应该看起来很像这个。 上面的答案似乎试图解决inheritance问题,而不是多态!
#include <stdio.h> typedef struct { int x; int z; } base; typedef struct { base; int y; int x; } derived; void function_on_base( base * a) // here I can pass both pointers to derived and to base { printf("Class base [%d]\n",a->x); printf("Class base [%d]\n",a->z); } void function_on_derived( derived * b) // here I must pass a pointer to the derived class { printf("Class derived [%d]\n",b->y); printf("Class derived [%d]\n",b->x); } int main() { derived d; base b; printf("Teste de poliformismo\n"); bx = 2; dy = 1; bz = 3; dx = 4; function_on_base(&b); function_on_base(&d); function_on_derived(&b); function_on_derived(&d); return 0; }
输出是:
Class base [3] Class base [1] Class base [4] Class derived [2] Class derived [3] Class derived [1] Class derived [4]
所以它的作品,它的多态代码。
UncleZeiv在一开始就对此进行了解释。
为了在C中构build面向对象的function,你可以看看以前的答案。
但是,如果你想通过C语言中的例子来理解多态是什么,那么(正如在其他问题中已经提到的那样)。 也许我错了,但我想不出任何像C指针算术一样容易理解的东西。 在我看来, 指针运算在本质上是多态的 。 在下面的例子中,相同的函数(OO中的方法),即加法(+),将根据input结构的属性产生不同的行为。
例:
double a*; char str*; a=(double*)malloc(2*sizeof(double)); str=(char*)malloc(2*sizeof(char)); a=a+2; // make the pointer a, point 2*8 bytes ahead. str=str+2; // make the pointer str, point 2*1 bytes ahead.
免责声明:我对C非常陌生,非常期待被纠正,并从其他用户的意见中学习,甚至完全消除这个答案,如果它是错误的。 非常感谢,