[英]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;
}
}
work like I want it to: 首先,這像我想要的那樣:
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
what I want. 這我想要的。 我希望它像其他功能那樣打印。
有什么方法可以解決這個問題嗎? 也許任何方式可能做整個派生類的事情好一點?
您的程序行為未定義:
Base b;
b.var0 = 23;
vec.push_back(&b);
正在推回指向超出范圍的變量( b
)的指針。
為什么不使用std::vector<std::unique_ptr<Base>>
呢? 對象切片不會成為問題,向量將為您管理內存。
這與對象切片無關,而且與您在向量中存儲指向局部變量的指針有關。 一旦變量聲明的范圍已經結束,變量就會被破壞,留下亂碼指針,並且解除引用這些雜散指針會導致未定義的行為 。
在你說工作正常的程序中也有這個問題。 看似工作正常是一種或未定義行為的可能性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.