从内存布局看多态性

通过一个实验来说明,代码如下:

#include <iostream>
 
using namespace std;
 
class A {
public:
    int x, y;
    virtual void func() { cout << "This is A" << endl; }
};
 
class B: public A {
public:
    int z;
    void func() { cout << "This is B" << endl; }
};
 
int main()
{
    B b;
    A *pa = &b;
    B *pb = &b;
 
    cout << "memory size = " << sizeof(*pa) << endl;
    cout << "memory size = " << sizeof(*pb) << endl;
 
    pa->func();
    pb->func();
 
    return 0;
}


运行结果:


指针pa和指针pb都指向对象b,但pb所涵盖的地址包含整个对象(x、y、z、vptr),而pa所涵盖的地址只包括基类A的子对象(x、y、vptr)。从两者涵盖的地址范围可以看出,想要通过pa来访问类B中的成员是不允许的(除非类型强制转换),例如数据成员z。但有一个例外,那就是虚函数。从运行结果可以看出指针pa和指针pb都访问了类B中的成员函数,这是因为pa是通过vptr找到这个函数的地址的。pa、pb所指范围包含一个公共的vptr,两者对函数func()的调用都必须通过这一个vptr。vptr相同,vptr所指向的virtual table相同,virtual table内虚函数的地址当然也就相同了,从而调用的是同一个函数。

但如果是针对对象的操作:
B b;        // 派生类对象
A a = b;    // 发生切割


经过这样的初始化之后就不能利用对象a进行多态操作了。a.func()始终调用类A中的func函数。至于切割时编译器到底对它做了什么?这会在以后的学习中详细说明。

环境:
Win7 + Code::Blocks

参考:
《深度探索C++对象模型》 P28-P35.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值