> Throwing an exception involves copying it. In the statement "throw t"
the static type of t is used to determine the exception that is
thrown. t is copied into a "temporary" exception object of type
static-type-of-t, and this copy will be a slice if the static type of
t doesn't match its dynamic type.
How do you think about the effects by the following design sketch?
#include <iostream.h>
#include <errno.h>
struct errno_exception
{
virtual ~errno_exception() {}
virtual int get_code() const { return EZERO; }
};
struct invalid : public errno_exception
{
};
struct invalid_value : public invalid
{
virtual int get_code() const { return EINVAL; }
};
struct invalid_environment : public invalid
{
virtual int get_code() const { return EINVENV; }
};
struct invalid_format : public invalid
{
virtual int get_code() const { return EINVFMT; }
};
struct no_entry : public errno_exception
{
virtual int get_code() const { return ENOENT; }
};
struct exception_factory
{
virtual ~exception_factory() {}
virtual errno_exception& create (int err_no) const = 0;
};
struct factory1 : public exception_factory
{
virtual errno_exception& create (int err_no) const;
};
struct errno_exceptions
{
errno_exception _ZERO;
no_entry _NOENT;
invalid_format _INVFMT;
invalid_environment _INVENV;
invalid_value _INVAL;
};
errno_exceptions my_e_e;
errno_exception& factory1::create (int err_no) const
{
switch (err_no)
{
case ENOENT:
return my_e_e._NOENT;
case EINVFMT:
return my_e_e._INVFMT;
case EINVENV:
return my_e_e._INVENV;
case EINVAL:
return my_e_e._INVAL;
default:
return my_e_e._ZERO;
}
}
struct exception_thrower
{
virtual ~exception_thrower() {}
virtual void create (int code) const = 0;
};
struct factory2 : public exception_thrower
{
virtual void create (int code) const;
};
void factory2::create (int code) const
{
switch (code)
{
case ENOENT:
throw no_entry();
case EINVFMT:
throw invalid_format();
case EINVENV:
throw invalid_environment();
case EINVAL:
throw invalid_value();
default:
throw errno_exception();
}
}
int main ()
{
factory1 f1;
try
{
throw f1.create(EINVFMT);
}
catch (invalid const& i)
{
cout << "1. invalid = " << i.get_code() << endl;
}
catch (errno_exception const& e)
{
cout << "1. errno exception base" << endl;
}
try
{
factory2 f2;
f2.create(EINVFMT);
}
catch (invalid const& i)
{
cout << "2. invalid = " << i.get_code() << endl;
}
catch (errno_exception const& e)
{
cout << "2. errno exception base" << endl;
}
return 0;
}