exception and polymorphism problem

J

josh

Hi I have this code:

class Exception : public exception
{
public:
Exception(string m="exception!") : msg(m) {}
~Exception() throw() {}
const char* what() { return msg.c_str(); }

private:
string msg;
};

int main()
{
try
{
throw Exception();
}
catch(exception e)
{
cout << e.what() << endl;
}

return 0;
}

when I run it I don't have print out my message "exception!" but
St9exception

why?
 
?

=?iso-8859-1?q?Erik_Wikstr=F6m?=

Hi I have this code:

class Exception : public exception
{
public:
Exception(string m="exception!") : msg(m) {}
~Exception() throw() {}
const char* what() { return msg.c_str(); }

private:
string msg;

};

int main()
{
try
{
throw Exception();
}
catch(exception e)
{
cout << e.what() << endl;
}

return 0;

}

when I run it I don't have print out my message "exception!" but
St9exception

Because you catch the exception by value, so you copy-construct a new
std::exception from the Exception that was thrown, catch the exception
by reference instead and it will work:

catch (exception& e)
 
M

mimi

Hi I have this code:

class Exception : public exception
{
public:
Exception(string m="exception!") : msg(m) {}
~Exception() throw() {}
const char* what() { return msg.c_str(); }

private:
string msg;

};

int main()
{
try
{
throw Exception();
An exception object is always created at the throw point.We reference
it as "temp" here.
}
catch(exception e)
The exception declaration of a catch clause behaves very much like a
parameter declaration. Here, e is another object of type exception
(Not Exception) that initialized by the "temp" of type Exception.
{
cout << e.what() << endl;
So, here, the e.what() refers to the what() member function of class
Exception, but not class exception.
 
J

josh

Because you catch the exception by value, so you copy-construct a new
std::exception from the Exception that was thrown, catch the exception
by reference instead and it will work:

catch (exception& e)

yes I've forgotten that...... so it print 9Exception but not
my msg string may be I didn't override the right what() ?

P.S.
I try to read the source of exception.h and exception.cpp but in my
gcc source I didn't find it!
where are them?
 
Z

Zeppe

josh said:
yes I've forgotten that...... so it print 9Exception but not
my msg string may be I didn't override the right what() ?

no, you did. the problem, as Eric said, is that if you don't put the
reference a new std::exception is created by copy-constructor. And for
the standard exception the what behaves differently that for your class.
P.S.
I try to read the source of exception.h and exception.cpp but in my
gcc source I didn't find it!
where are them?

it depends. For me, /usr/include/c++/4.1.2/exception

Regards,

Zeppe
 
J

josh

no, you did. the problem, as Eric said, is that if you don't put the
reference a new std::exception is created by copy-constructor. And for
the standard exception the what behaves differently that for your class.


it depends. For me, /usr/include/c++/4.1.2/exception

Regards,

Zeppe

I do it but still the code doesn't work.

....

try
{
throw Exception();
}
catch(exception &e)
{
cout << e.what() << endl;
}
....

here e is a reference to the new Exception() created so
at run-time e.what() should point to my Exception class
and to print "exception!" but it doesn't do that and print
9Exception ... why?
 
M

Markus Moll

Hi
no, you did. the problem, as Eric said, is that if you don't put the
reference a new std::exception is created by copy-constructor. And for
the standard exception the what behaves differently that for your class.

No, he did not. In std::exception it is
virtual const char* what() const throw();

So it should read:

class Exception : public exception
{
public:
Exception(string m="exception!") : msg(m) {}
~Exception() throw() {}
const char* what() const throw () { return msg.c_str(); }

private:
string msg;
};

The const is part of the function signature and thus necessary for
overriding while without the throw() part the program would be ill-formed.

Markus
 
J

josh

Hi



No, he did not. In std::exception it is
virtual const char* what() const throw();

So it should read:

class Exception : public exception
{
public:
Exception(string m="exception!") : msg(m) {}
~Exception() throw() {}
const char* what() const throw () { return msg.c_str(); }

private:
string msg;

};

The const is part of the function signature and thus necessary for
overriding while without the throw() part the program would be ill-formed.

Markus

yes that was my wrong (and also to make Exception not a reference) now
it works!!!
 
J

James Kanze

Because you catch the exception by value, so you copy-construct a new
std::exception from the Exception that was thrown, catch the exception
by reference instead and it will work:
catch (exception& e)

Just a detail, but he's probably not going to be modifying the
object, so:
catch ( exception const& e )
would be more appropriate. (In practice, in the case of
exceptions, I don't think it makes much difference, but using
const systematically when appropriate is a good habit to get
into.)
 
B

BobR

josh said:
I do it but still the code doesn't work.
...

try{
throw Exception();
}
catch(exception &e){
cout << e.what() << endl;
}
...

here e is a reference to the new Exception() created so
at run-time e.what() should point to my Exception class
and to print "exception!" but it doesn't do that and print
9Exception ... why?

Catch the right thing!

catch( Exception const &e ){
cout << e.what() << endl;
}

..... or, re-throw() the std::exception() in your derived class.

I am guessing (have not tested this yet), so, try it, see what happens.
 
B

BobR

Hi Bob.... Oh wait, I'm Bob! <G> [answering my own post]

Hi josh,

Ok, after a very little testing, it seems that your class (derived from
std::exception) 'slices', removing your '*.what() when passed to the
'catch(std::exception&)'. By the time I downcasted it to 'Exception' there
is a problem with 'const' which I couldn't find a combination to (for the
few minutes I tried).
Catch the right thing!
// > catch( Exception const &e ){
catch( Exception &e ){ // 'const' no work.
cout << e.what() << endl;
}
.... or, re-throw() the std::exception() in your derived class.
I am guessing (have not tested this yet), so, try it, see what happens.

If you derive your class from 'std::runtime_error', the 'slicing' does not
happen.
( no '*.what()' in 'Exception3' to slice, duh! )

class Exception3 : public std::runtime_error { public:
Exception3( std::string const &msg = "exception3!")
: std::runtime_error( msg ){}
};

{ // main or function
try{
throw Exception3();
}
catch( std::exception const &e ){
cout<<"caught std::exception= " << e.what() << std::endl;
} // catch( exception& )

try{
throw Exception();
}
catch( std::exception const &e ){
cout<<"caught std::exception= " << e.what() << std::endl;
} // catch( exception& )
}
// output: caught std::exception= exception3!
// output: caught std::exception= 9Exception // sliced

Is there a reason you cannot use 'Exception3'?
( remember, if you just want to catch *any* exception, you can set up
default handlers.)
 
B

BobR

BobR said:
Catch the right thing!
catch( Exception const &e ){
cout << e.what() << endl;
}
.... or, re-throw() the std::exception() in your derived class.
I am guessing (have not tested this yet), so, try it, see what happens.

[ Answering my own post again! ]
Hey, always try just one more thing!! Duh!

try{
throw Exception();
}
// catch( std::exception const &e ){ // no 'const'
catch( std::exception &e ){
Exception *ex = dynamic_cast<Exception*>( &e );
if( ex ){
cout<<"caught std::exception= "<<ex->what()<<std::endl;
}
} // catch(exception&)

// output: caught std::exception= exception!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,767
Messages
2,569,571
Members
45,045
Latest member
DRCM

Latest Threads

Top