Is it possible to do the following: I have an inherited class B from base class A. I want to create a constructor for a method that takes in a unique pointer to class A but still accept unique pointers to class B, similar to pointer polymorphism.
void Validate(unique_ptr<A> obj) {obj->execute();}
...
unique_ptr<B> obj2;
Validate(obj2);
This doesn't seem to work as I've written it (I get a No matching constructor for initialization
error), but I wonder if this is still possible?
Polymorphism works on std::unique_ptr
objects, just as it does on raw pointers. So, if you create a std::unique_ptr<A>
for (the address of) a B
object, then you can pass that to your Validate
function; then, assuming there are virtual functions in the classes, polymorphism will kick-in when you call the execute
function on the passed smart pointer.
#include <iostream>
#include <memory>
class A {
public:
virtual void execute() { std::cout << "From A...\n"; }
virtual ~A() = default;
};
class B :public A {
public:
void execute() override { std::cout << "From B...\n"; }
~B() override = default;
};
void Validate(std::unique_ptr<A>& obj) // MUST pass by reference!
{
obj->execute();
}
int main()
{
B obj2;
std::unique_ptr<A> p2{ &obj2 };
Validate(p2);
return 0;
}
Important Note: Your code attempts to pass a std::unique_ptr
by value ; this is not allowed, as a copy will be made and then that copy will (eventually) be destroyed, and those operations aren't allowed on std::unique_ptr
; thus, in my code, I have changed that argument to be passed by reference .
Your issue doesn't really have anything to do with polymorphism, but rather in how unique_ptr<>
works in general.
If Validate()
is not meant to take ownership of obj
, then it should not accept a unique_ptr<>
in the first place. It should accept either a raw pointer or a reference depending on whether nullptr
is an expected valid value:
void Validate(A* obj) {
if(obj) {
obj->execute();
}
}
...
unique_ptr<B> obj2;
Validate(obj2.get());
// Or
void Validate(A& obj) {obj.execute();}
...
unique_ptr<B> obj2;
Validate(*obj2);
On the other hand, if Validate()
is meant to take ownership of the passed object, then you need to move the pointer, as it cannot be copied, which will null-out the original pointer. That's the whole point of unique_ptr<>
after all. There can only be one of them pointing at a given object.
void Validate(unique_ptr<A> obj) {obj->execute();}
...
unique_ptr<B> obj2;
Validate(std::move(obj2));
// Obj2 is now null.
You cannot copy a unique pointer.
If you wish to transfer the ownership to the Validate
function, then you must move from the unique pointer:
Validate(std::move(obj2));
If ~A
isn't virtual, then you may not use std::unique_ptr<A>
because it would try to destroy the object through a pointer to the base which would result in undefined behaviour. You could use a custom deleter in such case.
If you don't wish to transfer ownership, then don't use a unique pointer parametr in the first place. Use a reference instead:
void Validate(A& obj) {
obj.execute();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.