我正在嘗試將許多從基類派生的物件存盤在std::array(或任何其他容器)中而無需物件切片。
下面代碼片段的所需輸出是:
Hi from child1!
Hi from child2!
和代碼:
#include <iostream>
#include <array>
#include <memory>
class Base {
public:
void hello() {
std::cout << "This shouldn't print\n";
}
};
class Child1 : public Base {
public:
void hello() {
std::cout << "Hi from child 1!\n";
}
};
class Child2 : public Base {
public:
void hello() {
std::cout << "Hi from child 2!\n";
}
};
std::array<std::unique_ptr<Base>, 2> array = {std::make_unique<Child1>(Child1()), std::make_unique<Child2>(Child2()) };
int main() {
for (auto &i : array) {
i->hello();
}
}
我實際上從代碼中得到的輸出是:
This shouldn't print
This shouldn't print
顯然,派生物件已被切片。有沒有辦法避免這種情況?
提前感謝您提供的任何建議。
uj5u.com熱心網友回復:
顯然,派生物件已被切片。
實際上,沒有。他們沒有被切片。您在陣列中存盤指向派生類物件的基類指標是正確的。
不,代碼不能按照您想要的方式作業,不是因為物件切片,而是因為您根本沒有在派生類中標記為hello()和在派生類中。因此,當您在回圈內部呼叫時,不會執行多型調度。virtualBaseoverridei->hello()
另外,您使用std::make_unique()不正確。的引數按make_unique<T>()原樣傳遞給 的建構式T。在這種情況下,您是從臨時/物件復制構建Child1/類,這是不必要的。你可以擺脫臨時工。Child2Child1Child2
您還virtual缺少Base. 當您的陣列超出范圍并且s 嘗試呼叫它們的指標時,這將導致未定義的行為。只有解構式會被呼叫,而不是/解構式。unique_ptrdeleteBase*BaseChild1Child2
試試這個:
#include <iostream>
#include <array>
#include <memory>
class Base {
public:
virtual ~Base() = default;
virtual void hello() {
std::cout << "This shouldn't print\n";
}
};
class Child1 : public Base {
public:
void hello() override {
std::cout << "Hi from child 1!\n";
}
};
class Child2 : public Base {
public:
void hello() override {
std::cout << "Hi from child 2!\n";
}
};
int main() {
std::array<std::unique_ptr<Base>, 2> array = {
std::make_unique<Child1>(),
std::make_unique<Child2>()
};
for (auto &i : array) {
i->hello();
}
}
在線演示
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/440068.html
