The first piece of code does not compile, whereas the second one does. Why?
The code is almost the same indeed. I would be grateful to have some help with this question.
The code below does not compile. You could check it on http://cpp.sh/8j53y.
dynamic_cast
#include <iostream>
#include <memory>
using namespace std;
class Derived;
class Base {
public:
static unique_ptr<Base>& get_instance()
{
pBase = make_unique<Derived>();
return pBase;
}
private:
static unique_ptr<Base> pBase;
};
class Derived: public Base { };
std::unique_ptr<Base> Base::pBase = nullptr;
int main () {
auto& instance = Base::get_instance();
return 0;
}
The code below does compile.
#include <iostream>
#include <memory>
using namespace std;
class Derived;
class Base {
public:
static unique_ptr<Base>& get_instance();
private:
static unique_ptr<Base> pBase;
};
class Derived: public Base { };
std::unique_ptr<Base> Base::pBase = nullptr;
unique_ptr<Base>& Base::get_instance()
{
pBase = make_unique<Derived>();
return pBase;
}
int main () {
auto& instance = Base::get_instance();
return 0;
}
When you define Base::get_instance
inline, Derived
doesn't have a definition yet (only the forward declaration). So, it can't convert std::unique_ptr<Derived>
to std::unique_ptr<Base>
, because the definition where Derived
inherits from Base
hasn't been seen yet. For the same reason, std::make_unique<Derived>()
would also fail, because Derived
doesn't have a definition yet.
This is why you need to define Base::get_instance
after the definition of Derived
to compile. You can keep it in a header file by marking it inline
then defining it out of line:
class Base {
public:
static unique_ptr<Base>& get_instance();
private:
static unique_ptr<Base> pBase;
};
class Derived: public Base { };
/*
`inline` here so the definition can appear in multiple translation units
(e.g., directly in the header file)
*/
inline unique_ptr<Base>& Base::get_instance()
{
pBase = make_unique<Derived>();
return pBase;
}