When using a factory to create an object, such as in the example below, in certain circumstances the objected wrapped by the shared_ptr apparently gets deleted during the return process (during debugging the object is created OK but when it is assigned to this->xs an exception is thrown). When I change the factory method to return a raw pointer, and the Link::xs member to be a unique_ptr the code runs fine. What is going on under the hood with shared_ptr to cause it to behave this way? Is it related to the fact that shared_ptr<CrossSection> is wrapping a Circular object? Testing has been done using MS Visual C++ 2012.
class Link
{
private:
std::shared_ptr<xs::CrossSection> xs;
public:
void parseXsection(const std::vector<std::string>& parts);
std::shared_ptr<xs::CrossSection> getXs() { return this->xs; }
};
void Link::parseXsection(const std::vector<std::string>& parts)
{
this->xs = xs::Factory::create(parts[1]);
}
namespace xs
{
class CrossSection
{
};
class Circular : public CrossSection
{
};
class Dummy : public CrossSection
{
};
class Factory
{
public:
static std::shared_ptr<CrossSection> create(const std::string& type);
};
std::shared_ptr<CrossSection> Factory::create(const std::string& type)
{
if (geom == "circular")
{
return std::shared_ptr<CrossSection>(new Circular());
}
else
{
return std::shared_ptr<CrossSection>(new Dummy());
}
}
}
So, Martin has one option for fixing a destructor problem. You could add a virtual destructor.
However, because you're using std::shared_ptr, which employs a bit of type erasure, you could do a smaller fix:
std::shared_ptr<CrossSection> Factory::create(const std::string& type)
{
if (geom == "circular")
return std::shared_ptr<Circular>(new Circular());
else
return std::shared_ptr<Dummy>(new Dummy());
}
Or, even better:
std::shared_ptr<CrossSection> Factory::create(const std::string& type)
{
if (geom == "circular")
return std::make_shared<Circular>();
else
return std::make_shared<Dummy>();
}
You definitely need to define a virtual destructor in your CrossSection base class in order to use polymorphism, i.e. in order to declare derived classes and use them in place of the parent class (so generally almost everytime you want to use derived classes ...)
class CrossSection {
public:
virtual ~CrossSection() { /* Nothing to do here ... */ }
};
See e.g. When to use virtual destructors? or Should every class have a virtual destructor? for more explanations.
PS: I cannot say right now, if this is the cause for your problems with shared_ptr, but it looks a lot like the kind of problems you might encounter if you forget virtual destructors ...
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