[英]Virtual functions with automatic storage duration does not seem to work
我在将虚拟函数与使用自动存储持续时间声明的对象一起使用时遇到麻烦。 这是一个可重现的方案:
#include <iostream>
class A {
public:
A() {}
virtual ~A() {}
virtual void printClassName() {
std::cout << "A" << std::endl;
}
};
class B : public A {
public:
B() : A() {}
~B() {}
void printClassName() {
std::cout << "B" << std::endl;
}
};
class Test {
private:
A item;
public:
Test() {}
~Test() {}
void setItem(A item) {
this->item = item;
}
A getItem() {
return this->item;
}
};
int main() {
Test t;
B item;
t.setItem(item);
t.getItem().printClassName();
return 0;
}
这会打印“ A”,而我希望它会打印B。我很好奇为什么。
先感谢您!
您在这里切片 :
void setItem(A item) {
this->item = item;
}
当您将item
传递给setItem()
, B
部分会被setItem()
,因此您将失去它的基础部分。 如果A
是抽象的,这将是一个更明显的错误(因为您不能按值存储抽象类)。
相反,您将需要将项目存储为指针。
这种现象称为对象切片 。
基本上,当您将item
(类型为B
)传递给setItem
(使用A
)时,您将丢失B
所有信息,因为B
无法存储在A
。
因此,当您调用printClassName
,它仅从A
知道该函数,因此从A
调用它。
一种可能的解决方案是将指针传递给对象,而不是原始数据。 在您的示例中,这将调用B
printClassName
,因为不会发生切片。
为了清楚void setItem(A item)
在这种情况下,为避免对象切片,应将void setItem(A item)
更改为void setItem(A& item)
, A getItem()
更改为A& getItem()
。
(通过引用传递/返回)保留了动态类型,并且几乎可以肯定是您在这种情况下的意图
编辑:我忽略了您存储的对象也是A
类型的事实。 这行不通。 您需要将其用作指针,以使其能够具有与其静态类型(或引用)不同的动态类型(但必须在构造函数中对其进行初始化)。
因此,要改变使用指针,你可以尝试改变A item
在Test
到A* item
。 然后设置/获取成为:
void setItem(A& item) {
this->item = &item;
}
A& getItem() {
return *(this->item);
}
这将为您提供所需的输出。 如果您只是测试多态行为,这是可以的,但是在实际设计中需要非常小心(例如,您可能要考虑是否应该使用std::shared_ptr
来共享所有权)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.