I've problem with exceptions:
#include <iostream>
#include <cstring>
#include <exception>
class except :public std::exception
{
char* err;
public:
except(const char* s) noexcept
{
err = new char[strlen(s) + 1];
strcpy(err, s);
err[strlen(s)] = 0; //is it necessary??
}
virtual const char* what() noexcept
{return err;}
virtual ~except() noexcept
{delete err;}
};
double div(const double& a, const double& b) noexcept
{
if (b == 0.0)
throw except("DIVIDED BY 0");
return a / b;
}
int main()
{
try
{
std::cout << div(5.0, 0.0);
}
catch (std::exception &ex)
{
std::cout << ex.what();
}
return 0;
}
I want to print "DIVIDED BY 0" but I get:
terminate called after throwing an instance of 'except'
what(): std::exception
Aborted
Process returned 134 (0x86)
Shall I put noexcept
in every function/member function that doesn't throw any exceptions?
Is err[strlen(s)] = 0
necessary? (in except::except(const char* s))
I want to print "DIVIDED BY 0" but I get: terminate called after throwing an instance of 'except'
double div(const double& a, const double& b) noexcept
You are claiming that you won't throw an exception, but you are lying. The result is the call to std::terminate when you actually throw.
The problem is a actually twofold. Firstly, as @manni66 suggests, div
should not be declared noexcept
and this does cause a run-time error, but removing it does not solve the issue.
The second problem is that what
has been declared:
virtual const char* what() noexcept;
whereas it's declared in std::exception
as:
virtual const char* what() const noexcept;
and this difference in signature means that when it's caught by the handler for std::exception
, it calls std::exception::what()
and not except::what()
A couple of points worth mentioning:
std::string
class if you can. It will make things easier and safer. Although in this case, as point two eludes to, a string member is not really necessary as the class is specific enough not to need further qualification.std::runtime_error
or in this case std::overflow_error
would be decent choices and both take a std::string
as an argument to the constructor, so no need to create your own exception class.For example:
#include <exception>
using namespace std;
class divide_by_zero : public std::exception
{
public:
virtual const char* what() const noexcept { return "DIVIDED BY 0"; }
};
double div(const double& a, const double& b)
{
if (b == 0.0)
throw divide_by_zero();
return a / b;
}
int main()
{
try
{
std::cout << div(5.0, 0.0);
}
catch (divide_by_zero &ex)
{
std::cout << ex.what();
}
catch (std::exception &ex)
{
std::cout << ex.what();
}
return 0;
}
Output:
DIVIDED BY 0
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.