具有自动存储持续时间的虚拟功能似乎不起作用

时间:2016-06-02 14:20:46

标签: c++ polymorphism virtual-functions

我在使用自动存储持续时间声明的对象使用虚函数时遇到问题。这是一个可重现的场景:

>>> set(a) & set(b)
{'shampoo', 'product'}
>>> set(b) - set(a)
{'random', 'nothing'}

这打印“A”,而我​​希望它打印B.我很好奇为什么。

提前谢谢!

3 个答案:

答案 0 :(得分:8)

你在这里slicing

void setItem(A item) {
    this->item = item;
}

当您将B传递到item时,setItem()部分会被切掉,因此您将失去其中的基础部分。如果A是抽象的,那么这将是一个更明显的错误(因为你不能按值存储抽象类)。

相反,您希望将项目存储为指针。

答案 1 :(得分:4)

这种现象称为对象切片

基本上,当您将itemB类型)传递给setItem(需要A)时,您将失去每个 B的信息,因为B无法存储A

因此,当您致电printClassName时,它只会从A了解该功能,因此会从A调用该功能。

一种可能的解决方案是将指针传递给对象,而不是原始数据。这将在您的示例中调用printClassName B,因为不会发生切片。

答案 2 :(得分:3)

为了说清楚,为了避免在这种情况下切换对象,您应该将void setItem(A item)更改为void setItem(A& item)A getItem() A& getItem()

这个(通过引用传递/返回)保留了动态类型,几乎可以肯定你在这种情况下的意图

编辑:我忽略了您存储的对象也是A类型的事实。这不行。你需要将它作为一个指针,以便它能够与静态类型(或引用,但它必须在构造函数中初始化)具有不同的动态类型。

因此,要更改为使用指针,您可以尝试将A item中的Test更改为A* item。然后设置/ get成为:

    void setItem(A& item) {
        this->item = &item;
    }
    A& getItem() {
        return *(this->item);
    }

这为您提供所需的输出。如果您只是测试多态行为,这是可以的,但是对于实际设计需要非常小心(例如,您可能想要考虑是否应该使用std::shared_ptr来共享所有权。)