前言
看了其它人的例了,发现写得很复杂。参考了许多篇,发现核心思想也不过是那么回事,特此记载
基类
模拟继承
模拟继承就是子类包含所有父类的东西。我们可以直接包含一个父类对象或者父类的指针。在下面的例子中,使用的是父类的对象。
#include <stdio.h>
void baseShow() {
printf("base");
}
struct Base {
void (*show)() = baseShow;
};
struct Child {
Base base; //必须放在最前面
//...其它成员
};
int main() {
Child child;
((Base*)& child)->show();
}
模拟多态
所谓多态就是调用同一个函数有不同的效果。实现原理就是:一个指针指向不同的函数。
我们可以通过在子类中重写基类的函数指针来实现。
#include <stdio.h>
//结构区
struct Base {
void (*show)(void* base); //这个指针会被附不同的函数
int a = 0;
};
struct Child {
Base base;
int b = 1;
};
//函数区
void baseShow(void* base) {
printf("%d\n", ((Base*)base)->a );
}
void childShow(void* child) {
printf("%d\n", ((Child*)child)->b);
}
//测试区
void test(Base* base) {
base->show((void*)base);
}
int main() {
Base base;
Child child;
//相当于构造函数
((Base*)& base)->show = baseShow;
((Base*)& child)->show = childShow;
test((Base*)& base);
test((Base*)& child);
}
模拟多态升级版
使用虚拟表来保存虚函数。比较适合复杂的情况。
#include <stdio.h>
//结构区
//虚拟表,保存了虚函数,是实现多态的基础
struct VTable {
void (*show)(void* base) = 0;
};
struct Base {
VTable vtable; //必须放在最前面
int a = 0;
};
struct Child {
Base base;
int b = 1;
};
//函数区
void baseShow(void* base) {
printf("%d\n", ((Base*)base)->a );
}
void childShow(void* child) {
printf("%d\n", ((Child*)child)->b);
}
void baseConstructor(void* base) {
((VTable*)base)->show = baseShow;
}
void childConstructor(void* child) {
((VTable*)child)->show = childShow;
}
//测试区
void test(Base* base) {
((VTable*)base)->show((void*)base);
}
int main() {
Base base;
baseConstructor((void*)&base);
Child child;
childConstructor((void*)&child);
test(&base);
test((Base*)& child);
}
进一步改进思路
struct Base {
VTable* vtable; //改成指针
int a = 0;
};