我想构造一个包含从Base
类派生的对象的std::vector
。我知道我不能直接将整个对象推入vector
(对象切片的原因(,所以我使用智能指针。然而,它仍然不起作用。我做错了什么?
我的代码:
struct Base{
int num1;
explicit Base(int num1){
this->num1 = num1;
}
};
struct Derived : Base{
int num2;
explicit Derived(int num1, int num2) : Base(num1){
this->num2 = num2;
}
};
int main()
{
std::vector<std::unique_ptr<Base>> someList;
someList.push_back(std::make_unique<Derived>(100, 1));
someList.push_back(std::make_unique<Derived>(100, 2));
std::cout << someList[0]->num2 << std::endl; // <---- Can't access num2 !
}
Derived
对象及其num2
成员都在那里,但类型系统不知道(在类似的代码中,可能不确定(。
someList[0]
的类型是std::unique_ptr<Base>
,因此->
运算符允许命名Base
的成员。通常,unique_ptr<Base>
可能根本不指向Derived
,因此这是安全的方法。
如果Base
类型是多态的,则可以使用dynamic_cast
来检查对象是否真的是Derived
。为了实现这一点,让我们在Base
:中添加一个虚拟析构函数
struct Base{
int num1;
explicit Base(int num1){
this->num1 = num1;
}
virtual ~Base() = default;
};
然后我们可以做:
int main()
{
std::vector<std::unique_ptr<Base>> someList;
someList.push_back(std::make_unique<Derived>(100, 1));
someList.push_back(std::make_unique<Derived>(100, 2));
if (auto* dptr = dynamic_cast<Derived*>(someList[0].get()))
std::cout << dptr->num2 << std::endl;
}
对于实际代码,使用Base
中的虚拟函数比使用大量的if(dynamic_cast)
检查被认为是更好的设计。