返回信息流就是如何模拟封装、继承和多态,某次面试问我的,没答出来,网上讨论的也不少,想听听大牛们的解释~~~~
这是一条镜像帖。来源:北邮人论坛 / cpp / #29749同步于 2009/10/11
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
用C语言如何模拟面向对象的三个特性?
never115
2009/10/11镜像同步7 回复
订阅后,新回复会通过你的通知中心匿名送达。
7 条回复
封装用结构体
继承把基类(结构体)作为派生类(结构体)的第一个成员,然后用指针强制转换
多态,函数指针吧
就想到这些
【 在 never115 (竹马) 的大作中提到: 】
: 就是如何模拟封装、继承和多态,某次面试问我的,没答出来,网上讨论的也不少,想听听大牛们的解释~~~~
随便写个类逆向一下你就知道,很简单的原理
【 在 never115 (竹马) 的大作中提到: 】
: 就是如何模拟封装、继承和多态,某次面试问我的,没答出来,网上讨论的也不少,想听听大牛们的解释~~~~
【 在 FadeToBlack 的大作中提到: 】
: 随便写个类逆向一下你就知道,很简单的原理
多态的实现:
mov eax, 【ecx】
call dword ptr 【eax+虚函数偏移】
说得都好简单啊。。。
Child c;
Base* pb=(Base*)&c;
pb->print();
要让print是不同的行为,要建个类似虚表的东西吗?
【 在 never115 的大作中提到: 】
: 说得都好简单啊。。。
: Child c;
: Base* pb=(Base*)&c;
: ...................
不用什么虚表的,直接在结构内用函数指针变量就行了,然后在适当的时候修改就产生多态了
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 base\n");
}
void foo_derived() { // overrides foo_base()
printf("hello from derived\n");
}
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("%d\n",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();
}
总结:
- C语言没有类,实例用结构体表示。
- 继承的时候,子类的结构体中第一个成员是父类,这样子类结构指针只要强制转换成父类结构指针,就能当父类用。
- “方法”就是第一个元素是实例指针的普通函数。
- 虚函数存在另一个“类结构”中,每个类只有一个,独立于实例存在,里面存虚函数的指针
- 子类的虚函数覆盖父类,就是在子类的类结构中,把相应的虚函数指针赋成不同的函数。
详情请看GLib的GObject
封装不太好做。可以在实例结构里放一个指向私有成员的指针,但这个私有成员的定义在.c文件里,不能被include,所以外部的用户无法知道。
// priv.h:
typedef struct _MyPrivate MyPrivate; // We don't have struct MyPrivate in this file.
typedef struct _MyInstance MyInstance;
struct _MyInstance {
MyPrivate *priv;
};
MyInstance* my_instance_new();
// priv.c
#include "priv.h"
struct _MyPrivate {
int x; // A private member
};
MyInstance* my_instance_new() {
MyInstance* self = malloc(sizeof(MyInstance));
self->priv = malloc(sizeof(MyPrivate));
return self;
}