//i_vptr
struct i_vptr
{
virtual void test() = ;
};
//vptr.h
#include "i_vptr.h"
#include <iostream>
class vptr:public i_vptr
{
public:
void test(); };
//vptr.cpp
#include "vptr.h"
void vptr::test()
{
std::cout << "hhhh" << std::endl;
}
//main.cpp
#include "vptr.h"
int main()
{
//这个可以说是我特别晕的,我想到基类的指针怎么会调用到派生类的函数
//vptr从i_vptr继承,就继承了他的vfptr,vfptr指向vtable,每个类有一个vtable
i_vptr* p = new vptr;//会发生切割,切割掉i_vptr没有的东西,所以这个vfptr不会被切割掉,所以指向的还是派生类的vfptr
p->test();//通过vfptr查找vtable,r就可以找到相应的函数地址,所以调用的还是派生类的函数
system("pause");
return ;
}

//下面我觉得挺有用的

需要知道一些常识,一个类所有的函数都是再code代码区中唯一的存放一份。而数据成员则是每个对象存储一份,并按照声明顺序依次存放。
类A中有了虚函数就会再类的数据成员的最前面添加一个vfptr指针(void** vfptr),这个指针用来指向一个vtable表(一个函数指针数组)(一个类只有一个该表),该表存储着当前类的所有 虚函数 的地址。这样vfptr就成为了一个类似成员变量的存在。访问虚函数的时候通过vfptr间址找到vtable表,再间址进而找到要调用的函数。这样就在一定程度上摆脱了类型制约。
只要vptr的值不同,那么访问函数成员的时候使用的vtable表就不同,就可能访问到不同类的函数成员。B类对象中的vptr指向B类自己的vtable。
当B类继承A类的时候,因为A中有虚函数,编译器就自动的给B类添加vfprt指针和vtable表。也可以理解为B类继承来了A类中的那个vptr指针成员。
当A类指针指向B类对象时,发生假切割。要知道这个过程只是切掉A类中没有的那些成员,由于vptr是从A类中继承来的,所以这个量仍将保留。而对于vptr的值则不会改变,仍然指向B类的vtable表。所以访问F1函数的时候是通过B类的vtable表去寻址的,自然就是使用子类的函数。
当B类的指针指向A类的对象时(当B类存在新增数据成员时可能出错),同理。
而对于普通函数则受类型的制约,(因为没有vptr指针)使用哪个类的指针调用函数,那么所调用的就是那个累的函数。
总而言之,普通函数通过对象或指针的类型来找所调用的函数,而虚函数是通过一个指针来找到所要调用的函数的。

最新文章

  1. iOS集成sharesdk遇到的坑
  2. 怎么打开sql server 数据库日志文件
  3. [.net 面向对象编程基础] (16) 接口
  4. vb.net加密解密方法
  5. 关于mvc3.0RadioButtonFor的使用
  6. Postfix之telnet测试
  7. oracle 分区表和分区索引
  8. CodeForce 2A Winner
  9. linux中screen命令的用法
  10. JS学习笔记(四)常用对象
  11. Elasticsearch Java虚拟机配置详解(转)
  12. java基础笔记(3)----函数
  13. Django REST framework 中文文档
  14. 解决 EDAS:Upload failed: The right margin is 0.535 in on page 1 问题
  15. linux 2.6.32文件系统的dentry父子关系
  16. Daily Scrum - 12/0809
  17. Redis高级特性---------事务与持久化与发布订阅
  18. HTML-▲▲video 视频标签全属性详解▲▲
  19. Tomcat热启动
  20. js字符串与Unicode编码互相转换

热门文章

  1. 万字总结:学习MySQL优化原理(转)
  2. 来自 119.*.*.*的回复: TTL 传输中过期
  3. pthread_barrier_init,pthread_barrier_wait简介(转)
  4. 关于Fragment API版本号兼容问题
  5. Azure Storage Blob Go SDK示例
  6. 通过 P3P规范让IE跨域接受第三方cookie session
  7. 微信支付和微信支付通知基于sdk的说明
  8. php的pear包管理
  9. 每天进步一点点——Linux中的文件描写叙述符与打开文件之间的关系
  10. VS2013-解决VS2013 4996错误