Throw object vs throw variable as exception in c++ oop [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 months ago.
Improve this question
I have been reading a book where the object oriented implementation for exceptions is as follows:
Rectangle.hpp
class Rectangle
{
private:
// code
public:
class NegativeSize
{
// empty class declaration
// for exception
};
// code
};
Whenever a specific error occurs, the NegativeSize() is thrown from the constructor as follows:
Rectangle.cpp
void Rectangle::setX(int _x)
{
if (_x < 0)
{
// this instantiates an object
throw NegativeSize();
}
x = _x;
}
main.cpp
try
{
// code
}
catch (Rectangle::NegativeSize)
{
cout << "Negative value entered" << endl;
}
But I can do the same thing by declaring a public variable in Rectangle class and throw it instead:
Rectangle.hpp
class Rectangle
{
private:
// code
public:
string NegativeVal;
// code
};
Rectangle.cpp
void Rectangle::setX(int _x)
{
if (_x < 0)
{
throw NegativeSize;
}
x = _x;
}
main.cpp
try
{
// code
}
catch (string NegativeSize)
{
cout << "Negative value entered" << endl;
}
Can the second implementation be considered a good practice?

The actual exception object that the catch clause will catch is not the object that you name or refer to in the throw expression. Instead the exception object is an object of the same (decayed) type as the throw operand and initialized from the same.
So in your first example you throw an object of type Rectangle::NegativeSize which is initialized from NegativeSize() and in the second example you throw a std::string which is a copy of the NegativeSize member, whatever value it holds at that time.
In the second example catch (Rectangle::NegativeSize) will not work, because NegativeSize is not a type anymore. You will need to catch std::string instead, which of course is a problem, since it doesn't tell you at all what the kind of exception this is (plus some other deeper issues).
Throwing a std::string instead of a specific exception class is therefore not a good practice. You wouldn't be able to differentiate different exceptions and catch only those you can handle in a given catch clause.
Throwing a data member also seems pointless. What value will you set it to? Probably just the "Negative value entered" string? If so, that could be thrown directly as throw std::string("Negative value entered"); as well. As I said above, the exception object is going to be a copy anyway. At the catch clause you can't identify anymore that the throw expression used the NegativeSize member.
Also, in practice exception classes are usually derived from std::exception or a class derived from it and are not empty. They commonly store a string which can be given at the point of the throw expression, so that detailed information from the source of the exception can be provided to the user, e.g.:
class Rectangle
{
private:
// code
public:
struct NegativeSize : std::invalid_argument {};
// code
};
//...
void Rectangle::setX(int _x)
{
if (_x < 0)
{
throw NegativeSize("Negative value entered");
}
x = _x;
}
//...
try
{
// code
}
catch (const Rectangle::NegativeSize& e)
{
cout << e.what() << endl;
}
Also, as I do above, exceptions should usually be caught by-reference.

Related

Why does an exception thrown in a constructor fully enclosed in try-catch seem to be rethrown?

Considering this silly looking try-catch chain:
try {
try {
try {
try {
throw "Huh";
} catch(...) {
std::cout << "what1\n";
}
} catch(...) {
std::cout << "what2\n";
}
} catch(...) {
std::cout << "what3\n";
}
} catch(...) {
std::cout << "what4\n";
}
its output will surely be (and is) what1, because it will be caught by the closest matching catch. So far so good.
However, when I try to create a constructor for a class that tries to initialise a member via member initialiser list (which will result in an exception being raised) like so:
int might_throw(int arg) {
if (arg < 0) throw std::logic_error("que");
return arg;
}
struct foo {
int member_;
explicit foo(int arg) try : member_(might_throw(arg)) {
} catch (const std::exception& ex) { std::cout << "caught1\n"; }
};
int main() {
try {
auto f = foo(-5);
} catch (...) { std::cout << "caught2\n"; }
}
The output of the program is now:
caught1
caught2
Why is the exception being rethrown here (I assume that it is, otherwise why would two catches fire?)? Is this mandated by the standard or is it a compiler bug? I am using GCC 10.2.0 (Rev9, Built by MSYS2 project).
cppreference has this to say about a function-try-block (which is what we have here):
Every catch-clause in the function-try-block for a constructor must terminate by throwing an exception. If the control reaches the end of such handler, the current exception is automatically rethrown as if by throw.
So there we have it. Your exception is automatically rethrown when the catch on the constructor's member initialization list exits. I guess the logic is that your constructor is deemed to have failed so (after the exception handler in the constructor performs any cleanup, perhaps) the exception is automatically propagated to the caller.
While the other answer gives a great official explanation, there is also a really intuitive way to see why things have to behave this way: Consider the alternative.
I've replaced the int with a string to make the issue obvious, but the same principle applies with arithmetic types as well.
std::string might_throw(const std::string& arg) {
if (arg.length() < 10) throw std::logic_error("que");
return arg;
}
struct foo {
std::string member_;
explicit foo(const std::string& arg) try : member_(might_throw(arg)) {
} catch (const std::exception& ex) { std::cout << "caught1\n"; }
};
int main() {
try {
auto f = foo("HI");
std::cout << f.member_ << "\n"; // <--- HERE
} catch (...) { std::cout << "caught2\n"; }
}
What would be supposed to happen if the exception did not propagate?
Not only did arg never make it to member, but the string's constructor never got invoked at all. It's not even default constructed. Its internal state is completely undefined. So the program would be simply broken.
It's important that the exception propagates in such a way to avoid messes like this.
To pre-empt the question: Remember that the reason initializer lists are a thing in the first place is so that member variables can be initialized directly without having their default constructor invoked beforehand.

How to add exception handling

Hi everyone I would like to add exception handling for a couple conditions. Parentheses mismatch when unstacking and and if the expression entered by the user doesn't start and end with #. Mostly just looking for pointers and tips for expression handling in a class and main not a solution.
Here's what I was thinking but its obviously not correct.
This is done in my infixtopost class and I have class invalidExp(){} declared in my header file.
The other exception I tried to handle in main checking the line of input from the user with
if(line[0] != '#' || line[line.length()] != '#') throw "Invalid Expression"
but it would skip over this line and when I put it in a try catch block the rest of the code couldn't exectue.
while (!op->isEmpty() && op->top() != '(') throw invalidExp();
{
post.push_back(op->pop());
if (!op->isEmpty())
{
op->pop();
} //to remove ( from stack
}
main:
try{
IntoPost *infix = new IntoPost(token.length());
post = infix->inToPost(token);
cout << post << "=";
Evalexp *result = new Evalexp(post.length());
result->evalExp(post);
result->print();
}
catch (IntoPost::invalidExp){
cout << "Exception: Invalid Expression" << endl;
}
As I understand your question, you want to declare some custom exception types to handle errors in a clean way. Thats good and the following code will be an example of how this can be done. It's all just an example, to show what is possible.
0: Understanding throw
You can read more about throw here. But in general you can throw anything. throw 1; will throw an int for example. Your example throw "Invalid Expression" will throw a const char*. Usually you want to throw an object of a class that inherits from std::exception.
1: Declare a class for each type of exception you need to handle
It's good practice to let them extend from std::exception. In the constructor I usually create the exception message and pass it to the constructor of std::exception. So the following are just examples:
class ExceptionA : public std::exception {
public:
ExceptionA() : std::exception("Case A occurred!") { }
};
class ExceptionB : public std::exception {
public:
static string CreateMessage(int x, int y) {
// You can create a custom exception message here
}
ExceptionB(int x, int y) : std::exception(ExceptionB::CreateMessage(x, y)) {}
};
As you see in ExceptionB it's totally fine to attach additional data to your exception. This will help you to create a more specific exception message.
2: Sorround your code with a try-multicatch
You can read more about this here
It means, you can use multiple catch-blocks for each try-block.
void foo() {
try {
// Calcultion starts here
// Now you get unexpected input or something like this and signal it by throwing an exception.
if(errorCondition) { throw ExceptionA(); }
// Something else might happen here, so you throw the other type of exception
// in this example ExceptionB also takes two custom parameters.
if(otherErrorCondition) { throw ExceptionB(x, y); }
}
catch(ExceptionA &e) {
// Handle an occurence of Exception A
}
catch(ExceptionB &e) {
// Handle an occurence of Exception B
}
catch(std::exception &e) {
// Handle an occurrence of any other exceptions STL-components migth throw for example std::range_error
}
catch(...) {
// Handle the occurrence of any other thrown ... things. This will also catch things like throw 1, but usually you don't need this.
}
}
Here the order of the catch-blocks is important!
3: Enjoy clean exception handling!
I hope this answers your question!

pass class variable to exception in C++

This is a (modified) problem from a test last week.
I was given an exception class with a predefined number in it:
class ErrorException {
/**
* Stub class.
*/
private :static long ErrorCode;
public: ErrorException( string str) {
cout <<str;
}
};
long ErrorException::ErrorCode = -444;
I think I was supposed to do was catch the exception and then return the number as an error code, but I could not figure out how to get the number in. I could make the catch return a string but not the number as string:
#include "stdafx.h"
#include <iostream>
#include "ErrorException.h"
#include "errno.h""
#include <string>;
class FillerFunction {
public :
virtual int getFillerFunction(int x) throw (ErrorException) = 0;
} // this notation means getFillerFunction is always throwing ErrorException?
double calculateNumber(int y){
//.....
try{
if (y !=0){
throw(ErrorException(?????))
}
};
double catchError(){
catch(ErrorException& x);
};
I eventually made it return the string "error" which is no better than using an if statement. I've looked up other catch-throw examples in c++ and dynamic exceptions, but I can't find an example with an exception grabbing a variable defined in the class.How do I access the ErrorCode, save changing the return type of ErrorException()?
Though this question has already been answered, I just want to add a few notes on proper exception handling in C++11:
First, throw(ErrorException) should not be used, as it is deprecated: http://en.cppreference.com/w/cpp/language/except_spec
Also, it is generally advisable to make use of the fact that C++ provides standard exception classes, personally I usually derive from std::runtime_error.
In order to really take advantage of the exception mechanism in C++11, I recommend using std::nested_exception and std::throw_with_nested as described on StackOverflow here and here. Creating a proper exception handler will allow you to get a backtrace on your exceptions inside your code without need for a debugger or cumbersome logging. Since you can do this with your derived exception class, you can add a lot of information to such a backtrace!
You may also take a look at my MWE on GitHub, where a backtrace would look something like this:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
In your throw you're constructing an exception object. If you prefer to pass a number, you must provide the appropriate constructor.
Quick and dirty:
class ErrorException {
private :
static long ErrorCode;
public:
ErrorException( string str) {
cerr <<str<<endl;
}
ErrorException( long mynumeric code) {
cerr <<"error "<<mynumericcode<<endl;
}
};
The catching should look like:
double calculateNumber(int y){
try {
if (y !=0){
throw(ErrorException(227));
}
} catch(ErrorException& x) {
cout << "Error catched"<<endl;
}
}
Must be elaborated further
It's unusual to to print something in the exception constructor. You'd better populate the information needed in the catch, so that these information could later be accessed with the appropriate getter. The printing would then occur in the exception handler.
If you have a static error code, I suppose that somewhere you have a function that returns the last error code whatever happened. So maybe you'd update this code (but how do you intend to update it with the existing string alternative ?
Here how it could look like:
class ErrorException {
private :
static long LastErrorCode;
long ErrorCode;
string ErrorMessage;
public:
ErrorException(long ec, string str) : ErrorCode(ec), ErrorMessage(str)
{
LastErrorCode = ec;
}
static long getLastError() const { return LastErrorCode; } // would never be reset
long getError() const { return ErrorCode; }
string getMessage() const { return ErrorMessage; }
};
The catching should look like:
double calculateNumber(int y){
try {
if (y !=0){
throw(ErrorException(227,"y is not 0"));
}
} catch(ErrorException& x) {
cerr << "Error "<<x.getError()<<" : "<<x.getMesssage()<<endl;
}
cout << "Last error ever generated, if any: " << ErrorException::getLastErrror()<<endl;
}
Neverthesess, I'd advise you to have a look at std::exception before reinventing the wheel.

Throwing an object of a class defined within a class

I'm reading chapter 16 so that I may begin my assignments for my C++ class. This section is on exception handling. I understand the concept behind a try / catch construct, however, one of the examples in the book is a bit confusing to me. I'm hoping for some explanation as to how this is working. The sample code is below:
// Includes, header guards, and namespace std...
class IntRange
{
private:
int intput;
int lower;
int upper;
public:
// Exception class
class OutOfRange { }; // This is exactly how it appears in the text.
IntRange(int low, int high) { lower = low; upper = high; }
int GetInput()
{
cin >> input;
if (input < lower || input > upper)
throw OutOfRange(); // <-- This is my question in particular. What is this?
return input;
}
};
// End header guard.
// Program entry point.
int main()
{
IntRange range(5, 10)
int userValue;
cout << "Enter a value in the range 5 - 10: ";
try
{
userValue = range.getInput();
cout << "You entered " << userValue << endl;
}
catch (IntRange::OutOfRange) // <-- Again, what is this delcaration and how can
// this data type be defined when IntRange does not
// have a default constructor?
{
cout << "That value is out of range.\n";
}
return 0;
}
The code is exactly as it appears in the textbook, except I put some stuff on the same line in order to keep the question from becomming really long.
If you notice any errors, it's most likely a typo, but the most important points have been double-checked.
throw OutOfRange();
This creates a new instance of class OutOfRange and throws it. Remember that you can also create an instance like this:
my_method( MyClass() );
instead of:
MyClass obj;
my_method( obj );
Now:
catch (IntRange::OutOfRange)
OutOfRange is an inner or nested class of IntRange. See here
throw OutOfRange(); // <-- This is my question in particular. What is this?
This default constructs an object of OutOfRange then throws it.
Even if you do not define a methods in a class the compiler will automatically generate a couple for you one of these is the default constructor. Thus even if you don't specify a constructor there will be one there (Do a google on rule 3/5 for explanation of what methods are generated by the compiler).
catch (IntRange::OutOfRange) // <-- Again, what is this delcaration and how can
// this data type be defined when IntRange does not
// have a default constructor?
Here we are catching an object of type IntRange::OutOfRange. Note: we are not catching an object of IntRange. We are catching the class OutOfRange that happens to be defined inside the class IntRange (apart from where it is defined there is no other relationship).
Also note: Unless you disable it the compiler will automatically generate a copy constructor for all classes. Thus exceptions are usually copy constructed from the throw point to the catch point (its a tiny bit more complex). So your exception object must be copyable.
Also note it is best to catch exceptions by const reference:
catch (IntRange::OutOfRange const& e)
The avoids problems associated with slicing objects that are part of exception hierarchies.
They are creating a custom exception (as a class) called OutOfRange and throwing it.
This way, you can specifically catch an OutOfRange exception, this way:
try
{
//do something
}
catch (OutOfRange o)
{
//you know the input was out of range
}
catch (Exception e)
{
//something else went wrong
}
your OutOfRange class belongs to the IntRange class as a whole - it doesn't belong to any particular object of that class.
In order to use OutOfRange there's no requirement even for IntRange to actually be usable as a concrete class , since IntRange::OutOfRange simply specifies the fully-qualified typename and not an object.
in C++, type names are only important at compile time; data type information (along with variable names and all sorts of other stuff like that in your code) is generally stripped out in its entirety by the compiler - data types only exist to help you write code and to do your debugging.

exception handling a constructor

This was an interview question of me.
Surprisingly i never thought of this kinda question to myself.
can we have exception handling inside a constructor c++?
in tense and not thinking much i said "yes we could probably do it in a constructor.lets say we are allocating some memory using new operator to a pointer member and it throws a bad alloc exception,in this way there is a possibility of exceptions being raised"
Then later i thought that constructors can never return a value.So how can an exception inside a constructor caught.now i am asking this to myself!
can anybody pls help me to come out of this confusion?
See this GOTW Constructor Failures question which addresses your query somewhat and goes on to say it is a waste of time.
Constructors don't have a return type,
so it's not possible to use return
codes. The best way to signal
constructor failure is therefore to
throw an exception. If you don't have
the option of using exceptions, the
"least bad" work-around is to put the
object into a "zombie" state by
setting an internal status bit so the
object acts sort of like it's dead
even though it is technically still
alive.
You would catch the exception in the calling code, not within the constructor.
See How can I handle a constructor that fails? for further details (actually, I'd suggest reading the whole page about exception handling, truly enlightening).
Exception handling and return type are completely different. when the program find the exception in constructor, it throws the exception to nearly by catch block [if used] or thrown to caller (main()). in this case, we have catch block in constructor and exception handled by it. Once exception handled, the remaining statement in the constructor/function will be started executing. see the below example,
class A
{
public:
A(){
printf("Hi Constructor of A\n");
try
{
throw 10;
}
catch(...)
{
printf("the String is unexpected one in constructor\n");
}
printf("Hi Constructor of A\n");
}
~A(){
printf("Hi destructor of A\n");
}
};
int main()
{
try{
A obj ;
throw "Bad allocation";
}
catch(int i)
{
printf("the Exception if Integer is = %d\n", i);
}
catch(double i)
{
printf("the Exception if double is = %f\n", i);
}
catch(A *objE)
{
printf("the Exception if Object \n");
}
catch(...)
{
printf("the Exception if character/string \n");
}
printf("Code ends\n");
return 0;
}
This produce Output:
Start: Constructor of A
the String is unexpected one in constructor
End: Constructor of A
Hi destructor of A
the Exception if character/string
Code ends
C++ has try-catch clauses similar to those of other languages. A tutorial can be found online: http://www.cplusplus.com/doc/tutorial/exceptions/
EDIT: example turned into fully working code
#include <iostream>
using namespace std;
class A
{
public:
void f(){
throw 10;
}
A(){
try{
f();
}
catch(int e){
cout << "Exception caught\n";
}
}
};
int main (int argc, const char * argv[])
{
A a;
return 0;
}
This produces output:
Exception caught