Reputation: 564
I want to construct a std::vector
containing objects derived from the Base
class. I know that I can't directly push the whole object into the vector
(cause of object slicing) so I use smart pointers. However, it still doesn't work. What am I doing wrong?
My code:
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 !
}
Upvotes: 0
Views: 454
Reputation: 72271
The Derived
objects and their num2
members are there, but the type system doesn't know that (and in similar code, it might not be certain).
The type of someList[0]
is std::unique_ptr<Base>
, so the ->
operator allows naming members of Base
. In general, a unique_ptr<Base>
might not point at a Derived
at all, so this is the safe way.
If the Base
type were polymorphic, you could use dynamic_cast
to check if the object really is a Derived
. To get this working, let's add a virtual destructor to Base
:
struct Base{
int num1;
explicit Base(int num1){
this->num1 = num1;
}
virtual ~Base() = default;
};
Then we can do:
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;
}
For real code, it's considered better design to make use of virtual functions in Base
rather than using lots of if(dynamic_cast)
checks.
Upvotes: 2