什么是多态
定义一个虚基类ISpeaker
class ISpeaker{
protected:
size_t b;
public:
ISpeaker( size_t _v )
: b(_v)
{}
virtual void speak() = 0;
};
有两个子类,都实现了虚函数speak():
class Dog : public ISpeaker {
public:
Dog()
: ISpeaker(0)
{}
//
virtual void speak() override {
printf("woof! %llu\n", b);
}
};
class Human : public ISpeaker {
private:
size_t c;
public:
Human()
: ISpeaker(1)
, c(2)
{}
virtual void speak() override {
printf("hello! %llu\n", c);
}
};
main方法中把Dog*和Human*类型的指针,退化(强转)成ISpeaker*指针,并调用speak()方法:
int main( int argc, char** _argv ) {
Human* pHuman = new Human();
Dog* pDog = new Dog();
//
ISpeaker* speaker1 = (ISpeaker*)pHuman;
ISpeaker* speaker2 = (ISpeaker*)pDog;
//
speaker2->speak();
speaker1->speak();
//
return 0;
}
输出:
woof! 0
hello! 2
同样类型的指针(都是ISpeaker*),其函数表现出不同的行为(输出不同),称为多态
编译器如何实现多态
以MSVC编译器为例
编译器处理虚类ISpeaker时,生成内存模型(结构体)__ispeaker,其成员有虚表指针SpeakerTable* vt
。
Dog继承ISpeaker,所以__dog会包含__ispeaker中的成员;
Human继承ISpeaker,所以__human会包含__ispeaker中的所有数据,此外还有自己的数据size_t c
SpeakerTable是虚表结构体
__dogSpeakerTable和__humanSpeakerTable是SpeakerTable的实例
参考:
http://showlinkroom.me/2017/08/21/C-%E9%80%86%E5%90%91%E5%88%86%E6%9E%90/
https://www.bilibili.com/video/BV15g4y1a7F3/?spm_id_from=333.337.search-card.all.click&vd_source=0fcfb2f2f346ba4bccf7f3ee3eb4ae69