运行时多态性 - 箭头运算符访问错误的成员?

Posted

技术标签:

【中文标题】运行时多态性 - 箭头运算符访问错误的成员?【英文标题】:Runtime Polymorphism - Arrow operator accessing the wrong member? 【发布时间】:2020-05-18 08:00:57 【问题描述】:

我的程序中有以下课程:

class base 
public:
    int bval;
    base() 
        bval = 1;
    
;

class deri: public base 
    int dval;
public:
    deri() 
        dval = 2;
    
;

还有一个函数f,它接受指向base类对象的指针和它指向的数组的大小:

void f(base *arr, int size) 
    for(int i=0; i<size; i++, arr++)
        cout << arr->bval << " ";
    
    cout << endl;

这是主要的:

int main() 
    base a[5];
    f(a, 5); // first call

    deri b[5];
    f(b, 5); // second call

第一次调用的输出是1 1 1 1 1,这是正确的。

但是第二次调用的输出是1 2 1 2 1,这让我很意外。对于函数f 内的for 循环的每第二次迭代,似乎dval 的值将代替bval 打印。

此外,如果我在 deri 类中包含另一个私有数据成员 int dval2,则每次执行第二次调用时都会输出 1 2 65535 1 2(因此 65535 看起来不像任何随机值)。

为什么箭头操作符会出现这种行为

【问题讨论】:

您将指针作为base 指针传递,因此指针算法不适合您的deri 数组。 对不起,我误读了这个问题。我已经编辑了我的评论。我仍然建议使用 std::vector 并让 f() 取一个const std::vector&lt;deri&gt;&amp; @ypnos 如果您能解释指针运算作为答案,我将不胜感激。 【参考方案1】:

您将指针作为base 指针传递给f(),因此指针算法不适合您的deri 数组。

此时:for(int i=0; i&lt;size; i++, arr++),只有base的大小被添加到arr,因为arr是一个base指针。

在这种情况下,真正存储什么类型的对象并不重要;增加指针值时不查看它们。

两个有帮助的选项:

    使用 C++ 容器。例如。 std::vector&lt;deri&gt; b(5)void f(const std::vector&lt;deri&gt; &amp;vec)。 传递一个指针数组。在这种情况下,当使用箭头运算符访问指针时,可能会发生多态性。请注意,您的基类需要一个 vtable,您可以通过定义和声明一个虚拟析构函数来获得它(不需要 vtable 来提供预期的输出,但有几个其他原因)。

【讨论】:

即使我们指定了名称,成员是否在后台通过指针运算访问? 会员权限不是你的问题,是循环出错了! @KashinathPatekar,因为 Base* 在编译时被绑定

以上是关于运行时多态性 - 箭头运算符访问错误的成员?的主要内容,如果未能解决你的问题,请参考以下文章

C++基础知识 易错点 总结(待补)

C++基础知识 易错点 总结(待补)

多态分为哪两中

在C++中,啥是运算符重载?啥是虚函数?

使用箭头运算符计算结构的 3 个成员的平均值,需要将点运算符转换为箭头

虚函数和函数重载的问题