I'm new to exception handling and this is a question about a problem I'm having on one of my first assignments on the subject. I have purposely gave the program an invalid entry for hours and seconds to test out the try/catch, so both should throw an exception. I kind of get why the first catch block catches both throws, but I'm not sure then how to get it to use both catch blocks? Thanks! (output is "ERROR: INVALID HOUR ENTRY")
int main()
{
MilTime Object;
string BadHour;
string BadSeconds;
try
{
if ( (Object.getHour() < 0) || (Object.getHour() > 2359) ) throw BadHour;
if ( (Object.getSec() < 0) || (Object.getSec() > 59 ) ) throw BadSeconds;
}
catch (string BadHour)
{
cout << "ERROR, INVALID HOUR ENTRY";
}
catch (string BadSeconds)
{
cout << "ERROR, INVALID SECOND ENTRY";
}
return 0;
catches are differentiated by type, not by argument names.
In principle you could define different exception types, or you could use e.g. std::system_error which allows you to pass an integer error id.
However, in practice the particular cause of an exception is of little interest other than for logging, because it generally doesn't affect what to do about it. An exception says that the code has failed to do what its contract said it should do. A catch can only try to do whatever that goal was, again (possibly in some different way), or in turn fail.
You have to catch exceptions by data type, not by variable name. Try something more like this instead:
#include <iostream>
#include <stdexcept>
class BadHourError : public std::runtime_error
{
public:
BadHourError() : std::runtime_error("") {}
};
class BadSecondsError : public std::runtime_error
{
public:
BadSecondsError() : std::runtime_error("") {}
};
class MilTime
{
public:
int getHour() const { return ...; }
int getSec() const { return ...; }
};
int main()
{
MilTime Object;
try
{
if ( (Object.getHour() < 0) || (Object.getHour() > 2359) ) throw BadHourError();
if ( (Object.getSec() < 0) || (Object.getSec() > 59 ) ) throw BadSecondsError();
}
catch (const BadHourError &)
{
std::cout << "ERROR, INVALID HOUR ENTRY";
}
catch (const BadSecondsError &)
{
std::cout << "ERROR, INVALID SECOND ENTRY";
}
return 0;
}
Alternatively:
#include <iostream>
#include <string>
#include <stdexcept>
class BadTimeError : public std::runtime_error
{
public:
BadTimeError(const std::string &what_arg) : std::runtime_error(what_arg) {}
};
class BadHourError : public BadTimeError
{
public:
BadHourError() : BadTimeError("INVALID HOUR ENTRY") {}
};
class BadSecondsError : public BadTimeError
{
public:
BadSecondsError() : BadTimeError("INVALID SECOND ENTRY") {}
};
class MilTime
{
public:
int getHour() const { return ...; }
int getSec() const { return ...; }
};
int main()
{
MilTime Object;
try
{
if ( (Object.getHour() < 0) || (Object.getHour() > 2359) ) throw BadHourError();
if ( (Object.getSec() < 0) || (Object.getSec() > 59 ) ) throw BadSecondsError();
}
catch (const BadTimeError &ex)
{
std::cout << "ERROR, " << ex.what();
}
return 0;
}
You can see how try/throw/catch is indeed type dependent if you set up your own types i.e. struct's and test as follows:
#include <iostream>
using namespace std;
struct BadHr
{
};
struct BadSec
{
};
int main()
{
int test = 2;
try
{
if (test == 1) throw BadHr();
if (test == 2) throw BadSec();
}
catch (BadHr& e)
{
std::cout << "Bad hour" << std::endl;
}
catch (BadSec& e)
{
std::cout << "Bad Sec" << std::endl;
}
}
Related
I have this:
// exception::what
#include <iostream> // std::cout
#include <exception> // std::exception
struct ooops : std::exception {
const char* what() const noexcept {return "Ooops!\n";}
};
class A: std::exception{
public:
int tt;
int getTT(int rr){
if (rr ==5) throw ooops();
return rr;
};
};
int main () {
try {
A testA;
int ww = testA.getTT("kkk");
std::cout << ww << std::endl;//throw ooops();
} catch (std::exception& ex) {
std::cout << ex.what();
}
return 0;
}
I want to call getTT() with the string above and I want to throw My Exception message instead the default one. I know that If I overload a method from Exception class I will be ok but I am asking if there is a more easy way to do it.I am reading the documentation on Exceptions but I can't find something useful.
You can throw any object. you don't have to inherit from std::exception
#include <iostream>
class A{
public:
int tt;
int getTT(int rr){
if (rr ==5) throw "ooops";
return rr;
};
};
int main () {
try {
A testA;
int ww = testA.getTT(5);
std::cout << ww << std::endl;//throw ooops();
} catch (const char* exc) {
std::cout << exc;
}
return 0;
}
And If you don't know the type of the exception, you can use ..., as follows
#include <iostream>
class A{
public:
int tt;
int getTT(int rr){
if (rr ==5) throw "ooops";
return rr;
};
};
int main () {
try {
A testA;
int ww = testA.getTT(5);
std::cout << ww << std::endl;//throw ooops();
} catch (...) {
std::cout << "exception has been thrown";
}
return 0;
}
Your ooops class should derive from
std::runtime_error instead, which takes a user-defined string as input and overrides what() for you to return that string.
There are other mistakes in your code, too. A should not derive from std::exception. And A::getTT() takes an int as input, but you are trying to pass it a string literal (const char[4]) instead.
Try this instead:
#include <iostream>
#include <stdexcept>
#include <string>
struct ooops : std::runtime_error {
ooops(const std::string &what_arg = "Ooops!")
: runtime_error(what_arg)
{
}
};
class A {
public:
int tt;
int getTT(int rr) const {
if (rr == 5) throw ooops("rr can't be 5");
return rr;
}
};
int main () {
try {
A testA;
int ww = testA.getTT(5);
std::cout << ww << std::endl; // throw ooops();
}
catch (const std::exception& ex) {
std::cout << ex.what() << std::endl;
}
return 0;
}
I've overloaded an operator such that I can return the value of an array. I can handle out of bounds using if:
float arr::operator[](const int i) const
{
if (i < 0)
{
cout << "Outside of array, first entry returned" << endl;
return value[0];
}
else if (i >=size)
{
cout << "Outside of array, last entry returned" << endl;
return value[size-1];
}
else return value[i];
}
but I am learning about exceptions and try-catch blocks.
Is it possible to throw an exception with a different int (for example) for out of upper/lower bounds, and have catches that execute different code depending on the value of that int?
I know that if works well here, but I'm looking to develop my knowledge for use in more complex ideas.
Is it possible to throw an exception with a different int (for example) for out of upper/lower bounds, and have catches that execute different code depending on the value of that int?
Sort of. You can certainly throw a different int value based on a condition, but you would have to catch a single generic int and test its value, you can't catch different int values individually. For example:
const int OutOfBoundsInFront = -1;
const int OutOfBoundsInBack = 1;
float arr::operator[](const int i) const
{
if (i < 0)
throw OutOfBoundsInFront;
if (i >= size)
throw OutOfBoundsInBack;
return value[i];
}
...
try
{
... = myarr[index];
}
catch (int value)
{
switch (value)
{
case OutOfBoundsInFront:
//...
break;
case OutOfBoundsInBack:
//...
break;
}
}
However, when throwing an exception, it is better to throw an object instead of a simple POD type. catch blocks deal in types, not values. In this case, you can define different class types for each condition you want to catch. For example:
#include <stdexcept>
class OutOfBoundsInFront : public std::out_of_range
{
public:
OutOfBoundsInFront() : std::out_of_range("out of bounds in front") {}
};
class OutOfBoundsInBack : public std::out_of_range
{
public:
OutOfBoundsInBack() : std::out_of_range("out of bounds in back") {}
};
float arr::operator[](const int i) const
{
if (i < 0)
throw OutOfBoundsInFront();
if (i >= size)
throw OutOfBoundsInBack();
return value[i];
}
...
try
{
... = myarr[index];
}
catch (const OutOfBoundsInFront &)
{
//...
}
catch (const OutOfBoundsInBack &)
{
//...
}
Alternatively:
#include <stdexcept>
class OutOfBoundsOnSide : public std::out_of_range
{
public:
enum WhichSide { InFront, InBack };
static const char* WhichSideErrorMsg[] = {
"out of bounds in front",
"out of bounds in back"
};
WhichSide whichSide;
OutOfBoundsOnSide(WhichSide side) : std::out_of_range(WhichSideErrorMsg[side]), whichSide(side) {}
};
class OutOfBoundsInFront : public OutOfBoundsOnSide
{
public
OutOfBoundsInFront() : OutOfBoundsOnSide(InFront) {}
};
class OutOfBoundsInBack : public OutOfBoundsOnSide
{
public
OutOfBoundsInBack() : OutOfBoundsOnSide(InBack) {}
};
float arr::operator[](const int i) const
{
if (i < 0)
throw OutOfBoundsInFront();
if (i >= size)
throw OutOfBoundsInBack();
return value[i];
}
...
try
{
... = myarr[index];
}
catch (const OutOfBoundsOnSide &e)
{
switch (e.whichSide)
{
case InFront:
//...
break;
case InBack:
//...
break;
}
}
I am new to try/catch exception handling, and am wondering why my second catch block will not execute. The sec variable should not be between 0-59, so I'd like it to say "invalid second entry", but it doesn't. Thank you!
#include <stdexcept>
#include <iostream>
#include <string>
using namespace std;
class BadHourError : public runtime_error
{
public:
BadHourError() : runtime_error("") {}
};
class BadSecondsError : public runtime_error
{
public:
BadSecondsError() : runtime_error("") {}
};
class Time
{
protected:
int hour;
int min;
int sec;
public:
Time()
{
hour = 0; min = 0; sec = 0;
}
Time(int h, int m, int s)
{
hour = h, min = m, sec = s;
}
int getHour() const
{return hour;}
int getMin() const
{return min;}
int getSec() const
{return sec;}
};
class MilTime : public Time
{
protected:
int milHours;
int milSeconds;
public:
MilTime() : Time()
{
setTime(2400, 60);
}
MilTime(int mh, int ms, int h, int m, int s) : Time(h, m, s)
{
milHours = mh;
milSeconds = ms;
getHour();
getMin();
getSec();
}
void setTime(int, int);
int getHour(); //military hour
int getStandHr();
};
void MilTime::setTime(int mh, int ms)
{
milHours = mh;
milSeconds = ms;
sec = milSeconds;
getSec();
}
int MilTime::getHour()
{
return milHours;
}
int MilTime::getStandHr()
{
return hour;
}
int main()
{
MilTime Object;
try
{
if ( (Object.getHour() < 0) || (Object.getHour() > 2359) ) throw BadHourError();
if ( (Object.getSec() < 0) || (Object.getSec() > 59 ) ) throw BadSecondsError();
}
catch (const BadHourError &)
{
cout << "ERROR, INVALID HOUR ENTRY";
}
catch (const BadSecondsError &)
{
cout << "ERROR, INVALID SECOND ENTRY";
}
return 0;
}
throw will return control to the next matching exception handler. In this case, the next block executed will be your catch (const BadHourError &), so Object.getSec() is never even evaluated. Your handling here is correct, and it will throw but not if your first if statement throw instead.
You could do this instead:
try
{
if ( (Object.getHour() < 0) || (Object.getHour() > 2359) )
throw BadHourError();
}
catch (const BadHourError &)
{
cout << "ERROR, INVALID HOUR ENTRY";
}
try
{
if ( (Object.getSec() < 0) || (Object.getSec() > 59 ) )
throw BadSecondsError();
}
catch (const BadSecondsError &)
{
cout << "ERROR, INVALID SECOND ENTRY";
}
Now they will be handled separately from each other, ensuring they both get tested; however, you need to decide whether it's worth testing both. If an hour is invalid, what does it matter if everything is correct or invalid? Your class probably can't function well, so it doesn't matter if getSec() > 59 if getHour() > 2359
Because your milHour is 2400, so the exception is thrown for the bad hour.
I've been working with exception handling for a long while today. I've figured out to get it to work if it's in a void function, but how do I handle functions that have to return a value. The last 3 lines in main are where the "issue" happens. I found this link earlier to help me get this far, but my exception handling has to all be contained inside the class structure, so I can't have try/throw/catch in main. I'd like to understand what's going on. [1]: What type of exception should I throw?
Thanks in advance.
#include <iostream>
#include <exception>
class out_of_range : public std::exception
{
private:
std::string msg;
public:
out_of_range(const std::string msg) : msg(msg){};
~out_of_range(){};
virtual const char * what()
{
return msg.c_str();
}
};
class divide
{
private:
int a;
int * _ptr;
public:
divide(int r): a(r), _ptr(new int[a]) {};
~divide(){ delete[] _ptr; };
int get(int index) const
{
try
{
if (index < 0 || index >= a)
throw out_of_range("Err");
else
return _ptr[index];
}
catch (out_of_range & msg)
{
std::cout << msg.what() << std::endl;
}
}
int &get(int index)
{
try
{
if (index < 0 || index >= a)
throw out_of_range("Err");
else
return _ptr[index];
}
catch (out_of_range & msg)
{
std::cout << msg.what() << std::endl;
}
}
};
int main()
{
divide test(6);
for (int i(0); i < 6; ++i)
{
test.get(i) = i * 3;
std::cout << test.get(i) << std::endl;
}
std::cout << "test.get(10): " << test.get(10) << std::endl;
test.get(3) = test.get(10);
std::cout << "test.get(3): " << test.get(3) << std::endl;
return 0;
}
If you catch exception in the divide::get method, it must somehow tell its caller that something went wrong. So implementation may look something like that:
class divide
{
//..
bool get(int nIndex, int* nResult);
//...
int main()
//...
int nRes = 0;
if(!test.get(10, &nRes))
cout << "Something is not right";
If there is many things that could go amiss, you could return some error code instead of bool. But if you use this method, there is no need in your exception class, you could simply return error without raising exception at all.
new to the try/catch thing and need to use it for a program. For some reason though my program crashes when it catches the obj. The sample program I wrote just reads in a number and then tests to see if its below 10 or above 20. The point is to use two user defined classes to throw and catch. The above 20 obj gets thrown and catches just fine. But the below 10, if its thrown will crash the program. Why is this? here is my code
#include <iostream>
#include <cstdlib>
using namespace std;
class above20
{
public:
above20()
{
msg = "Number is above 20.";
};
string getmsg()
{
cout<<msg<<endl;
};
private:
string msg;
};
class below10
{
public:
below10()
{
msg = "Number is below 10";
};
string getmsg()
{
cout<<msg<<endl;
};
private:
string msg;
};
int main ()
{
int num;
try
{
cout<<"Enter Number between 10 and 20:"<<endl;
cin >> num;
if (num > 20)
{
throw above20 ();
}
}
catch (above20 obj)
{
obj.getmsg();
}
try
{
if (num < 10)
{
throw below10 ();
}
}
catch (below10 obj)
{
obj.getmsg();
}
system ("pause");
return (0);
}
Are you sure this compiles? Did you omit something in your copy paste? The getmsg() methods don't return anything.
---edit ---
Try this:
void getmsg()
{
cout<<msg<<endl;
};
You have a lot of poor syntax in your code. The error you get is because you declare getMsg with a return value and do not return (UB - you are lucky it even compiles!).
To fix all of your issues: http://ideone.com/1qGAuR
You have a few errors in your code like having a function that doesn’t return anything despite saying that it should in the signature:
string getmsg()
{
cout<<msg<<endl;
};
should really be:
void getmsg()
{
cout<<msg<<endl;
};
or
string getmsg()
{
return string(msg);
};
Putting aside those bugs for a second, from a design point of view inheriting from one exception base class is cleaner. I would usually inherit from std::runtime_error but you could define your own if you wanted. For example :
#include <iostream>
#include <cstdlib>
using namespace std;
class above_below_exception
{
public:
virtual string getmsg() =0;
};
class above20 : public above_below_exception
{
public:
above20()
{
msg = "Number is above 20.";
};
string getmsg()
{
return string(msg);
};
private:
string msg;
};
class below10 : public above_below_exception
{
public:
below10()
{
msg = "Number is below 10";
};
string getmsg()
{
return string(msg);
};
private:
string msg;
};
int main ()
{
int num;
try
{
cout<<"Enter Number between 10 and 20:"<<endl;
cin >> num;
if (num > 20)
{
throw above20();
}
if (num < 10)
{
throw below10();
}
}
catch (above_below_exception& obj)
{
cout << obj.getmsg();
}
return (0);
}
A potential fix for your code:
#include <iostream>
#include <cstdlib>
using namespace std;
class above20 : public std::exception
{
public:
above20()
{
msg = "Number is above 20.";
}
virtual ~above20 () throw ()
{
}
string getmsg ()
{
cout << msg << endl;
return msg;
}
private:
string msg;
};
class below10 : public std::exception
{
public:
below10()
{
msg = "Number is below 10";
}
virtual ~below10 () throw ()
{
}
string getmsg()
{
cout << msg << endl;
return msg;
}
private:
string msg;
};
int main ()
{
int num;
try
{
cout<<"Enter Number between 10 and 20:"<<endl;
cin >> num;
if (num > 20)
{
throw above20 ();
}
}
catch (above20 &obj)
{
cout << obj. getmsg () << endl;
}
try
{
if (num < 10)
{
throw below10 ();
}
}
catch (below10 obj)
{
obj.getmsg();
}
system ("pause");
return (0);
}