C作为面向对象的语言

时间:2010-02-28 19:55:04

标签: c

您是否可以建议C语言的语法以与面向对象语言类似的方式使用它?我知道它们不能相同,并且C中没有一些关键字,但我想知道是否有办法利用某些方面(如继承),即使在C程序中也是如此。

5 个答案:

答案 0 :(得分:10)

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

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

通过实现虚函数包装器(不要与vtables指向的函数混淆),可以创建一个非常好的API,如下所示(在它前面添加static inline,如果你在报头):

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

单继承可以通过滥用结构的二进制布局来完成:alt text

请注意,多重继承更加混乱,因此在层次结构类型之间进行转换时,通常需要调整指针值。

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

答案 1 :(得分:2)

GObject library

  

GLib对象系统(或称GObject)是一个免费软件库(由LGPL提供),它提供了一个便携式对象系统和透明的跨语言互操作性。 GObject旨在直接在C程序中使用,也可以通过绑定到其他语言。

答案 2 :(得分:2)

传统的解决方案是函数指针结构。我强调传统。我可以告诉你我在PL / I和C年前写过的代码是什么类型,但如果你可以称之为艺术,我不会声称代表“艺术”的状态。

这有很多变化,下面是一个妥协。

struct SortOfAnAbstractClass {
   int (*function1)(SortOfAnAbstractClass* this, int arg1, int arg2, char * arg3);
   void (*function2)(SortOfAnAbstractClass* this, char *arg);
};

struct SortOfDerived {
   struct SortOfAnAbstractClass base;
   int instanceVariable1;
};

SortOfAnAbstractClass getMeOne() {
     SortOfDerived *d = malloc(sizeof SortOfDerived);
     memset(d, 0, sizeof SortOfDerived);
     d->function1 = myf1;
     d->function2 = myf2;
     return &d->base;
};

然后'myf1'和'myf2'投出'this'参数并前往城镇。您可以将其扩展为更完整的虚拟调度。

时间迷雾的另一个常见变化:

struct SortOfAClass {
   void *creatorInfo;
   int (*function1)(SortOfAnAbstractClass* this, int arg1, int arg2, char * arg3);
   void (*function2)(SortOfAnAbstractClass* this, char *arg);
};

在此变体中,包含没有继承。派生类每个都将其私有状态放入creatorInfo中的自己的对象中。

答案 3 :(得分:1)

答案 4 :(得分:0)

在C中进行OO编程有很多变化。我喜欢这样做的方法是为每个头文件定义一个类。你会注意到一个构造函数new_testclass(),它只是初始化你的函数指针并返回一个指向已分配的类/结构的指针。此外,任何函数都会在第一个参数中获取指向该类的指针(c ++会这样做,但会隐藏)。

testclass.h

#ifndef MALLOC_H
    #include<malloc.h>
#endif
struct _testclass 
{
    int a;
    int b;
    int (*sum)(struct _testclass *obj);
};

typedef struct _testclass testclass;

int f_sum (testclass *obj)
{
    return obj->a + obj->b;
}

testclass* new_testclass()
{
    testclass *temp;
    temp = (testclass*)malloc(sizeof(testclass));
    temp->sum = &f_sum;
    return temp;
}

然后你可以简单地使用它。

testclass.c

#include <stdio.h>
#include "testclass.h"
int _tmain(int argc, _TCHAR* argv[])
{
    int result;
    testclass *testclass1;
    testclass1 = new_testclass();
    testclass1->a = 5;
    testclass1->b = 8;
    result = testclass1->sum(testclass1);
    printf("%d\n",result);
    free(testclass1);
    return 0;
}

当然,这里缺少面向对象编程的几个重要方面,但这为基本抽象提供了一种简单的方法。我认为继承需要某种时髦的预处理技巧,如果它可以完成的话。