Reputation: 1421
I am trying to hold a unique pointer to both a vector (from a Base
class) and a Derivated
class object, so later I am able to call a method for all. However I want to call aswell methods from Derivated
classes so I need to store the reference for them aswell.
class Foo
{
vector<unique_ptr<Base>> bar;
unique_ptr<Derivated1> bar2;
unique_ptr<Derivated2> bar3;
}
Foo::Foo(){
this->bar2 = make_unique<Derivated1>();
this->bar2->doSomethingDerivated1();
this->bar3 = make_unique<Derivated2>();
this->bar->push_back(move(bar2));
this->bar->push_back(move(bar3));
}
Foo::callForAll() {
for (const auto& foo: this->bar) foo->doSomethingBase();
}
Foo::callForDerivated1() {
this->bar2->doSomethingDerivated1();
}
Is something like this possible? For my understanding this code will most likely fail. Will move place bar2
and bar3
to nullptr? Creating a unique_ptr
, store a raw pointer with bar2->get()
and then push_back
to vector
works?
Note: These objects only belong to this class, so unique would make sense.
Upvotes: 0
Views: 71
Reputation: 22623
No. The whole point of unique_ptr is to be unique. This means you cannot copy it.
However, you CAN make copies of the underlying pointer that unique_ptr manages. E.g.
unique_ptr<Foo> foo(new Foo);
Foo* foo_copy = foo.get();
There are a couple things that you need to be careful of when doing this:
Do not delete foo_copy
. That is the job of unique_ptr. If you delete foo_copy, then you will have committed the sin of double delete, which has undefined behavior (i.e. the compiler is allowed to generate code that launches a nuclear missile).
Do not use foo_copy
after foo
has been destroyed because when foo
is destroyed, the underlying pointer is deleted (unless foo has relinquished ownership of the underlying pointer, and the underlying pointer hasn't been deleted by some other means yet). This is the sin of use after free, and it also has UB.
Moving is one way for unique_ptr to relinquish ownership. Once you move out of a unique_ptr, it no longer points to anything (that is the whole point of moving; when you walk from A to B, you are no longer at A, because there is only one of you, and you have decided to instead be located at B). I believe that trying to call a method using the -> operator on an empty unique_ptr is also UB.
It seems like what you should do is
vector<unique_ptr<Base>> v;
Derived* ob = v[i].get();
Let me reiterate that this is slightly dangerous and unusual.
Tangent: I find it highly suspicious that you are not using virtual methods; virtual really should be the default (kind of like how double is the default, not float, even though float looks like it is and should be the default). Actually, I find it suspicious that you are using inheritance. Inheritance is one of the most over-rated features of all time. I suspect that this is where your troubles may be originating. For example, the Go language doesn't even have inheritance, yet it does have polymorphism (i.e. different implementations of the same interface).
PS: Please, do not accidentally extinguish the human race by invoking UB.
Upvotes: 2