编译时的多态性:编译时的多态性是通过重载函数来实现的。
运行时的多态性:运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。C++中,运行时的多态性通过虚成员实现。
参考:https://blog.csdn.net/wenqiang1208/article/details/76244628https://blog.csdn.net/wenqiang1208/article/details/76244628https://blog.csdn.net/wenqiang1208/article/details/76244628
C++ 多态:func()函数 传入子类指针,形参是父类。#includeC语言实现C++的多态:#include "stdio.h" class parent { public: virtual void test() { printf("11111rn"); } }; class child : public parent { public: void test() override{ printf("22222rn"); } }; void func(parent* xx) { xx->test(); }; int main() { child* ch = new child(); func(ch); }
比较核心的点:
- 两个结构体之间的强制转换,以及转换后对方法的调用。
- 通过在结构体A嵌套结构体B,实现A继承B
// main.c #include "stdio.h" #includetypedef void (*Func)(); void baseFunc() { printf("basern"); } void DrivedFunc() { printf("Drivedrn"); } typedef struct base { Func func; }base; typedef struct DRIVED { base base; //结构体嵌套--代表C++的继承 }Drived; int main() { base base; base.func = baseFunc; base.func(); Drived derive; derive.base.func = DrivedFunc; derive.base.func(); base *bb = &base; bb->func(); bb = (base*)(&derive); bb->func(); }
bb = (base*)(&derive); 这里相当于是在C++中子类(derived类)的方法指向父类(base类),也就是子类指向父类指针。
但是C语言中的多态其实是很不安全的!!!!!!
如果把DERIVED结构体改为这样
typedef struct DRIVED
{
int a;
base base; //结构体嵌套--代表C++的继承
}Drived;
再次运行之前的代码:程序会出现段错误。然后就说明这种转换bb = (base*)(&derive) 是有问题的,于是加了点日志
然后根据打印可以看出,所谓的多态其实是假的,bb = (base*)(&derive)本质上就是把derive的地址给了bb, 对于bb来说,调用func在结构体里面是调用的方法内存的位置,当func()打印为0,代表这个转换调用是有问题的,于是返回空指针,而不是方法地址,如果能调用不应该为0(把int a;去掉即可看到不为0)。
结构体的方法调用,是根据这个结构体内这个方法在结构体内的偏移量来调用的,而通过强转后,说白了DERIVED*偏移为0的内存解释数据和base*偏移为0的内存解释是否能匹配,如果可以匹配,那么实现了所谓的多态,所以base类和Derived类的重载的方法必须放在最前面,这样才能保证多态的效果!!!而这种错误在编译不会有问题,在运行会有问题,所以指针的强大和不安全这里有那么点感觉了。



