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

时间:2019-03-01 13:43:01

标签: c++ pointers inheritance pointer-arithmetic

运行我的程序时,它将在第二次执行cout<<Core32->name()时终止。在研究了问题之后,我了解到在这种情况下指针运算会导致问题。我也可以通过用Core32++;代替Core32+04;来解决此问题(不知道为什么会这样)。不过,我的问题是为什么我能够调用方法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;
}

3 个答案:

答案 0 :(得分:8)

您正在增加错误的内容。

您有一个指针数组,对不对?还有一个指向该数组中指针的指针

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

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来迭代数组的元素,然后第二次取消引用以获取对象元素所指向的。

答案 1 :(得分:2)

  

问题是为什么我能够调用方法Core32->procfun()但不能调用Core32->name()

的原因

因为行为是不确定的。

在两种情况下均未定义。一种可能的行为是“我能够调用该方法” 。另一个可能的行为是“我的程序终止”。

  

我还可以通过替换Core32 ++来解决此问题;使用Core32 + 04

一种可能的行为看起来像是“我能够解决问题” ,但仅仅是因为它看起来像这样,并不意味着未定义的行为已得到解决。

问题在于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虚拟化。

答案 2 :(得分:0)

您可以调用def openFile(self): options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getOpenFileName(self, "QFileDialog.getOpenFileName()", "", "All Files (*);;Python Files (*.py)", options=options) if fileName: file = open(fileName) data = file.read() soup = BeautifulSoup(data, "lxml") for item in soup.find_all('strong'): results.append(float(item.text)) print('Score =', results[1]) print('Fps =', results[0]) ,因为它不是虚函数(因此不需要访问vtable)并且不使用任何内部数据。
由于Core32->procfun参数无效,因此对内部数据的任何访问都可能会失败。