I have looked over the internet and this thread looking for a complete answer of this situation I am facing. I have read that throwing smart pointers to objects is not very clever. I just want to understand why is this happening. I will explain the situation. Let's imagine this simple hierarchy:
class Foo
{
public: virtual ~Foo() {}
};
typedef tr1::shared_ptr<Foo> SPFoo;
class FooInherited: public Foo { };
typedef tr1::shared_ptr<FooInherited> SPFooInherited;
And let's check this test code:
int main(int argc, char** argv)
{
try
{
throw FooInherited();
}
catch(const Foo& f)
{
cout << "Foo& caught!" << endl;
}
try
{
throw SPFooInherited(new FooInherited());
}
catch(const SPFoo& f)
{
cout << "SPFoo& caught!" << endl;
}
return 0;
}
Everything compiles but in runtime the second try-catch won't be executed. Can someone explain me why? Specially if lines of code like this work perfectly fine in runtime.
void function(const SPFoo& f)
{
}
...
SPFooInherited fi(new FooInherited());
function(fi);
I do understand that the problem is that SPFooInherited does not inherit from SPFoo (even though FooInherited inherits from Foo), but It deeply would like to know what is the compiler/RTE doing differently from the function call example when catching an exception not to be able to solve de situation. Is it because the catch parameter is not the same as a function call parameter? Why Foo& works and SPFoo doesn't?
Thank you very much in advance.
Regards, Iker.
Smart pointers are used to make sure that an object is deleted if it is no longer used (referenced). The unique_ptr<> template holds a pointer to an object and deletes this object when the unique_ptr<> object is deleted.
Smart pointers try to prevent memory leaks by making the resource deallocation automatic: when the pointer to an object (or the last in a series of pointers) is destroyed, for example because it goes out of scope, the pointed object is destroyed too. Save this answer.
The main difference is that reference counted smart pointers can be copied (and used in std:: containers) while scoped_ptr cannot. Non reference counted pointers have almost no overhead or no overhead at all.
C++ libraries provide implementations of smart pointers in following types: auto_ptr. unique_ptr. shared_ptr.
As you said in your question, SPFooInherited
is not a subclass of SPFoo
. This means that catch(SPFoo const&)
will not catch instances of SPFooInherited
. On the other hand, FooInherited
is inherited from Foo
, and so catch(Foo const&)
will catch instances of FooInherited
.
To understand this you do not need any special understanding of the compiler or run-time-environment. It is simply a part of the language.
The reason that the call to the function works is that tr1::shared_ptr
has a templated non-explicit constructor that allows an implicit conversion to take place at function call sites.
That is: tr1::shared_ptr
has the following constructor:
//Note the lack of explicit
template<class Y> shared_ptr(shared_ptr<Y> const & r);
This allows a shared_ptr
to be constructed from a different shared pointer type. The implementation of this constructor relys on the implicit conversion from FooInherited*
to Foo*
to actually store the pointer in the SPFooInherited
into the SPFoo
. If this implicit conversion does not exist then the code will not compile, and so unsafe conversions between shared_ptr
s to unrelated types will not occur.
The fundamental difference between the function call and the catch is that implicit conversions will occur in the initialization of function arguments, but a catch can only match a single type (FooInherited
is-a Foo
, so it will match).
Because SPFoo
is not a subclass of SPFooInherited
. catch
blocks will only catch things that are in their catch list, or a public child class of what's in their catch list. FooInherited
does inhertit from Foo
, so catching a Foo
will also let you catch a FooInherited
. SPFoo
and SPFooInherited
are completely different and unrelated classes.
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