从内存上解析c++中数组为什么不支持多态

前段时间在c/c++版块的时候,看到有人问为什么数组对象不支持多态的问题,当时没有回,只是感觉不支持!不能拿出理论和实际证据!后面因为工作也就没有
细想,今天刚好看到酷壳上陈皓老师说的也就来述说一下!

因为这个涉及到内存的问题,所以 我们先来一个小段c语言简单代码


typedef struct 
{
    void *ptrv;
    int  a;  
    char c;
}Base_t;

typedef struct 
{
    void *ptrv;
    int a;
    char c;
    char d[12];
}Derived_t;

int main(void)
{
    Derived_t stB[2] = { 
        {(void*)0x01, 100, 'd', "Derived0"}, 
        {(void*)0x02, 200, 'D', "Derived1"}
    };  
    Base_t *pA = (Base_t *)stB;

//  Base_t *pA = (Base_t *)malloc(2 * sizeof(Base_t));
//  pA[0].ptrv = (void*)0x3;
//  pA[0].a    = 1000;
//  pA[0].c    = 'a';
//
//  pA[1].ptrv = (void*)0x4;
//  pA[1].a    = 2000;
//  pA[1].c    = 'A';
//  Derived_t *pB = (Derived_t *)pA;
    return 0;
}
通过gdb调试看到栈上的数据情况


(gdb) p stB
$4 = {{ptrv = 0x1, a = 100, c = 100 'd', d = "Derived0\000\000\000"}, {ptrv = 0x2, a = 200, c = 68 'D', d = "Derived1\000\000\000"}}
(gdb) p pA[0]
$5 = {ptrv = 0x1, a = 100, c = 100 'd'}
(gdb) p pA[1]
$6 = {ptrv = 0x64657669, a = 48, c = 0 '\000'}
(gdb) q
A debugging session is active.

很明显,pA[0]的还是正确,但是pA[1]的值已经完全被破坏掉了!

上面的例子已经能说明一个部分的原因了,我们再改把main函数里面注释打开,把上面的注释掉再看看


int main(void)
{
//  Derived_t stB[2] = {
//      {(void*)0x01, 100, 'd', "Derived0"}, 
//      {(void*)0x02, 200, 'D', "Derived1"}
//  };
//  Base_t *pA = (Base_t *)stB;

    Base_t *pA = (Base_t *)malloc(2 * sizeof(Base_t));
    pA[0].ptrv = (void*)0x3;
    pA[0].a    = 1000;
    pA[0].c    = 'a';

    pA[1].ptrv = (void*)0x4;
    pA[1].a    = 2000;
    pA[1].c    = 'A';
    Derived_t *pB = (Derived_t *)pA;
    return 0;
}

gdb调试结果如下:


(gdb) n
53		return 0;
(gdb) p pA[0]
$1 = {ptrv = 0x3, a = 1000, c = 97 'a'}
(gdb) p pA[1]
$2 = {ptrv = 0x4, a = 2000, c = 65 'A'}
(gdb) p pB[0]
$3 = {ptrv = 0x3, a = 1000, c = 97 'a', d = "\000\000\000\004\000\000\000\320\a\000\000A"}
(gdb) p pB[1]
$4 = {ptrv = 0x0, a = 135137, c = 0 '\000', d = '\000' <repeats 11 times>}

(gdb) p pB[1]
$4 = {ptrv = 0x0, a = 135137, c = 0 '\000', d = '\000' <repeats 11 times>}

很明显,pB[1]的值,也完全被破坏了!

可见,这完全就是C语言里乱转型造成了内存的混乱,这和C++一点关系都没有。

而且,C++的任何一本书都说过,父类对象和子类对象的转型会带来严重的内存问题。
那我们接下来看看c++的例程:


#include <iostream>
using namespace std;

class Base
{
    public:
        int b;
        virtual ~Base()
        {   
            cout <<"Base::~Base()"<<endl; 
        }   
};

class Derived : public Base
{
    public:
//      int d;  //  注意这个地方,先是注释的,打开的运行又是怎么样的呢?
        virtual ~Derived() { 
            cout <<"Derived::Derived~()"<<endl; 
        }   
};
int main(void)
{
    cout << "size base    = " << sizeof(Base) << endl;
    cout << "size Derived = " << sizeof(Derived) << endl;
    
    Base *pB = new Derived [2];

    delete [] pB; 

    return 0;
}

在子类中,注释 Int d 运行结果如下:


size base    = 8
size Derived = 8
Derived::Derived~()
Base::~Base()
Derived::Derived~()
Base::~Base()
不注释 int d 运行结果如下:


size base    = 8
size Derived = 12
Segmentation fault

上面的代码可以正确执行,包括调用子类的虚函数!因为内存对齐了。

但是如果打开屏蔽的int成员的话,这个程序就Segmentation fault了。

pB[1]的虚表找到了一个错误的内存上,内存乱掉了。

所以通过上面的一个c语言的基本例程和一个c++的例程,大家就可以完全理解为什么c++中数组不支持多态了吧!

从内存这边来分析,这个完全就是c语言的内存管理知识,和c++语言本身一点关系都没有的,如果对c语言内存管理这块熟悉的话,

一眼就知道内存在其中作祟了!所以从c++很多东西也可以看出,c语言确实比较强大!学好了它,其他语言都容易融会贯通了!



  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

max_min_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值