C++-C能实现出面向对象的三个特征吗?

发布于 2017-02-02 18:36:47 字数 49 浏览 1322 评论 4

C能实现出面向对象里面的封装、继承、多态这几个基本特征吗?如果可以,给出实例代码吧。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

清晨说ぺ晚安 2017-10-08 21:38:09

“基类”用结构体实现,函数指针很重要,可以用来模拟多态,其原理基本和c++的多态编译层面的实现是一致的。用经典的shape, rectangle, circle,带一个计算面积函数的c++继承链作为例子。

typedef struct {
float (*computeArea)(const ShapeClass *shape);
} ShapeClass;

//这就是多态函数接口

float shape_computeArea(const ShapeClass *shape)
{
return shape->computeArea(shape);
}

RectangleClass继承基类shapeclass

 typedef struct {
ShapeClass shape;
float width, height;
} RectangleClass;

static float rectangle_computeArea(const ShapeClass *shape)
{
const RectangleClass *rect = (const RectangleClass *) shape;
return rect->width * width->height;
}

构造函数

 void rectangle_new(RectangleClass *rect)
{
rect->width = rect->height = 0.f;
rect->shape.computeArea = rectangle_computeArea;
}

不同参数的构造函数,哈

 void rectangle_new_with_lengths(RectangleClass *rect, float width, float height)
{
rectangle_new(rect);
rect->width = width;
rect->height = height;
}

客户端调用

 int main(void)
{
RectangleClass r1;

rectangle_new_with_lenghts(&r1, 4.f, 5.f);
printf("rectangle r1's area is %f units squaren", shape_computeArea(&r1));
return 0;
}

瑾兮 2017-05-14 16:26:05

1:推荐看一下Python的源码实现,能解决你的问题: Python源码剖析
2:GTK+,c语言写的,采用采用面向对象设计思想,框架扩展性极强:GTK+ 的面向对象机制

甜柠檬 2017-03-14 11:47:22

给一个模拟代码:

 typedef struct { // Instance
void *klass; // "Class" of the instance
int x;
} Base;

typedef struct { // Class (Class is virtual-methods table)
void (*foo)();
} BaseClass;

typedef struct {
Base parent; // Derived derives Base
int y;
} Derived;

typedef struct {
BaseClass parent_class;
} DerivedClass;

void foo_base() {
printf("hello from basen");
}

void foo_derived() { // overrides foo_base()
printf("hello from derivedn");
}

BaseClass bc;
bc.foo=foo_base;

DerivedClass dc;
dc.foo=foo_derived;

Base* base_new() { // Constructor
Base *b = malloc(sizeof(Base));
b->klass=&bc;
return b;
}

Derived* derived_new() { // Constructor
Derived *d = malloc(sizeof(Derived));
((Base*)d)->klass = &dc;
return d;
}

// Create two instances.
Base *b = base_new();
Derived *d = derived_new();

// Access member variables
b->x = 42;

((Base*)d)->x = 43; // Inherited member
d->y = 65;

void base_print_member_x(Base* b) { // Method of Base
printf("%dn",b->x);
}

base_print_member_x(b); // outouts 42

// polymorphism: It is the show time!!!!!!!!!

Base instances[2] = {b,d};
for(int i=0;i<2;i++) {
Base* inst = instances[i]; // We consider both b and d as "Base", even though d is "Derived"
BaseClass* klass = inst->klass; // Remember that klass->foo is overwritten in Derived.

klass->foo();
}

总结:
- 类用结构体表示。
- 继承的时候,子类的结构体中第一个成员是父类,这样子类结构指针只要强制转换成父类结构指针,就能当父类用。

- “方法”就是第一个元素是实例指针的普通函数。

- 虚函数存在另一个“类结构”中,每个类只有一个,独立于实例存在,里面存虚函数的指针
- 子类的虚函数覆盖父类,就是在子类的类结构中,把相应的虚函数指针赋成不同的函数。

虐人心 2017-02-24 00:37:43

1、封装
利用C的特殊语法,在头文件中提前声明结构,在C文件才真正定义它。这样可以把结构的全部数据信息都隐藏起来。因为外部不知道对象所占内存的大小,所以不能静态的创建该类的对象,只能调用类提供的创建函数才能创建。这种方法的缺陷是不支持继承,因为子类中得不到任何关于父类的信息。如:
头文件:

 struct _LrcPool;
