涉及多态性的极其奇怪的错误

Extremely weird error involving polymorphism?

本文关键字:错误 多态性      更新时间:2023-10-16

我有一个类,我们称之为A。它有一个名为myFunc的虚拟函数。

class A {
    public:
          virtual void myFunc(){}
}

然后我有一个派生类,称之为 B。

class B: public A {
   public:
          void myFunc() {//does stuff}
}

然后我在另一个名为 C 的类中有一个名为 C 的函数,它接受一个 A 数组。这个数组实际上不是 A 类型,它实际上由 B 的元素或从 A 派生的另一个类组成。

class C {
    private:
           void anotherFunc(A myArray[], int index) {
                myArray[index].myFunc();
           }
}

我本质上希望调用 myFunc,除了由派生类实现的版本,myArray 实际上是,而不是 A 实现的版本。

如果索引为 0,则此方法正常工作。但是由于某种原因,如果它是 0 以外的任何索引,它会因段错误 (EXC_BAD_ACCESS) 而崩溃。

所以我尝试了以下方法:

1)我用调试器在另一个Func中设置断点。出于某种原因,myArray 仅被视为大小为 1 的数组,其他元素由于某种原因没有显示。

2)但是,如果我将在myArray上调用的函数从myFunc更改为其他非虚拟函数,则它适用于所有索引...

知道发生了什么吗?

编辑:这就是另一个Func的称呼方式。

B myArray[7];
//Initialize elements
anotherFunc(myArray, 2);

这个数组实际上不是 A 类型,它实际上由 B 的元素或从 A 派生的另一个类组成。

A myArray[](实际上读取A *myArray,因为它是一个函数参数),准确地指向A对象的数组。 数组是同类的,即所有元素必须是相同的类型。

您的函数需要一个由A对象组成的数组。但是,您的代码提供了一个由B对象组成的数组。 一旦您访问数组的第一个元素之外,事情就会变成蛋奶冻,因为AB对象具有不同的大小。 例如,当编译器计算出要访问myArray[1]的内存地址时,它将在第一个B对象的中途得到一个地址;而不是第二个B对象的地址。

要解决此问题,您需要使函数接受B *,或使用不同的容器。