Here is a simple note for c++ exception usage.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
class CBad : public std::exception
{
public:
const char* what() const throw () { //`const throw()` means it <B>won't</B> throw any exception.
return "CBad";
}
};
class BBad : public std::exception
{
public:
const char* what() const throw () {
return "BBad";
}
};
class C{
public:
C(int x) throw(CBad){
printf("C(%d)...\n", x);
if (x < 0) {
//error
throw CBad();
}
}
~C(){
printf("~C()...\n");
}
};
class B{
public:
B(int x) throw(BBad){
printf("B(%d)...\n", x);
if (x < 0) {
throw BBad();
}
}
~B(){
printf("~B()...\n");
}
};
class A{
public:
A(int b, int c)
try: b_(new B(b)),
c_(new C(c))
{
printf("A()...\n");
}
catch (BBad & e) {
std::cout << "b fucked" << std::endl;
//Q: will "new C(c)" run ? A: won't. so here we don't need to do other things.
throw;
}
catch (CBad & e) { //if no exception introduced, the resources held by B is not going to be released.
std::cout << "c fucked, but b is ok. so we have to release b's resources." << std::endl;
delete b_;
throw;
}
catch (...) {
throw;
}
~A() {
printf("~A()...\n");
delete b_;
delete c_;
}
private:
B *b_;
C *c_;
};
void custom_termination()
{
abort();
}
int main()
{
try {
A(1, -2);
} catch (...) {
printf("other exception\n");
//if A's construtor generate any exception, we can:
// 1. throw it to higher level ( here the exception will go calling `std::terminate()`. )
// throw;
// 2. continue do other things if this error can be tolarated.
// do nothing;
// 3. custom termination functions.
// ourterminate();
custom_termination();
}
return 0;
}
a further example:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
class XBad : public std::exception
{
public:
explicit XBad(const char *msg) throw()
: msg_(msg) {
}
virtual const char* what() const throw () {
return msg_;
}
protected:
const char* msg_;
};
class CBad : public XBad
{
public:
explicit CBad(const char *msg) throw()
: XBad(msg) {
}
explicit CBad(int ec) throw()
: XBad(strerror(ec))
{
}
};
class BBad : public XBad
{
public:
explicit BBad(const char *msg) throw()
: XBad(msg) {
}
};
class C{
public:
C(int x) throw(CBad){
printf("C(%d)...\n", x);
if (x < 0) {
//error
throw CBad(x);
}
}
~C(){
printf("~C()...\n");
}
};
class B{
public:
B(int x) throw(BBad){
printf("B(%d)...\n", x);
if (x < 0) {
throw BBad(".... is not permit.");
}
}
~B(){
printf("~B()...\n");
}
};
class A{
public:
A(int b, int c)
try: b_(new B(b)),
c_(new C(c))
{
printf("A()...\n");
}
catch (const BBad & e) {
std::cout << "b fucked" << std::endl;
//Q: will "new C(c)" run ? A: won't. so here we don't need to do other things.
throw e;
}
catch (const CBad & e) { //if no exception introduced, the resources held by B is not going to be released.
std::cout << "c fucked, but b is ok. so we have to release b's resources." << std::endl;
delete b_;
throw e;
}
catch (...) {
throw XBad("other exception");
}
~A() {
printf("~A()...\n");
delete b_;
delete c_;
}
private:
B *b_;
C *c_;
};
void custom_termination()
{
abort();
}
int main()
{
try {
A(1, -2);
} catch ( const XBad & x ){
printf("Error: %s\n", x.what());
abort();
//if A's construtor generate any exception, we can:
// 1. throw it to higher level ( here the exception will go calling `std::terminate()`. )
// throw;
// 2. continue do other things if this error can be tolarated.
// do nothing;
// 3. custom termination functions.
// ourterminate();
} catch (...) {
printf("other exception\n");
custom_termination();
}
return 0;
}