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;
}
Related
Simple program is written as:
#include <iostream>
#include <vector>
using std::vector;
class Test {
public:
Test( int d ) : data(d), addr(&data) {
}
// Test( Test &src ) : data(src.data), addr(src.addr) { }
const int data;
const int *addr;
~Test() {
delete addr;
}
void print() {
std::cout << " Data is : " << data << '\n';
}
};
int main( int, char**, char** ) {
std::vector<Test> data1;
data1.emplace_back( 98 );
for( auto a : data1 )
a.print();
std::cout << "main";
std::cout << std::endl;
return 0;
}
and the output was
Possibly the reason was the destructor called twice
I tried to get some info from : here and there but cant get clear vison.
As mentioned in comments the problem is the delete statement in destructor which is unwanted for non-dynamic data member.
here is my code, when i try running this, main does output the information placed into the LoggerComponent, but not the Logger itself. I don't know why, what could be preventing the logger from passing information into the underlying loggercomponent?
i tried using information from http://www.cplusplus.com/reference/map/map/
and from https://www.geeksforgeeks.org/map-associative-containers-the-c-standard-template-library-stl/
logger.cpp:
#include "logger.hpp"
Logger::Logger(bool verbose, bool fileoutput)
{
if(verbose)
{
LoggerComponent c1(LoggerLevel::DEBUG, &std::cout);
addLogger (LoggerType::CONSOLE, &c1);
c1.output (LoggerLevel::DEBUG, "This is the start of console output");
}
if(fileoutput)
{
}
}
void Logger::output(LoggerLevel level, std::string message)
{
for(auto& x : components)
{
x.second->output (level, message);
}
}
void Logger::addLogger(LoggerType type, LoggerComponent* component)
{
if(components.find (type) == components.end ())
components.emplace(type, component);
}
LoggerComponent* Logger::getLogger (LoggerType type)
{
if(components.find (type) != components.end ())
return components.at (type);
return nullptr;
}
void Logger::clearLoggers()
{
components.clear ();
}
void Logger::removeLogger(LoggerType type)
{
if(components.find (type) != components.end ())
components.erase (type);
}
logger.hpp
#ifndef LOGGER_HPP
#define LOGGER_HPP
#include "loggercomponent.hpp"
#include <map>
enum class LoggerType
{
CONSOLE,
FILE
};
class Logger
{
public:
explicit Logger(bool verbose, bool fileoutput);
void output(LoggerLevel level, std::string message);
void addLogger(LoggerType type, LoggerComponent* component);
void removeLogger(LoggerType type);
void clearLoggers();
LoggerComponent* getLogger(LoggerType type);
private:
std::map<LoggerType, LoggerComponent*> components;
};
#endif // LOGGER_HPP
main.cpp
#include "logger.hpp"
int main()
{
int* p;
int i = 5;
int j = 5;
p = &i;
std::cout << p << std::endl;
p = &j;
std::cout << p << std::endl;
LoggerComponent c(LoggerLevel::DEBUG, &std::cout);
c.output (LoggerLevel::INFO, "Hello World!");
c.output (LoggerLevel::CRITICAL, "Hello World!");
Logger c2(true, true);
std::cout << c.getOutputStream () << std::endl;
std::cout << c2.getLogger (LoggerType::CONSOLE)->getOutputStream () << std::endl;
c2.output (LoggerLevel::INFO, "Hello World!");
c2.output (LoggerLevel::CRITICAL, "Hello World!");
}
loggercomponent.hpp
#ifndef LOGGERCOMPONENT_HPP
#define LOGGERCOMPONENT_HPP
#include <iostream>
#include <string>
#include <ctime>
enum class LoggerLevel
{
INFO,
DEBUG,
WARNING,
ERROR,
CRITICAL
};
class LoggerComponent
{
public:
explicit LoggerComponent(LoggerLevel level, std::ostream* output);
LoggerLevel getMinimumLevel();
std::ostream* getOutputStream();
void setMinimumLevel(LoggerLevel level);
void setOutputStream(std::ostream* output);
void output(LoggerLevel level, std::string outputMessage);
private:
std::string getLevelString(LoggerLevel level);
LoggerLevel minimumLevel;
std::ostream* outputStream;
};
#endif // LOGGERCOMPONENT_HPP
loggercomponent.cpp
#include "loggercomponent.hpp"
LoggerComponent::LoggerComponent(LoggerLevel level,
std::ostream* output)
{
setMinimumLevel (level);
setOutputStream (output);
}
void LoggerComponent::setMinimumLevel(LoggerLevel level)
{
if(minimumLevel != level)
minimumLevel = level;
}
void LoggerComponent::setOutputStream(std::ostream *output)
{
if(outputStream != output)
outputStream = output;
}
LoggerLevel LoggerComponent::getMinimumLevel()
{
return minimumLevel;
}
std::ostream* LoggerComponent::getOutputStream()
{
return outputStream;
}
std::string LoggerComponent::getLevelString(LoggerLevel level)
{
switch (level) {
case LoggerLevel::INFO:
return "INFO";
case LoggerLevel::DEBUG:
return "DEBUG";
case LoggerLevel::WARNING:
return "WARNING";
case LoggerLevel::ERROR:
return "ERROR";
case LoggerLevel::CRITICAL:
return "CRITICAL";
}
return nullptr;
}
void LoggerComponent::output(LoggerLevel level, std::string outputMessage)
{
if(level >= minimumLevel)
{
time_t now = time(nullptr);
*outputStream << ctime(&now)
<< (getLevelString (level) + " >> " + outputMessage)
<< std::endl << std::endl;
}
}
output:
0x60fda8
0x60fdac
Tue Oct 01 12:29:14 2019
CRITICAL >> Hello World!
Tue Oct 01 12:29:14 2019
DEBUG >> This is the start of console output
0x6fd0cd00
0x60fdb0
You are storing a pointer to an object local to the constructor (c1) in components. It will be destroyed and the pointer invalid when you try to use it later.
Store the object itself (or a std::unique_ptr to it if you have a good reason not to store the object itself) in the map instead.
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;
}
}
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);
}