I have some code that looks something this:
class Info {
public:
virtual bool IsHere() = 0;
virtual std::wstring GetStr() = 0;
};
class WindowsInfo : public Info {
public:
virtual std::wstring GetAnotherStr() = 0;
bool IsHere() override;
};
class AdvancedWindowsInfo : public WindowsInfo {
public:
AdvancedWindowsInfo() {}
~AdvancedWindowsInfo() {}
std::wstring GetAnotherStr() override;
std::wstring GetStr() override;
};
class InfoFactory {
public:
static Info* GetInfo();
};
class InfoManager {
public:
InfoManager();
//~InfoManager();
bool IsSomething();
private:
std::unique_ptr<Info> info;
};
InfoManager::InfoManager() {
#if WIN
info = std::make_unique<WindowsInfo>();
#else // currently no implementation Linux
info = nullptr;
#endif
}
bool InfoManager::IsSomething() {
std::unique_ptr<Info> info = InfoFactory::GetInfo();
return info && info->IsHere();
}
Info* InfoFactory::GetInfo() {
#if IS_WINDOWS
return new AdvancedWindowsInfo();
#else
return nullptr;
#endif
}
The entire code is too large (and confidential) to post here, but this snippet sums it up pretty well.
Essentially, I have a base class and some derived classes.
I also have a manager that uses a (smart) pointer to that base class.
And a Factory Method that returns the appropriate Derived object (although the signature returns a Base*
).
Unfortunately, I can't get the the assignment (via the Factory Method) to work. I've tried multiple approaches but nothing works.
I tried using unique_ptr
and make_unique<raw pointer>()
--> it doesn't work with derived classes, only base.
I tried using unique_ptr
and raw pointers --> conversion is not possible.
I tried using raw pointers (although I don't want this) and raw pointers --> it tells me that the destructor is called on the base object which is abstract. How can you call a destructor when you haven't instantiated the object (since it's an abstract class)? The compiler is contradicting itself!
CodePudding user response:
Let's check the documentation for std::unique_ptr
's constructors. The signature of the relevant constructor:
explicit unique_ptr( pointer p ) noexcept;
(2)
The converting constructor that converts a raw pointer to a std::unique_ptr
is explicit
. Among other things, this means it cannot be used for copy initialization of the form
std::unique_ptr<Info> info = InfoFactory::GetInfo();
Instead, you can use direct initialization:
std::unique_ptr<Info> info{InfoFactory::GetInfo()};
Which will allow you to perform that conversion.
While looking at this code, however, I notice that the local variable info
in InfoManager::IsSomething
is shadowing the class member variable InfoManager::info
. If you want to change an existing std::unique_ptr
so that it's now managing a new raw pointer, you might want to use reset:
info.reset(InfoFactory::GetInfo());
CodePudding user response:
Ok, so I did the following:
InfoFactory::GetInfo()
now returns astd::unique_ptr<Info>
, as indicated by Galik- Added
virtual ~Info() = default;
as indicated by Nathan Pierson
Now everything seems to be working ok. For now, I will the question unanswered as I still need to run some tests and double check some things, but basically it seems to be ok.
Thank you to everyone who made positive contibutions!