Topic: Throwing dereferenced pointers invokes copy constructor
Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 2000/01/25 Raw View
Sean Shubin wrote:
> #include <iostream>
>
> using std::cout;
> using std::endl;
>
> class Base
[...]
> class Derived : public Base
[...]
> void
> main()
should be int main.
> {
> Base* b = 0;
> try
> {
> b = new Derived();
> //What is thrown is not what b is pointing to,
> //but a copy of what b is pointing to
You need to introduce a raise member function (which does
the obvious thing) in Base, and call it:
b->raise ();
That's the only way if you don't know the dynamic type
and don't want slicing.
--
Valentin Bonnard
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Sean Shubin <sean.shubin@integtech.com>
Date: 2000/01/22 Raw View
I couldn't find this one in the FAQ.
I was a bit suprised by this behavior.
is this the way standard C++ is supposed to behave,
or is it a bug in the compiler?
#include <iostream>
using std::cout;
using std::endl;
class Base
{
public:
virtual void foo()
{
cout << "Base::foo()" << endl;
}
};
class Derived : public Base
{
public:
virtual void foo()
{
cout << "Derived::foo()" << endl;
}
};
void
main()
{
Base* b = 0;
try
{
b = new Derived();
//What is thrown is not what b is pointing to,
//but a copy of what b is pointing to
throw *b; //Copy constructor gets called here
//Compiler must think it needs a
//temporary variable, even though
//I catch an exception reference
//Code such as "(*b).foo()" works fine
}
//Even though I am catching a reference,
//it is a reference to a copy
catch(Base& ex)
{
//I get Base::foo, not Derived::foo
//It is not dynimic binding that fails,
//it is the fact that an instance of Derived
//was never thrown in the first place
ex.foo(); //Prints "Base::foo()"
}
if(b != 0) delete b;
}
I realize it is unusual to store
an exception in a variable, but
I am writing a multithreaded application,
and I want each thread I create to
defer exception handling to the
main thread. This requires the
exception to be stored in a variable
until the main thread is ready to
receive an exception.
I could also throw and catch pointers
to exceptions, but this requires me
to change ALL of my code that throws
exceptions, even code that does not
know it is in a separate thread.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 2000/01/23 Raw View
In article <387F65BA.2AFB75A@integtech.com>, Sean Shubin
<sean.shubin@integtech.com> writes
>void
well that allows the compiler to do anything it likes:)
>main()
>{
> Base* b = 0;
> try
> {
> b = new Derived();
as there is no virtual dtor for Base you already have another problem.
> //What is thrown is not what b is pointing to,
> //but a copy of what b is pointing to
> throw *b; //Copy constructor gets called here
> //Compiler must think it needs a
> //temporary variable, even though
> //I catch an exception reference
> //Code such as "(*b).foo()" works fine
Yes, but we have a problem because of the lack of virtual ctors and the
compiler always behaves as if a copy ctor was called for an exception
object. Now you will get slicing.
If you really want to do this sort of thing (though it puzzles me as to
why you would) you will have find some mechanism to throw a statically
typed object.
> }
> //Even though I am catching a reference,
> //it is a reference to a copy
Yes, all the catch means is that it can catch any type derived from base
without introducing slicing at this end.
> catch(Base& ex)
> {
> //I get Base::foo, not Derived::foo
> //It is not dynimic binding that fails,
> //it is the fact that an instance of Derived
> //was never thrown in the first place
> ex.foo(); //Prints "Base::foo()"
> }
> if(b != 0) delete b;
>}
Francis Glassborow Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]