C++-C能实现出面向对象的三个特征吗?
C能实现出面向对象里面的封装、继承、多态这几个基本特征吗?如果可以,给出实例代码吧。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
C能实现出面向对象里面的封装、继承、多态这几个基本特征吗?如果可以,给出实例代码吧。
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(4)
“基类”用结构体实现,函数指针很重要,可以用来模拟多态,其原理基本和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;
}
1:推荐看一下Python的源码实现,能解决你的问题: Python源码剖析
2:GTK+,c语言写的,采用采用面向对象设计思想,框架扩展性极强:GTK+ 的面向对象机制
给一个模拟代码:
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();
}
总结:
- 类用结构体表示。
- 继承的时候,子类的结构体中第一个成员是父类,这样子类结构指针只要强制转换成父类结构指针,就能当父类用。
- “方法”就是第一个元素是实例指针的普通函数。
- 虚函数存在另一个“类结构”中,每个类只有一个,独立于实例存在,里面存虚函数的指针
- 子类的虚函数覆盖父类,就是在子类的类结构中,把相应的虚函数指针赋成不同的函数。
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;
}