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.
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;
}
fun(int a) {
if (a) return a; return "empty";
}
I need a function that gets a number and depending on which number it is returns either an int variable or a string.
Please tell me how I can implement such a function.
With C++ 17 you can use variant:
std::variant<int, std::string> fun(int a) {
if (a) return a; return "empty";
}
Or use a struct with optional:
struct r {
std::optional<int> i;
std::optional<std::string> s;
};
r fun(int a) {
r out;
if (a) out.i = a; else out.s = "empty";
return out;
}
Or for prior standards use a struct with fields indicating validity.
struct r {
enum class type {i, s};
int i;
std::string s;
type t;
};
r fun(int a) {
r out;
if (a) {
out.i = a;
out.t = r::type::i;
else {
out.s = "empty";
out.t = r::type::s;
}
return out;
}
Interpret-able languages like python does not have restrictions on type of argument and type of return value. However, C++ can only accept and return values of pre-defined type.
Now, Adding to other answers, if you don't have C++17, You could try it this way:
std::pair<int, string> func(int a)
{
if(a) return std::make_pair(a , "");
return std::make_pair(0,"string");
}
In callee, you can check for non-null against both members of std::pair.
You could accomplish this flow with exceptions! If func is expecting to work with a number that is greater than 5, for example, you could do something like:
int func(int a) {
if (a > 5) { return a; }
throw std::runtime_error("Empty");
}
int main() {
try {
int x = func(3);
// Do some stuff with x...
} catch(const std::exception &e) {
std::cout << "Looks like the num is " << e.what();
}
}
So you either process the int if things went well, or, if something bad happened, you grab the string from the exception and deal with it.
You could accomplish this by splitting the two different tasks into separate functions and continue your execution from there.
#include <iostream>
using namespace std;int inputValue = 0;
int returnInt() {
std::cout << "Returning your int" << std::endl;
return inputValue;
}
string returnString() {
std::cout << "Returning your string" << std::endl;
return "Your string";
}
int main() {
std::cout << "Please type in a number" << "\t";
std::cin >> inputValue;
if (inputValue > 5) {
returnInt();
}
else {
returnString();
}
}
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'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;
}
}
first i used flyweight for string which works fine, but when i use flyweight for a struct. it doesn't work.
the first test case for string is:
static void testflyweightString()
{
char tmp[0];
vector<boost::flyweight<string>> boost_v;
for(int i=0;i<10000000;i++)
{
sprintf(tmp,"zws_%d",i/1000);
boost_v.pushback(boost::flyweight<string>(tmp));
}
return;
}
then i defined a struct A, some properties in A i used flyweight.
testcase2 is as below:
static void testflyweightA()
{
vector<A> boost_v;
for(int i=0;i<10000000;i++)
{
A a();//here new some A;
boost_v.pushback(a);
}
return;
}
but it doesn't have any change for memory used whether i used flyweight in A or not.
First off:
A a();//here new some A;
This is: Most vexing parse: why doesn't A a(()); work?
I prepared this test program:
Live On Coliru
#include <boost/flyweight.hpp>
#include <vector>
#include <iostream>
static void testflyweightString() {
std::cout << __FUNCTION__ << "\n";
std::vector<boost::flyweight<std::string> > boost_v;
for (int i = 0; i < 10000000; i++) {
boost_v.emplace_back("zws_" + std::to_string(i/1000));
}
}
struct A {
boost::flyweight<std::string> s;
A(std::string const& s) : s(s) { }
};
static void testflyweightA() {
std::cout << __FUNCTION__ << "\n";
std::vector<A> boost_v;
for (int i = 0; i < 10000000; i++) {
boost_v.push_back("zws_" + std::to_string(i/1000));
}
}
int main() {
testflyweightString();
testflyweightA();
std::cout << "Done\n";
}
Its memory usage looked ok using valgrind --tool=massif: