C++ new []进入基类指针在数组访问时崩溃

Mar*_*tin 3 c++ arrays polymorphism inheritance

当我分配单个对象时,此代码工作正常.当我尝试添加数组语法时,会出现段错误.为什么是这样?我的目标是向外界隐瞒类c在内部使用b对象的事实.我已将程序发布到键盘供您使用.

#include <iostream>

using namespace std;

// file 1

class a
{
    public:
        virtual void m() { }
        virtual ~a() { }
};

// file 2

class b : public a
{
    int x;

    public:
        void m() { cout << "b!\n"; }
};

// file 3

class c : public a
{
    a *s;

    public:
        // PROBLEMATIC SECTION
        c() { s = new b[10]; } // s = new b;
        void m() { for(int i = 0; i < 10; i++) s[i].m(); } // s->m();
        ~c() { delete[] s; } // delete s;
        // END PROBLEMATIC SECTION
};

// file 4

int main(void)
{
    c o;

    o.m();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Dan*_*nas 9

创建10的阵列b与的new,然后分配给它的地址到a*被找麻烦.

不要多态地处理数组.

有关更多信息,请参阅ARR39-CPP.不要把阵列多态,在部分06.阵列和STL(ARR)的的CERT C++安全编码标准.


Ari*_*Ari 7

一个问题是表达式s[i]使用指针算法来计算所需对象的地址.由于s被定义为指针a,结果对于as 的数组是正确的,对于s 的数组是不正确b的.继承提供的动态绑定仅适用于方法,没有别的(例如,没有虚拟数据成员,没有虚拟sizeof).因此,当调用方法时s[i].m(),this指针被设置为数组中的i第th个a对象.但是因为实际上数组是bs中的一个,它最终(有时)指向对象中间的某个地方并且你得到一个段错误(可能是当程序试图访问对象的vtable时).您可以通过虚拟化和重载来纠正问题operator[]().(尽管如此,我并没有考虑它是否真的有效.)

另一个问题是delete在析构函数中,出于类似的原因.您也可以虚拟化和重载它.(再一次,只是一个随意的想法突然出现在我脑海里.可能不起作用.)

当然,铸造(如其他人所建议的)也会起作用.