指针运算和继承导致未定义的行为

Pointer Arithmetic and Inheritance result in undefined behauviour

当 运行 我的程序在第二次执行 cout<<Core32->name() 时终止。在研究了这个问题之后,我了解到在这种情况下指针运算会导致问题。我也可以通过用 Core32+04; 替换 Core32++; 来解决问题(真的不知道为什么会这样)。尽管如此,我的问题是为什么我能够调用方法 Core32->procfun() 而不是 Core32->name()。我查找了对象切片,但它似乎并没有解决我的问题。

编辑:想知道为什么它只能调用 procfun() 而不能调用 name()。 这是一个旧考试的例子

#include <iostream>
#include<string>

using namespace std;

class Prozessor{
public:
    virtual string name()=0;
};

class ARM : public Prozessor{
public:
    virtual string name(){return "VAR";};
    virtual int procbitw()=0;
    string procfun(){return "VFP";};
};

class ARMv7:public ARM{
public:
    int procbitw(){return 32;};
    string procfun(){return "VFP";};
};

class ARMv8:public ARM{
public:
    int procbitw(){return 64;};
    string procfun(){return "VFP, NEON";};
};

int main()
{
    const unsigned int n_cores=4;

    ARM *HetQuadCore[n_cores]={new ARMv7, new ARMv7, new ARMv8, new ARMv8};
    ARMv7* Core32=(ARMv7*)HetQuadCore[0];
    for(int i =0;i<n_cores;i++)
    {
        cout<<Core32->procfun()<<endl;
        cout<<Core32->name()<<endl;
        cout<<"Bandwith is "<<HetQuadCore[i]->procbitw()<<endl;
        Core32++;
    }
    return 0;
}

您可以调用 Core32->procfun,因为它不是虚函数(因此不需要访问 vtable)并且不使用任何内部数据。
由于 this 参数无效,因此对内部数据的任何访问都可能会失败。

question is why I was able to call the Method Core32->procfun() but not Core32->name()

因为行为未定义。

在这两种情况下都未定义。一种可能的行为是 "I was able to call the Method"。另一种可能的行为是 "my programm it terminates".

Also i was able to fix the problem by substituting Core32++; with Core32+04

一种可能的行为可能看起来像 "i was able to fix the problem",但仅仅因为它可能看起来如此,并不意味着未定义的行为已得到修复。

问题是 Core32 不是指向数组元素的指针,因此递增它不会产生有效对象。你可以这样做:

for(int i =0;i<n_cores;i++)
{
    if (auto ptr7 = dynamic_cast<ARMv7*>(HetQuadCore[i]))
        cout<<ptr7->procfun()<<endl;
    else if (auto ptr8 = dynamic_cast<ARMv8*>(HetQuadCore[i]))
        cout<<ptr8->procfun()<<endl;
    cout<<HetQuadCore[i]->name()<<endl;
    cout<<"Bandwith is "<<HetQuadCore[i]->procbitw()<<endl;
    Core32++;
}

但是,将 procfun 虚拟化可能会更好。

你增加了错误的东西。

你有一个指针数组,对吧?而且你还有一个指针指向那个数组中的一个指针。

您正在递增对象指针之一,而不是数组指针。

Array      Hypothetical     Objects              Your pointer
          "array pointer"  (scattered)             "Core32"
                                                       ┃
╔══════╗ «━━━━ aPtr            ╔═══════╗               ┃
║ ptr1 ║━━━━━━━━━━━━━━━━━━━━━━»║ ARMv7 ║«━━━━━━━━━━━━━━┛
╠══════╣   ↓  ++aPtr           ╚═══════╝
║ ptr2 ║━━━━━━━━━━━━━━━━━━━━━━━━┓                  ╔═══════╗
╠══════╣   ↓  ++aPtr            ┃  ╔═══════╗  ┏━━━»║ ARMv8 ║
║ ptr3 ║━━━━━━━━━━━━━━━━━━━━━━┓ ┗━»║ ARMv7 ║  ┃    ╚═══════╝
╠══════╣   ↓  ++aPtr          ┃    ╚═══════╝  ┃
║ ptr4 ║━━━━━━━━━━━━━━━━━━━━━┓┗━━━━━━━━━━━━━━━┛  ╔═══════╗
╠══════╣   ↓  ++aPtr         ┗━━━━━━━━━━━━━━━━━━»║ ARMv8 ║
║   …  ║                                         ╚═══════╝
╙┄┄┄┄┄┄╜

因为这些对象 [可能] 分散,增加 Core32 只会让你胡说八道。这永远不能保证有效。只有当 new 调用为您提供内存中相邻的动态分配对象时,它才会起作用。

您应该只使用 i 来迭代数组,就像您已经在做的那样,或者使用一个指针 aPtr 来迭代数组的元素,然后再次取消引用以获得元素指向的对象。