网站首页 > 资源文章 正文
虚函数机制 virtual mechanism
先看代码:
class A{public:
virtual void print() { cout<<"A.."<<endl; }
};class B : public A{public:
virtual void print() { cout<<"B.."<<endl; }
};
void test4()
{ A a1; //base
B b1;//child
a1 = b1;//A::operator= 对象b1赋值给a2
a1.print(); // prints A
A& a2=b1;// 引用a2指向b1
a2.print();//// prints B}
实现条件:
To get polymorphic behavior in C++, the member functions called must be virtualand objects must be manipulated through pointers or references
Q:
为什么使用派生类和基类对象之间直接赋值不能实现?? 必须用用指针或者引用?
为什么要用虚函数?
A:为什么使用派生类和基类对象之间直接赋值不能实现?? 必须用用指针或者引用?
要实现多态,必须使用指针或者引用 因为默认的赋值运算符并不会操作虚函数表
验证如下:[ Print C++ vtables using GDB]
1.1 vptr 理解成指针 因为不知道vptr内部结果 采用 gdb x查看变量值
因为给出代码只提供一个函数 只需要打印4字节就可以了
(gdb) p sizeof(int) $10 = 4
1.2 打印 A a1; //base
(gdb) p a1
$11 = (A) { _vptr.A = 0x400e10 <vtable for A+16> }
(gdb) x/4x 0x400e10
0x400e10 <_ZTV1A+16>: 0x00400c9e 0x00000000 0x00004231 0x00000000
(gdb) x/4x 0x00400c9e
0x400c9e <A::print()>: 0xe5894855 0x10ec8348 0xf87d8948 0x400dd7be
父类A::_vptr.A 内容是:
0x400c9e <A::print()>
1.3 打印 B b1;//child
执行构造函数:A() -> B() 初始化_vptr
(gdb) p b1 $12 = (B) { = { _vptr.A = 0x400df0 <vtable for B+16> }, }
(gdb) x/4x 0x400df0
0x400df0 <_ZTV1B+16>: 0x00400cc8 0x00000000 0x00000000 0x00000000
(gdb) x/4x 0x00400cc8
0x400cc8 <B::print()>: 0xe5894855 0x10ec8348 0xf87d8948 0x400ddbbe
这说明对象b1.vptr 记录虚函数入口地址 0x400cc8 <B::print()>
只要a1.vptr 指向 b1.vptr 即可
1.4 a1=b1
调用 A::operator=
a1 _vptr 没有发生变化
是不是复制操作有问题这个别人已经验证了
A& operator = (const B& b) { (int )this=(int )&b; return this; }
依然没有发生变化
1.5 A& a2=b1; 发生发生了什么变化
(gdb) p (B*)a2 { = { _vptr.A = 0x400cc8 <B::print()> }, }
(gdb) x/4x 0x400cc8
0x400cc8 <B::print()>: 0xe5894855 0x10ec8348 0xf87d8948 0x400ddbbe
一句话解释:
1.默认的赋值运算符并不会操作虚函数表。
2.要实现多态,必须使用指针或者引用
为什么要用虚函数?
如果不没有声明虚函数 同名函数出现覆盖现象!
A& a2=b1;
假如 b1 [AAAA BBBB]
a2 [AAAA]
A& a2=b1; 对象赋值 只是a.成员=b.成员 其他的就发生强制转换 结果 a2 [AAAA]
函数之间不会赋值的就需要一个记录 函数入口地址
图片可能和代码不符 你应该可以看懂
没有虚函数的对象数据布局
成员类型相同:
成员类型不同(对齐)
有虚函数的对象数据布局
有虚函数的对象数据布局
跟深入地方请查看《Inside the C++ Object Model》
我理解
数据部分:
对象在执行赋值 ==操作时候,如果类型不同会发生强制转换 因此需要相同成员
vptr比较特殊 不能像普通成员一样访问 只能通过指针来实现不同对象赋值
通过命令 gdb x 查看 我只声明一个virtual 因此 n=4
必须使用指针或者引用 为啥它可以如果有清楚麻烦留言告知!
猜你喜欢
- 2025-01-12 恶意代码常见的编程方式
- 2025-01-12 LPL:上野不变,中下换人!LNG 2025年阵容组建完毕
- 2025-01-12 西门子S7-300 SCL编程笔记(附实例)
- 2025-01-12 OLED弧面显示屏VR问世 Void游戏公园团战指日可待
- 2025-01-12 C++如何定义类对象?有哪几种方式?linux C++第17讲
- 2025-01-12 C语言随机数生成
- 2025-01-12 UCGVR主题公园“The Void”宣传影像(内含Gif)
- 2025-01-12 《Void Path》10月30日登陆Steam 日恐诡异探索
- 2025-01-12 西门子S7-1200/1500PLC的程序组成之FC的应用技巧
- 2025-01-12 The VOID开放测试体验,名额被抢购一空
你 发表评论:
欢迎- 05-1430个在线地图瓦片URL分享
- 05-1425个在线地图瓦片URL分享
- 05-14PixelStyle for Mac(mac照片编辑器)
- 05-14一篇文章带你了解CSS3 3D 转换知识
- 05-14我们的世界是假的?马斯克:我们生活在高文明模拟的矩阵游戏中
- 05-14【视觉AI的基石】斯坦福大学笔记!带你吃透卷积神经网络 (CNN)
- 05-14潮流 | 通过AAPE的新价目,无虑入荷未来主义服饰
- 05-14身份证查询服务API:准确识别身份证信息
- 最近发表
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)