mirror of
https://gitlab.com/fbb-git/cppannotations
synced 2024-11-16 07:48:44 +01:00
ddaf7204d9
git-svn-id: https://cppannotations.svn.sourceforge.net/svnroot/cppannotations/trunk@490 f6dd340e-d3f9-0310-b409-bdd246841980
72 lines
3.2 KiB
Text
72 lines
3.2 KiB
Text
Shared pointers cannot simply be cast using the standard bf(C++) style
|
|
casts. Consider the following two classes:
|
|
verb(
|
|
struct Base
|
|
{};
|
|
struct Derived: public Base
|
|
{};
|
|
)
|
|
A tt(shared_ptr<Derived>) can easily be defined. Since a tt(Derived) is
|
|
also a tt(Base) a pointer to a tt(Derived) can be cast to a pointer to a
|
|
tt(Base) using a static cast:
|
|
verb(
|
|
Derived d;
|
|
static_cast<Base *>(&d);
|
|
)
|
|
However, a plain tt(static_cast) cannot be used when initializing a shared
|
|
pointer to a tt(Base) using the object pointer of a shared pointer to a
|
|
tt(Derived) object. I.e., the following statement will eventually result in an
|
|
attempt to delete the dynamically allocated tt(Base) object twice:
|
|
verb(
|
|
shared_ptr<Derived> sd(new Derived);
|
|
shared_ptr<Base> sb(static_cast<Base *>(sd.get()));
|
|
)
|
|
Since tt(sd) and tt(sb) point at the same object tt(~Base) will be called
|
|
for the same object when tt(sb) goes out of scope and when tt(sd) goes out of
|
|
scope, resulting in premature termination of the program due to a
|
|
emi(double free) error.
|
|
|
|
These errors can be prevented using casts that were specifically designed
|
|
for being used with tt(shared_ptrs). These casts use specialized constructors
|
|
that create a tt(shared_ptr) pointing to memory but shares ownership (i.e.,
|
|
a reference count) with an existing tt(shared_ptr). These special casts are:
|
|
itemization(
|
|
ithtq(static_pointer_cast)
|
|
(std::static_pointer_cast<Base>(std::shared_ptr<Derived> ptr))
|
|
(A tt(shared_ptr) to a tt(Base) class object is returned. The returned
|
|
tt(shared_ptr) refers to the base class portion of the tt(Derived) class to
|
|
which the tt(shared_ptr<Derived> ptr) refers. Example:
|
|
verb(
|
|
shared_ptr<Derived> dp(new Derived());
|
|
shared_ptr<Base> bp = static_pointer_cast<Base>(dp);
|
|
)
|
|
)
|
|
ithtq(const_pointer_cast)
|
|
(std::const_pointer_cast<Class>(std::shared_ptr<Class const> ptr))
|
|
(A tt(shared_ptr) to a tt(Class) class object is returned. The
|
|
returned tt(shared_ptr) refers to a non-const tt(Class) object whereas the
|
|
tt(ptr) argument refers to a tt(Class const) object. Example:
|
|
verb(
|
|
shared_ptr<Derived const> cp(new Derived());
|
|
shared_ptr<Derived> ncp = const_pointer_cast<Derived>(cp);
|
|
)
|
|
)
|
|
|
|
ithtq(dynamic_pointer_cast)
|
|
(std::dynamic_pointer_cast<Derived>(std::shared_ptr<Base> ptr))
|
|
(A tt(shared_ptr) to a tt(Derived) class object is returned. The
|
|
tt(Base) class must have at least one virtual member function, and the class
|
|
tt(Derived), inheriting from tt(Base) may have overridden tt(Base)'s virtual
|
|
member(s). The returned tt(shared_ptr) refers to a tt(Derived) class object if
|
|
the dynamic cast from tt(Base *) to tt(Derived *) succeeded. If the dynamic
|
|
cast did not succeed the tt(shared_ptr)'s tt(get) member returns 0. Example
|
|
(assume tt(Derived) and tt(Derived2) were derived from tt(Base)):
|
|
verb(
|
|
shared_ptr<Base> bp(new Derived());
|
|
cout << dynamic_pointer_cast<Derived>(bp).get() << ' ' <<
|
|
dynamic_pointer_cast<Derived2>(bp).get() << '\n';
|
|
)
|
|
The first tt(get) returns a non-0 pointer value, the second tt(get)
|
|
returns 0.
|
|
)
|
|
)
|