typedef struct _LrcPool LrcPool;

LrcPool* lrc_pool_new(size_t unit_size, size_t n_prealloc_units);
void* lrc_pool_alloc(LrcPool* thiz);
void lrc_pool_free(LrcPool* thiz, void* p);
void lrc_pool_destroy(LrcPool* thiz);

struct _LrcPool
{
size_t unit_size;
size_t n_prealloc_units;
};

LrcPool* lrc_pool_new(size_t unit_size, size_t n_prealloc_units)
{
LrcPool* thiz = LRC_ALLOC(LrcPool, 1);

if(thiz != NULL)
{
thiz->unit_size = unit_size;
thiz->n_prealloc_units = n_prealloc_units;
}
return thiz;
}

2、继承

 struct _GObject
{
GTypeInstance g_type_instance;
volatile guint ref_count;
GData *qdata;
};

struct _GtkObject
{
GObject parent_instance;
guint32 flags;
};

struct _GtkWidget
{
GtkObject parent_instance;
guint16 private_flags;
guint8 state;
guint8 saved_state;
gchar *name;
GtkStyle *style;
GtkRequisition requisition;
GtkAllocation allocation;
GdkWindow *window;
GtkWidget *parent;
};

3、多态

 struct _LrcBuilder;
typedef struct _LrcBuilder LrcBuilder;

typedef LRC_RESULT (*LrcBuilderBegin)(LrcBuilder* thiz, const char* buffer);
typedef LRC_RESULT (*LrcBuilderOnIDTag)(LrcBuilder* thiz, const char* key, size_t key_length,
const char* value, size_t value_length);
typedef LRC_RESULT (*LrcBuilderOnTimeTag)(LrcBuilder* thiz, size_t start_time);
typedef LRC_RESULT (*LrcBuilderOnLrc)(LrcBuilder* thiz, const char* lrc, size_t lrc_length);
typedef LRC_RESULT (*LrcBuilderEnd)(LrcBuilder* thiz);
typedef LRC_RESULT (*LrcBuilderDestroy)(LrcBuilder* thiz);

struct _LrcBuilder
{
LrcBuilderBegin on_begin;
LrcBuilderOnIDTag on_id_tag;
LrcBuilderOnTimeTag on_time_tag;
LrcBuilderOnLrc on_lrc;
LrcBuilderEnd on_end;
LrcBuilderDestroy destroy;
char priv[1];
};

实现一:

 LrcBuilder* lrc_dump_builder_new(FILE* fp)
{
LrcDumpBuilder* data = NULL;
LrcBuilder* thiz = (LrcBuilder*)calloc(sizeof(LrcBuilder) + sizeof(LrcDumpBuilder), 1);

if(thiz != NULL)
{
thiz->on_begin = lrc_dump_builder_on_begin;
thiz->on_id_tag = lrc_dump_builder_on_id_tag;
thiz->on_time_tag = lrc_dump_builder_on_time_tag;
thiz->on_lrc = lrc_dump_builder_on_lrc;
thiz->on_end = lrc_dump_builder_on_end;
thiz->destroy = lrc_dump_builder_destroy;
data = (LrcDumpBuilder*)thiz->priv;
data->fp = fp != NULL ? fp : stdout;
}
return thiz;
}

实现二:

 LrcBuilder* lrc_default_builder_new(void)
{
LrcDefaultBuilder* data = NULL;
LrcBuilder* thiz = (LrcBuilder*)calloc(sizeof(LrcBuilder) + sizeof(LrcDefaultBuilder), 1);
if(thiz != NULL)
{
thiz->on_begin = lrc_default_builder_on_begin;
thiz->on_id_tag = lrc_default_builder_on_id_tag;
thiz->on_time_tag = lrc_default_builder_on_time_tag;
thiz->on_lrc = lrc_default_builder_on_lrc;
thiz->on_end = lrc_default_builder_on_end;
thiz->destroy = lrc_default_builder_destroy;
data = (LrcDefaultBuilder*)thiz->priv;
}
return thiz;
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文