人们使用哪些技术/策略在C(不是C ++)构建的对象?(What techniques/strate

2019-06-27 18:53发布

我是打算从C之内使用的对象特别感兴趣,而不是形成解释语言如Python的核心对象的实现。

Answer 1:

我倾向于做这样的事情:

struct foo_ops {
    void (*blah)(struct foo *, ...);
    void (*plugh)(struct foo *, ...);
};
struct foo {
    struct foo_ops *ops;
    /* data fields for foo go here */
};

有了这些结构的定义,实施FOO的代码看起来是这样的:

static void plugh(struct foo *, ...) { ... }
static void blah(struct foo *, ...) { ... }

static struct foo_ops foo_ops = { blah, plugh };

struct foo *new_foo(...) {
   struct foo *foop = malloc(sizeof(*foop));
   foop->ops = &foo_ops;
   /* fill in rest of *foop */
   return foop;
} 

然后,在代码中使用FOO:

struct foo *foop = new_foo(...);
foop->ops->blah(foop, ...);
foop->ops->plugh(foop, ...);

这个代码可以收拾与宏或内联函数,所以它看起来更类似C

foo_blah(foop, ...);
foo_plugh(foop, ...);

但如果你坚持使用一个相当短的名字为“行动”现场,简单地写出所示的代码本来不是特别详细。

这种技术是完全足够在C实施一个相对简单的基于对象的设计中,但它处理更高级的需求,例如明确地表示类,方法和继承。 对于这些,你可能需要类似的GObject(如埃夫拉伊姆提到的),但我建议,确保你确实需要更复杂的框架的额外功能。



Answer 2:

您使用的术语“对象”是一个有点模糊,所以我将假设你问如何用C实现面向对象编程的某些方面(随时纠正我的这个假设。)

方法多态性:

方法多态性使用函数指针通常仿真中℃。 例如,如果我有我用来表示image_scaler(一些需要的图像,并调整大小以新的维度)一个结构,我可以做这样的事情:

struct image_scaler {
    //member variables
    int (*scale)(int, int, int*);
}

然后,我可以做一些图像缩放器这样:

struct image_scaler nn, bilinear;
nn->scale = &nearest_neighbor_scale;
bilinear->scale = &bilinear_scale;

这让我实现多态行为是发生在一个image_scaler并通过简单地传递一个不同的image_scaler使用它的尺度方法的任何功能。

遗产

继承,则通常可获得这样:

struct base{
   int x;
   int y;
} 

struct derived{
   struct base;
   int z;
}

现在,我可以自由地使用衍生的额外的字段,以让基地的所有的“继承”字段一起。 此外,如果你有一个功能,只需要在一个结构基础。 你可以简单地施展你的结构dervied指针变成没有结果的一个结构基指针



Answer 3:

图书馆等的GObject 。

基本上GObject的提供描述不透明的值(整数,字符串)和对象(通过手动地描述接口-如函数指针的结构,基本上correspoinding到++ V表中C) -常见的方式在结构上的详细信息可以在其被发现参考

你常常还用手实现虚函数表中“在普通的C COM”



Answer 4:

正如你可以浏览所有的答案看到,有图书馆,函数指针,继承,封装等方式,所有可用的(C ++原本是前端为C)。

然而,我发现,软件一个很重要的方面是可读性。 你试过从10年前读码? 因此,我倾向于采取最简单的办法做这样的事情在C.对象时

问以下内容:

  1. 这是为有期限的客户(如果是的话,考虑OOP)?
  2. 我可以使用OOP(通常更少的代码,更快的发展,更可读的)?
  3. 我可以使用库(现有的代码,现有的模板)?
  4. 我在由存储器或CPU(例如Arduino的)约束?
  5. 是否有其他技术原因用C?
  6. 我可以保持我的C非常简单,可读?
  7. 我真的需要为我的项目是什么OOP的特点?

我通常会恢复到像油嘴API,让我概括了我的代码,并提供了一个非常可读的接口。 如果需要更多,我添加函数指针多态性。

class_A.h:
  typedef struct _class_A {...} Class_A;
  Class_A* Class_A_new();
  void Class_A_empty();
  ...

#include "class_A.h"
Class_A* my_instance;
my_instance = Class_A_new();
my_instance->Class_A_empty();  // can override using function pointers


Answer 5:

看看IJG的实现。 他们不仅使用了setjmp / longjmp的异常处理,他们有虚函数表和一切。 这是一个良好的书面和足够小的图书馆,你得到一个很好的例子。



Answer 6:

类似戴尔的做法,但一个多footgun位是PostgreSQL的代表如何解析树节点,表达式类型,并在内部等。 有默认的NodeExpr结构,沿行

typedef struct {
    NodeTag n;
} Node;

其中NodeTag是unsigned int的的typedef,并有一个与一堆描述所有可能的节点类型的常量的头文件。 节点本身是这样的:

typedef struct {
    NodeTag n = FOO_NODE;
    /* other members go here */
} FooNode;

FooNode可以转换为一个Node不受惩罚,因为C结构的怪癖:如果两个结构具有相同的第一部件,可以将它们浇铸到彼此。

是的,这意味着一个FooNode可以转换为一个BarNode ,你可能不希望这样做。 如果你想正确的运行时类型检查,GObject的是要走的路,虽然准备恨的生活,而你得到了它的窍门。

(注:从内存中的例子,我还没有砍死在一段时间Postgres的内部的。 开发人员常见问题有更多的信息。)



文章来源: What techniques/strategies do people use for building objects in C (not C++)?