用C编写面向对象代码有哪些方法?特别是在多态性方面。


另请参阅此堆栈溢出问题C中的面向对象。


当前回答

似乎人们正在尝试用C来模仿c++风格。我的观点是,用C来做面向对象的编程实际上就是做面向结构的编程。但是,您可以实现后期绑定、封装和继承等功能。对于继承,在子结构中显式地定义一个指向基结构的指针,这显然是一种多重继承。你还需要确定你的

//private_class.h
struct private_class;
extern struct private_class * new_private_class();
extern int ret_a_value(struct private_class *, int a, int b);
extern void delete_private_class(struct private_class *);
void (*late_bind_function)(struct private_class *p);

//private_class.c
struct inherited_class_1;
struct inherited_class_2;

struct private_class {
  int a;
  int b;
  struct inherited_class_1 *p1;
  struct inherited_class_2 *p2;
};

struct inherited_class_1 * new_inherited_class_1();
struct inherited_class_2 * new_inherited_class_2();

struct private_class * new_private_class() {
  struct private_class *p;
  p = (struct private_class*) malloc(sizeof(struct private_class));
  p->a = 0;
  p->b = 0;
  p->p1 = new_inherited_class_1();
  p->p2 = new_inherited_class_2();
  return p;
}

    int ret_a_value(struct private_class *p, int a, int b) {
      return p->a + p->b + a + b;
    }

    void delete_private_class(struct private_class *p) {
      //release any resources
      //call delete methods for inherited classes
      free(p);
    }
    //main.c
    struct private_class *p;
    p = new_private_class();
    late_bind_function = &implementation_function;
    delete_private_class(p);

用c_compiler main.c inherited_class_1编译。obj inherited_class_2。obj private_class.obj。

因此,我的建议是坚持使用纯C风格,不要试图强行采用c++风格。此外,这种方式也有助于以一种非常干净的方式构建API。

其他回答

我认为首先要说的是(至少在我看来)C的函数指针实现真的很难使用。我会跳过一大堆的圆环来避免函数指针…

也就是说,我认为其他人说的很好。你有结构,你有模块,而不是foo->方法(a,b,c),你最终用方法(foo,a,b,c)如果你有一个“method”方法,那么你可以用类型前缀它,所以FOO_method(foo,a,b,c),正如其他人所说…通过良好地使用.h文件,您可以获得私有和公共文件,等等。

现在,有一些事情是这个技巧不能给你的。它不会提供私有数据字段。我认为,这与意志力和良好的编码习惯有关……而且,没有一种简单的方法来继承它。

这些至少是简单的部分……其余的,我认为是90/10的情况。10%的收益需要90%的工作……

你可以使用函数指针来伪装它,事实上,我认为理论上可以将c++程序编译成C语言。

然而,将一种范式强加于一种语言,而不是选择一种使用范式的语言,很少有意义。

有几种技术可以使用。最重要的是如何分割项目。我们在项目中使用的接口是在.h文件中声明的,对象的实现是在.c文件中。重要的部分是,所有包含.h文件的模块都只将对象视为void *,而.c文件是唯一知道结构内部的模块。

以FOO类为例:

在。h文件中

#ifndef FOO_H_
#define FOO_H_

...
 typedef struct FOO_type FOO_type;     /* That's all the rest of the program knows about FOO */

/* Declaration of accessors, functions */
FOO_type *FOO_new(void);
void FOO_free(FOO_type *this);
...
void FOO_dosomething(FOO_type *this, param ...):
char *FOO_getName(FOO_type *this, etc);
#endif

C实现文件就像这样。

#include <stdlib.h>
...
#include "FOO.h"

struct FOO_type {
    whatever...
};


FOO_type *FOO_new(void)
{
    FOO_type *this = calloc(1, sizeof (FOO_type));

    ...
    FOO_dosomething(this, );
    return this;
}

因此,我明确地将指针指向该模块的每个函数。c++编译器隐式地完成它,而在C中我们显式地将它写出来。

我真的在我的程序中使用了这个,以确保我的程序不是用c++编译的,而且它在我的语法高亮编辑器中有另一种颜色的良好属性。

FOO_struct的字段可以在一个模块中修改,而另一个模块甚至不需要重新编译就仍然可用。

通过这种风格,我已经处理了OOP(数据封装)的很大一部分优点。通过使用函数指针,甚至可以很容易地实现继承之类的东西,但老实说,它真的很少有用。

哪些文章或书籍适合在C语言中使用面向对象的概念?

Dave Hanson的《C接口与实现》在封装和命名方面非常出色,在函数指针的使用方面也非常出色。Dave没有尝试模拟继承。

我亲眼见过。我不推荐。c++最初是作为一个生成C代码的中间步骤的预处理器开始的。

本质上,您最终要做的是为所有方法创建一个调度表,其中存储函数引用。派生类需要复制这个分派表并替换您想要重写的条目,如果您的新“方法”想要调用基方法,则必须调用原始方法。最终,你要重写c++。