c++ - 虚函数表_c++虚函数表(1)

int D;

};

int main(){
Base* b1 = new Base;
return 0;
}


![](https://img-blog.csdnimg.cn/20190715165211799.png)


这里有个问题:为什么b1中没有成员函数 C 的信息?


因为成员函数在编译期间确定,对象在调用时直接call函数名去调用,所以不需要在对象中存储成


员函数信息。



**2.单继承下的虚函数表(未覆盖)**


代码示例:



class Base{
public:
virtual void A(){ cout << “Base::A()” << endl; }
virtual void B(){ cout << “Base::B()” << endl; }
};

class Derive :public Base{
public:
virtual void C(){ cout << “Derive::C()” << endl; }
virtual void D(){ cout << “Derive:😄()” << endl; }
};

int main(){
Base b1;
Derive d1;

return 0;

}


 ![](https://img-blog.csdnimg.cn/20190715173039342.png)



这里面没有我们派生类的虚函数指针。这是因为编译器故意隐藏了这两个函数。


不过我们可以在通过代码打印出来。


代码示例:



typedef void(*pVtable)(void);

void PrintVTable(pVtable vTable[])
{
// 依次取虚表中的虚函数指针打印并调用。调用就可以看出存的是哪个函数
cout << " 虚表地址>" << vTable << endl;
for (int i = 0; vTable[i] != nullptr; ++i)
{
printf(" 第%d个虚函数地址 :0X%x,->", i, vTable[i]);
pVtable f = vTable[i];
f();
}
cout << endl;
}

int main(){
Base b1;
Derive d1;
pVtable* vTableb = (pVtable*)((int)&b1);
PrintVTable(vTableb);
pVtable* vTabled = (pVtable*)((int)&d1);
PrintVTable(vTabled);

return 0;

}


执行结果:


![](https://img-blog.csdnimg.cn/20190715174654764.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RpbWVjdXI=,size_16,color_FFFFFF,t_70)



**3.单继承下的虚函数表(覆盖)**


代码示例:



class Derive :public Base{
public:
void A(){ cout << “Derive::A()” << endl; }
virtual void C(){ cout << “Derive::C()” << endl; }
virtual void D(){ cout << “Derive:😄()” << endl; }
};


一般来讲基类声明虚函数就是为了让派生类重写,所以我们了解下重写之后的虚函数表。


![](https://img-blog.csdnimg.cn/20190715180348465.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3RpbWVjdXI=,size_16,color_FFFFFF,t_70)


 明显看出此时派生类对象中派生类虚函数地址已将基类虚函数地址覆盖掉了。



**4.多继承下的虚函数表(****未覆盖)**


代码示例:



class Base{
public:
virtual void A(){ cout << “Base::A()” << endl; }
virtual void B(){ cout << “Base::B()” << endl; }
};
class Base2{
virtual void A(){ cout << “Base::A()” << endl; }
virtual void B(){ cout << “Base::B()” << endl; }
};
class Derive :public Base, public Base2{
public:
virtual void C(){ cout << “Derive::C()” << endl; }
virtual void D(){ cout << “Derive:😄()” << endl; }
};


由于多继承下派生类会产生多个虚表,就本例而言会有两个虚表如下图所示:


![](https://img-blog.csdnimg.cn/20190715182918495.png)


 所以我们要取两次虚表地址:
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/b8359765f735a788589b3c781eb9ac95.png)

![img](https://img-blog.csdnimg.cn/img_convert/b7444f5ec6e41c573054d8a646fe71d1.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/2c2d390840eb5ab78da633e069e35a57.png)

 ![img](https://img-blog.csdnimg.cn/img_convert/9d76d596952b358c5db85aa6d8a567c2.png)

![img](https://img-blog.csdnimg.cn/img_convert/7d97488d39e290f38b04e0c74b3f5c28.png)

![img](https://img-blog.csdnimg.cn/img_convert/e2662f201433c037805e90376830fe6c.png)

![](https://img-blog.csdnimg.cn/img_convert/6b8d1cc3340e1bc6660a782adc77294c.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值