c++防止std::vector中的对象切片
c++ prevent object slicing in std::vector
我想在std::vector
中存储多个具有相同基类的类。经过一些研究,我发现我必须使用指针来防止对象切片。然而,当我创建向量,向其添加元素并返回时,生成的向量没有正确的值。
举个例子,这里是我的两个类:
class Base {
public:
int var0;
}
class Derived : public Base {
public:
int var1;
}
这里有一个简单的print
函数。通常,Base
的所有实例都应该具有var0 == 23
,而Derived
的所有实例应该具有var0 != 23
。
void print(Base& value) {
if (value.var0 == 23) {
std::cout << "Base: " << value.var0 << std::endl;
} else {
Derived d = (Derived&) value;
std::cout << "Derived: " << d.var0 << ", " d.var1 << std::endl;
}
}
首先,这个可以像我希望的那样工作:
int main() {
int num = 10;
std::vector<Base*> vec;
for (int i = 0; i < num; i++) {
if (i % 2 == 0) {
Base b;
b.var0 = 23;
vec.push_back(&b);
} else {
Derived d;
d.var0 = 17;
d.var1 = 42;
vec.push_back(&d);
}
}
// ....
for (int i = 0; i < num; i++) {
print(*vec.at(i));
}
}
此打印:
Base: 23
Derived: 17,42
Base: 23
Derived: 17,42
Base: 23
Derived: 17,42
Base: 23
Derived: 17,42
Base: 23
Derived: 17,42
现在,我希望这个向量由一个函数返回,所以我创建了一个函数:
std::vector<Base*> createVector(int num) {
std::vector<Base*> vec;
for (int i = 0; i < num; i++) {
if (i % 2 == 0) {
Base b;
b.var0 = 23;
vec.push_back(&b);
} else {
Derived d;
d.var0 = 17;
d.var1 = 42;
vec.push_back(&d);
}
}
return vec;
}
int main() {
int num = 10;
std::vector<Base*> vec = createVector(num);
// ....
for (int i = 0; i < num; i++) {
print(*vec.at(i));
}
}
此打印:
Derived: 2293232,0
Derived: 17,42
Derived: 2293232,0
Derived: 17,42
Derived: 2293232,0
Derived: 17,42
Derived: 2293232,0
Derived: 17,42
Derived: 2293232,0
Derived: 17,42
这不是我想要的。我希望它像其他函数一样打印。
有什么办法解决这个问题吗?有什么方法可以让整个派生类的事情做得更好一点吗?
您的程序行为未定义:
Base b;
b.var0 = 23;
vec.push_back(&b);
正在将指向超出范围的变量(b
)的指针推回。
为什么不使用std::vector<std::unique_ptr<Base>>
呢?对象切片将不是一个问题,矢量将为您管理内存。
这与对象切片无关,而是与在向量中存储指向局部变量的指针有关。一旦变量在其中声明的作用域结束,变量就会被销毁,留下杂散指针,并且取消引用这些杂散指针会导致未定义的行为。
你也有这个问题,你说的程序运行良好。看似工作良好是未定义行为的一种或多种可能性。
相关文章:
- 避免矢量中的对象切片<Base><shared_ptr>
- 专门化模板覆盖函数/避免对象切片
- C++ 被此代码与多态性、指针和对象切片混淆
- 我们能胜过对象切片吗?
- 如何在考虑对象切片的同时通过传入单个 Base 对象来打印出数组中的对象?
- 成员变量和对象切片
- 如何在不引入未来对象切片的情况下实现 ICloneable
- 避免对象切片
- 故意对对象切片是一种可行的技术吗?
- 对象切片:通过按值派生为 Base - 安全还是危险?
- C++ CRTP 派生类对象切片
- C++ - 即使在使用指针后也能进行对象切片
- 了解对象切片
- 使用对象切片可靠地从多个基类之一中复制
- 对象切片和隐式类型转换
- 一种克服对象切片的方法
- 按引用传递可避免对象切片
- 使用CRTP时的对象切片
- 对象切片:从基类对象访问分层的类方法
- 这会导致对象切片吗?