I am using C++. C++0x using Visual Studio 2010 to be correct.
Suppose I have a class Z. To make it safer in my application to work with pointers to this class, I can consistently use smart pointers (shared pointer, weak pointer).
Now this class Z inherits from a class X. Some parts of my application will work with pointers to class X, others will work with pointers to class Z.
std::shared_ptr<X>
or std::shared_ptr<Z>
) deletes the instance? Am I sure that if I delete std::shared_ptr<X>
, that the instance is kept as long as there is another std::shared_ptr<Y>
?Now suppose that I use multiple inheritance, where Z inherits from classes X and Y.
Some parts of my application will work with std::shared_ptr<X>
, others with std::shared_ptr<Y>
and others with std::shared_ptr<Z>
.
By the way, how can I safely cast one smart pointer to another, e.g. cast std::shared_ptr<Z>
to std::shared_ptr<X>
? Does this work? Is this allowed?
Notice that I explicitly refer to non-intrusive pointers (as the new std::shared_ptr
and std::weak_ptr
in C++0x). When using intrusive pointers (like in Boost), it probably works since the instance itself is responsible for keeping the counter.
Yes this is supported by the standard, §20.9.11.2.10 [util.smartptr.shared.cast].
The utils you need are:
std::static_pointer_cast<>()
std::dynamic_pointer_cast<>()
They have the same semantics as their C++03 counter parts static_cast<>()
and dynamic_cast<>()
. The one difference being that they only work on std::shared_ptr
s. And just to verbose, they do what you expect and correctly share the reference count between the original and newly cast shared_ptr
s.
struct X { virtual ~X(){} };
struct Y : public X {};
struct Z : public X {};
int main()
{
{
//C++03
X* x = new Z;
Z* z = dynamic_cast<Z*>(x);
assert(z);
x = new Y;
z = dynamic_cast<Z*>(x);
assert(!z);
z = static_cast<Z*>(x);
assert(z); //EVIL!!!
}
{
//C++0x
std::shared_ptr<X> x{new Z};
std::shared_ptr<Z> z{std::dynamic_pointer_cast<Z>(x)};
assert(z);
x = std::make_shared<Y>();
z = std::dynamic_pointer_cast<Z>(x);
assert(!z);
z = std::static_pointer_cast<Z>(x);
assert(z); //EVIL!!!
// reference counts work as expected.
std::shared_ptr<Y> y{std::static_pointer_cast<Y>(x)};
assert(y);
std::weak_ptr<Y> w{y};
assert(w.expired());
y.reset();
assert(w.expired());
x.reset();
assert(!w.expired());
}
{
//s'more nice shared_ptr features
auto z = std::make_shared<X>();
std::shared_ptr<X> x{z};
assert( z == x );
x = z; //assignment also works.
}
}
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