用C编写面向对象代码有哪些方法?特别是在多态性方面。
另请参阅此堆栈溢出问题C中的面向对象。
用C编写面向对象代码有哪些方法?特别是在多态性方面。
另请参阅此堆栈溢出问题C中的面向对象。
当前回答
在Jim Larson 1996年在312节编程午餐研讨会上的演讲中有一个使用C进行继承的例子:高级和低级C。
其他回答
是的。事实上,Axel Schreiner免费提供了他的书《ANSI-C中的面向对象编程》,这本书相当全面地涵盖了这个主题。
哪些文章或书籍适合在C语言中使用面向对象的概念?
Dave Hanson的《C接口与实现》在封装和命名方面非常出色,在函数指针的使用方面也非常出色。Dave没有尝试模拟继承。
关于c语言OOP的另一个变化,请参阅http://slkpg.byethost7.com/instance.html。它强调仅使用本机c实现实例数据的可重入性,多重继承使用函数包装器手动完成。保持型号安全。下面是一个小例子:
typedef struct _peeker
{
log_t *log;
symbols_t *sym;
scanner_t scan; // inherited instance
peek_t pk;
int trace;
void (*push) ( SELF *d, symbol_t *symbol );
short (*peek) ( SELF *d, int level );
short (*get) ( SELF *d );
int (*get_line_number) ( SELF *d );
} peeker_t, SlkToken;
#define push(self,a) (*self).push(self, a)
#define peek(self,a) (*self).peek(self, a)
#define get(self) (*self).get(self)
#define get_line_number(self) (*self).get_line_number(self)
INSTANCE_METHOD
int
(get_line_number) ( peeker_t *d )
{
return d->scan.line_number;
}
PUBLIC
void
InitializePeeker ( peeker_t *peeker,
int trace,
symbols_t *symbols,
log_t *log,
list_t *list )
{
InitializeScanner ( &peeker->scan, trace, symbols, log, list );
peeker->log = log;
peeker->sym = symbols;
peeker->pk.current = peeker->pk.buffer;
peeker->pk.count = 0;
peeker->trace = trace;
peeker->get_line_number = get_line_number;
peeker->push = push;
peeker->get = get;
peeker->peek = peek;
}
是的,这是可能的。
这是纯C语言,没有宏预处理。它具有继承、多态、数据封装(包括私有数据)。它没有等效的受保护限定符,这意味着私有数据在整个继承链中也是私有的。
#include "triangle.h"
#include "rectangle.h"
#include "polygon.h"
#include <stdio.h>
int main()
{
Triangle tr1= CTriangle->new();
Rectangle rc1= CRectangle->new();
tr1->width= rc1->width= 3.2;
tr1->height= rc1->height= 4.1;
CPolygon->printArea((Polygon)tr1);
printf("\n");
CPolygon->printArea((Polygon)rc1);
}
/*output:
6.56
13.12
*/
命名空间通常通过以下方式实现:
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 *