new带有虚函数的对象数组,调用方法时崩溃

new带有虚函数的对象数组,调用方法时崩溃

抽象的基类

class base
{
public:
    base(){}
    virtual ~base(){}
    virtual void close() = 0;
};

派生类:

class derive:public base
{
public:
    derive(){}
    virtual ~derive(){}
    virtual void close() override
    {
        printf("derive::close\n");
    }
private:
    uint32_t    mDevice;
};

调用代码:

int main(int argc,char** argv)
{
    base * ptr = new derive[2];
    ptr[0].close();
    ptr[1].close();
    return 0;
}
运行结果:

第一个close能成功调用,调用第二个close,程序崩溃。

尝试

把 派生类的成员 mDevice 注释掉就不会崩溃了。
把 基类和派生类的 虚函数 去掉,也不会崩溃。
所以怀疑是不是这样生成对象数组,虚函数指针有什么问题?
请哪位明白的解释一下,谢谢。

new derive[2]是动态创建derive对象数组,数组里每个元素是derive类型
你把这个数组的首地址赋给基类指针ptr,然后你试图把这个数组当作基类对象数组来访问。显然这里基类和派生类的大小是不一样的,所以当你把这个数组当着基类对象数组来访问时,除了第一个元素地址是对的,其他元素地址就错位了(因为基类和派生类大小不一样)
你应该定义基类指针数组来存储指向派生类的指针

base *ptr[5];
for (int i = 0; i < 5; i++)
    ptr[i] = new derive;
for (int i = 0; i < 5; i++)
   ptr[i]->close();

derive *d = new derive[5];
base *ptr[5];
for (int i = 0; i < 5; i++)
    ptr[i] = &d[i];
for (int i = 0; i < 5; i++)
    ptr[i]->close();

做了如下尝试:

    base * ptr = NULL;
    derive *dd = new derive[2];
    ptr = dd;

    cout << &ptr[0] << endl;
    cout << &ptr[1] << endl;

    cout << &dd[0] << endl;
    cout << &dd[1] << endl;

程序输出如下
0x76196c
0x761970
0x76196c
0x761974

基类指针与派生类指针差了4,正好是一个指针长度。

不要对数组是使用多态