用C编写面向对象代码有哪些方法?特别是在多态性方面。
另请参阅此堆栈溢出问题C中的面向对象。
用C编写面向对象代码有哪些方法?特别是在多态性方面。
另请参阅此堆栈溢出问题C中的面向对象。
当前回答
是的。事实上,Axel Schreiner免费提供了他的书《ANSI-C中的面向对象编程》,这本书相当全面地涵盖了这个主题。
其他回答
C的stdio FILE子库是如何在纯C中创建抽象、封装和模块化的极好示例。
继承和多态性——通常被认为是OOP必不可少的其他方面——不一定能提供它们所承诺的生产率提高,而且有合理的理由认为它们实际上会阻碍开发和对问题域的思考。
我亲眼见过。我不推荐。c++最初是作为一个生成C代码的中间步骤的预处理器开始的。
本质上,您最终要做的是为所有方法创建一个调度表,其中存储函数引用。派生类需要复制这个分派表并替换您想要重写的条目,如果您的新“方法”想要调用基方法,则必须调用原始方法。最终,你要重写c++。
这本书读起来很有趣。我自己也在思考同样的问题,思考这个问题的好处是:
Trying to imagine how to implement OOP concepts in a non-OOP language helps me understand the strengths of the OOp language (in my case, C++). This helps give me better judgement about whether to use C or C++ for a given type of application -- where the benefits of one out-weighs the other. In my browsing the web for information and opinions on this I found an author who was writing code for an embedded processor and only had a C compiler available: http://www.eetimes.com/discussion/other/4024626/Object-Oriented-C-Creating-Foundation-Classes-Part-1
在他的案例中,用普通C语言分析和调整面向对象的概念是一种有效的追求。他似乎愿意牺牲一些面向对象的概念,因为尝试用C语言实现它们会带来性能开销。
我得到的教训是,是的,在某种程度上它是可以做到的,是的,有一些很好的理由去尝试。
In the end, the machine is twiddling stack pointer bits, making the program counter jump around and calculating memory access operations. From the efficiency standpoint, the fewer of these calculations done by your program, the better... but sometimes we have to pay this tax simply so we can organize our program in a way that makes it least susceptible to human error. The OOP language compiler strives to optimize both aspects. The programmer has to be much more careful implementing these concepts in a language like C.
命名空间通常通过以下方式实现:
stack_push(thing *)
而不是
stack::push(thing *)
要将C结构体变成类似c++类的东西,您可以转向:
class stack {
public:
stack();
void push(thing *);
thing * pop();
static int this_is_here_as_an_example_only;
private:
...
};
Into
struct stack {
struct stack_type * my_type;
// Put the stuff that you put after private: here
};
struct stack_type {
void (* construct)(struct stack * this); // This takes uninitialized memory
struct stack * (* operator_new)(); // This allocates a new struct, passes it to construct, and then returns it
void (*push)(struct stack * this, thing * t); // Pushing t onto this stack
thing * (*pop)(struct stack * this); // Pops the top thing off the stack and returns it
int this_is_here_as_an_example_only;
}Stack = {
.construct = stack_construct,
.operator_new = stack_operator_new,
.push = stack_push,
.pop = stack_pop
};
// All of these functions are assumed to be defined somewhere else
和做的事:
struct stack * st = Stack.operator_new(); // Make a new stack
if (!st) {
// Do something about it
} else {
// You can use the stack
stack_push(st, thing0); // This is a non-virtual call
Stack.push(st, thing1); // This is like casting *st to a Stack (which it already is) and doing the push
st->my_type.push(st, thing2); // This is a virtual call
}
我没有做析构函数或删除,但它遵循相同的模式。
This_is_here_as_an_example_only类似于一个静态类变量——在一个类型的所有实例之间共享。所有的方法都是静态的,除了一些采用this *
您可能需要做的一件事是研究X Window的Xt工具包的实现。当然,它已经很老了,但是许多使用的结构都是在传统的c语言中以面向对象的方式设计的。一般来说,这意味着在这里或那里添加一个额外的间接层,并设计相互覆盖的结构。
你真的可以在C语言中以面向对象的方式做很多事情,即使有时感觉,面向对象的概念并没有完全从#include<favorite_OO_Guru.h>的思想中涌现出来。它们确实构成了当时许多公认的最佳实践。面向对象语言和系统只是提炼和放大了当时编程时代精神的一部分。