Its probably something really dumb, but I do not understand the g++ output I am getting. I am trying to hold a pointer to a derived object to a virtual base class. When I run the commented code, it works fine and as expected, holding it in the unique_ptr does not compile.
Error message:
In file included from /usr/include/c++/4.9/memory:81:0,
from 2:
/usr/include/c++/4.9/bits/unique_ptr.h: In instantiation of 'typename std::_MakeUniq<_Tp>::__single_object std::make_unique(_Args&& ...) [with _Tp = base; _Args = {derived*}; typename std::_MakeUniq<_Tp>::__single_object = std::unique_ptr<base>]':
20:66: required from here
/usr/include/c++/4.9/bits/unique_ptr.h:765:69: error: invalid new-expression of abstract class type 'base'
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
^
4:7: note: because the following virtual functions are pure within 'base':
6:18: note: virtual void base::foo()
7:18: note: virtual void base::bar()
Sample code
#include <memory>
class base {
public:
virtual void foo() = 0;
virtual void bar() = 0;
};
class derived : public base {
public:
derived() { }
void foo() override { printf("foo\n"); }
void bar() override { printf("bar\n"); }
void foobar() { printf("foobar\n"); }
};
int main()
{
std::unique_ptr<base> dv = std::make_unique<base>(new derived());
dv->foo();
reinterpret_cast<derived*>(dv.get())->foobar();
//base* dv = new derived();
//dv->foo();
//reinterpret_cast<derived*>(dv)->foobar();
}
I know it has to be some dumb error or a big missunderstanding from my part, but I found no solution when searching for virtual base classes with unique_ptr
As mentioned in the comments, the argument(s) to std::make_unique should be those required by the constructor of the created object. In your case, this would be an empty argument list (the derived constructor needs no argument). Further, you cannot create a unique_ptr object to your virtual base class; instead, that should be a pointer to the derived class.
Here is a version that compiles (you don't need to explicitly cast the unique_ptr object: polymorphism will take care of that):
#include <memory>
class base {
public:
virtual void foo() = 0;
virtual void bar() = 0;
virtual ~base() = default; // Add virtual destructor, to be safe!
};
class derived : public base {
public:
derived() { }
void foo() override {
printf("foo\n");
}
void bar() override {
printf("bar\n");
}
void foobar() {
printf("foobar\n");
}
};
int main()
{
std::unique_ptr<base> dv = std::make_unique<derived>();
dv->foo();
return 0;
}
Alternatively (and this may be part of your confusion), you can use the unique_ptr constructor, instead of calling make_unique as the first line of your main:
std::unique_ptr<base> dv{new derived()};
Two problems here: Your base class does not have a virtual destructor. This is required for unique_ptr to be able to destroy the object correctly.
Second, the call to make_unique should look like this:
std::unique_ptr<base> dv = std::make_unique<derived>();
This will create a new unique_ptr<derived> (because you want to create a derived object), which converts implicitly to a unique_ptr<base>.
In your initial example, you were creating a unique_ptr<base> (which holds a base object, not a derived object pointed to by a base pointer!), which you then tried to initialise from a derived* (the result of the new derived expression). This is what caused the compiler error message you saw.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With