为什么这段代码会在提到的地方崩溃?

Aam*_*mir 5 c++ arrays virtual

你能详细说明为什么这个代码在提到的地方崩溃了吗?我有点难过.我想这与它有关,sizeof(int)但我不太确定.谁能解释一下?

class Base
{
public:
    virtual void SomeFunction() 
    {
        printf("test base\n");
    }

    int m_j;
};

class Derived : public Base {
public:
   void SomeFunction() 
   {
       printf("test derive\n");
   }

private:
   int m_i;
};

void MyWonderfulCode(Base baseArray[])
{
   baseArray[0].SomeFunction();  //Works fine
   baseArray[1].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[2].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[3].SomeFunction();  //Works fine
   baseArray[4].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[5].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[6].SomeFunction();  //Works fine
   baseArray[7].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[8].SomeFunction();  //Crashes because of invalid vfptr
   baseArray[9].SomeFunction();  //Works fine
}
int _tmain(int argc, TCHAR* argv[])
{
   Derived derivedArray[10];
   MyWonderfulCode(derivedArray);
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

laa*_*lto 16

sizeof(Derived)大于sizeof(Base).这就是原因.

通常,Foo在索引处索引对象数组的i工作方式如下:

element_address = array_base_address + i * sizeof(Foo)
Run Code Online (Sandbox Code Playgroud)

如果数组元素不是预期的大小,您可以看到此索引如何中断.为什么它适用于某些索引是因为有时计算的元素地址指向内存中的有效对象(但它实际上不是第三i个对象).


Dan*_*nas 13

永远不要多态地处理数组.C++语言不支持这一点.(另见相关问题.)


Nav*_*een 12

从这个FAQ中引用:派生数组是否与base数组相同?

派生比Base大,用第二个对象baseArray完成的指针算法是不正确的:编译器在计算第二个对象的地址时使用sizeof(Base),但是数组是Derived的数组,这意味着计算的地址(以及随后的调用成员函数f())甚至不在任何对象的开头!它在Derived对象的中间.


sha*_*oth 9

数组不能用于存储不同类型的对象或用于多态处理对象 - 而是存储指针.

大小BaseDerived不同 - 看到Base[]数组的代码无法检测到它实际上是一个Derived[]数组,只是错误地索引数组产生各种未定义的行为.