Is there a way to prevent one particular object of being destroyed while another object still exists, without explicitly making the class of the second one to know about the first?
Here is an example:
class A { /* A creates B*/ };
class B {};
int main() {
auto spA = std::make_shared<A>();
auto spB = spA->getB();
spA.reset();
spB->DoSomething();
}
After spA.reset(), I would like to have at least one reference to the object pointed by spA. Or, in other words: I would like to destroy the object pointed by spA only after calling spB->DoSomething().
But, an important prerequisite is B is not allowed to "know" about A (e.g. it is not allowed to hold a pointer/reference to it).
As I understand, shared pointers provide some functionality which can help with dealing with this problem, but I am not sure which one.
EDIT:
The brief structure of A and B look as follows:
class A
{
public:
A()
{
m_B = B::FactoryB();
}
std::shared_ptr<B> getB()
{
return m_B;
}
private:
std::shared_ptr<B> m_B;
};
class B
{
public:
static std::shared_ptr FactoryB()
{
return std::make_shared<B>();
}
};
EDIT2 (MY SOLUTION):
So, using suggestion provided by @MSalters I was able to find a solution that works for me. In this case it was much simpler than expected, such that I only needed to adjust A::getB():
std::shared_ptr<B> getB()
{
std::shared<B> spBAlias(this->shared_from_this(), m_B.get());
return spBAlias;
}
Here, instead of just returning m_B, A::getB() creates and returns a shared pointer spBAlias of type B (using alias constructor), which influences the reference counting of the A object (provided by this->shared_from_this()). So, calling spA.reset() in the main decreases uses of spA from two to one, making the call of spB->DoSomething() possible. To use shared_from_this(), A needs to inherit from std::enable_shared_from_this<A>:
class A : public std::enable_shared_from_this<A> { /* ... */ }
shared_ptrhas something called an aliasing constructor. Ashared_ptr<B>can be created from ashared_ptr<A>and aB*. The destructor of thisshared_ptr<B>will delete theAobject, not theB.In your case, your
Aobject could itself hold aunique_ptr<B>, or even an outrightBmember.