How to handle smart ptrs and multiple inheritance?
-
I have a class that implements two interfaces, IA and IB. Some portions of the code manipulate objects through IA pointers and other parts of the code manipulate objects through IB pointers. I would like those IA and IB clients to hold shared_ptr(ia) and shared_ptr(ib) instead of raw pointers. However, the ref count of one of the pointers could reach 0 before the other, delete the object and make the other pointer invalid. How do I practice safe use of smart ptrs of different interfaces to the same object? Thanks
-
I have a class that implements two interfaces, IA and IB. Some portions of the code manipulate objects through IA pointers and other parts of the code manipulate objects through IB pointers. I would like those IA and IB clients to hold shared_ptr(ia) and shared_ptr(ib) instead of raw pointers. However, the ref count of one of the pointers could reach 0 before the other, delete the object and make the other pointer invalid. How do I practice safe use of smart ptrs of different interfaces to the same object? Thanks
If you use Boost
shared_ptr
s[^], the reference count is held on the object rather than the interface you're using - consider this code:#include <boost/shared_ptr.hpp>
#include <iostream>class A
{
public:
~A() { std::cout << "A::~A()\n"; }
};class B
{
public:
~B() { std::cout << "B::~B()\n"; }
};class C : public A, public B
{
public:
~C() { std::cout << "C::~C()\n"; }
};int main(int argc, char** argv)
{
{
std::cout << "Enter pC\n";
boost::shared_ptr<C> pC(new C);
{
std::cout << "Enter pB\n";
boost::shared_ptr<B> pB (pC);
std::cout << "Exit pB\n";
}
{
std::cout << "Enter pA\n";
boost::shared_ptr<A> pA (pC);
std::cout << "Exit pA\n";
}
std::cout << "Exit pC\n";
}
}The output is
Enter pC
Enter pB
Exit pB
Enter pA
Exit pA
Exit pC
C::~C()
B::~B()
A::~A()so, the object is only destructed once, when
pC
goes out of scope. -
If you use Boost
shared_ptr
s[^], the reference count is held on the object rather than the interface you're using - consider this code:#include <boost/shared_ptr.hpp>
#include <iostream>class A
{
public:
~A() { std::cout << "A::~A()\n"; }
};class B
{
public:
~B() { std::cout << "B::~B()\n"; }
};class C : public A, public B
{
public:
~C() { std::cout << "C::~C()\n"; }
};int main(int argc, char** argv)
{
{
std::cout << "Enter pC\n";
boost::shared_ptr<C> pC(new C);
{
std::cout << "Enter pB\n";
boost::shared_ptr<B> pB (pC);
std::cout << "Exit pB\n";
}
{
std::cout << "Enter pA\n";
boost::shared_ptr<A> pA (pC);
std::cout << "Exit pA\n";
}
std::cout << "Exit pC\n";
}
}The output is
Enter pC
Enter pB
Exit pB
Enter pA
Exit pA
Exit pC
C::~C()
B::~B()
A::~A()so, the object is only destructed once, when
pC
goes out of scope.Thanks for the response. Unfortunately, I was not clear enough in my question. The original shared_ptr is a pointer to one of the base classes. Here is an example:
shared_ptr<Base1> pBase1(new Derived);
Derived* pDerived = dynamic_cast<Derived*>(pBase1.get());
shared_ptr<Base2> pBase2(pDerived);This code will crash but I want to accomplish the spirit of the code: 1) Create an object. 2) Somewhere in client code, have safe access to the object in terms of a pointer to one base class. 3) Somewhere else in client code, have safe access to the object in terms of a pointer to another base class. This appears to be more of a design question than a pointer/multiple inheritance use question. Thanks
-
Thanks for the response. Unfortunately, I was not clear enough in my question. The original shared_ptr is a pointer to one of the base classes. Here is an example:
shared_ptr<Base1> pBase1(new Derived);
Derived* pDerived = dynamic_cast<Derived*>(pBase1.get());
shared_ptr<Base2> pBase2(pDerived);This code will crash but I want to accomplish the spirit of the code: 1) Create an object. 2) Somewhere in client code, have safe access to the object in terms of a pointer to one base class. 3) Somewhere else in client code, have safe access to the object in terms of a pointer to another base class. This appears to be more of a design question than a pointer/multiple inheritance use question. Thanks
If you're using Boost shared pointers, that's easy enough to resolve - use
boost::dynamic_pointer_cast
, documented on this page[^], in place ofdynamic_cast
. Here's some code of similar shape to yours that uses it:#include <iostream>
#include <boost/shared_ptr.hpp>class A
{
public:
virtual ~A() { std::cout << "~A\n"; }
};class B
{
public:
virtual ~B() { std::cout << "~B\n"; }
};class C : public A, public B
{
public:
virtual ~C() { std::cout << "~C\n"; }
};int main(int argc, char** argv)
{
boost::shared_ptr<A> pA(new C);
boost::shared_ptr<C> pC = boost::dynamic_pointer_cast<C>(pA);
boost::shared_ptr<B> pB(pC);
} -
If you're using Boost shared pointers, that's easy enough to resolve - use
boost::dynamic_pointer_cast
, documented on this page[^], in place ofdynamic_cast
. Here's some code of similar shape to yours that uses it:#include <iostream>
#include <boost/shared_ptr.hpp>class A
{
public:
virtual ~A() { std::cout << "~A\n"; }
};class B
{
public:
virtual ~B() { std::cout << "~B\n"; }
};class C : public A, public B
{
public:
virtual ~C() { std::cout << "~C\n"; }
};int main(int argc, char** argv)
{
boost::shared_ptr<A> pA(new C);
boost::shared_ptr<C> pC = boost::dynamic_pointer_cast<C>(pA);
boost::shared_ptr<B> pB(pC);
}Thanks a bunch. That works great!