class Task
{
public:
class Except : public std::runtime_error
{
public:
class BadInit : public Except
{
//...
};
class OpFailed : public Except
{
//...
};
};
void Init() throw(BadInit);
void DoStuff() throw(BadInit, OpFailed);
void DeInit() throw(BadInit);
};
Nested classes deriving from base classes
Is there any way of twisting the language to allow a nested class to derive from the class it it nested in? Sounds hideous, but here's the example I'm thinking of:
The idea is that the heirarchy is directly visible in the identifier names.
The exception handling code would like to know that exceptions thrown by members of Task came from there (perhaps for logging purposes), it'd like to know whether the exception was the object failing to initialise (so it can log the problem, and step around it or terminate depending on whether we're debugging or not), but it'd be nice to express the heirarchy in the language itself. Task::Except is very clear what kind of Except it is. Task::Except::OpFailed also makes sense. Task::OpFailed, though, is ambiguous.
Anyway, the obvious reson why this isn't working is that Task::Except is incomplete where OpFailed and BadInit try to derive from it, so it generates a compiler error. Is there any way to circumvent this (perhaps with forward declarations of classes)?
i'd say that is definate abuse of inheritence, you shouldn't use inheritence so that the idenfier names look nicer, you should use other things intended for such (eg. namespaces)
// GameDev.net CodeBox Formatter By Danushka "Silvermace"
// http://www.unsoundminds.com/codeformat/
namespace task {
enum { // bitmasks
EXCEPTION_OPFAILED = 1,
EXCEPTION_BADINIT = 2,
EXCEPTION_NULLPOINTER = 4,
};
class exception
{
int type
public:
exception( int _type ) : type( _type )
{
}
std::string getHumanReadable() {
std::string msg = "";
if( type & EXCEPTION_OPFAILED )
msg += "Operation Failure, ";
if( type & EXCEPTION_BADINIT )
msg += "Bad Initialization, ";
if( type & EXCEPTION_NULLPOINTER )
msg += "Null Pointer";
return std::string("Exception: ") + msg;
}
}
};
try
{
//example
throw( task::exception( task::EXCEPTION_OPFAILED | task::EXCEPTION_NULLPOINTER ) );
}
catch ( task::exception e )
{
std::cout << e.getHumanReadable() << std::endl;
}
// GameDev.net CodeBox Formatter By Danushka "Silvermace"
// http://www.unsoundminds.com/codeformat/
namespace task {
enum { // bitmasks
EXCEPTION_OPFAILED = 1,
EXCEPTION_BADINIT = 2,
EXCEPTION_NULLPOINTER = 4,
};
class exception
{
int type
public:
exception( int _type ) : type( _type )
{
}
std::string getHumanReadable() {
std::string msg = "";
if( type & EXCEPTION_OPFAILED )
msg += "Operation Failure, ";
if( type & EXCEPTION_BADINIT )
msg += "Bad Initialization, ";
if( type & EXCEPTION_NULLPOINTER )
msg += "Null Pointer";
return std::string("Exception: ") + msg;
}
}
};
try
{
//example
throw( task::exception( task::EXCEPTION_OPFAILED | task::EXCEPTION_NULLPOINTER ) );
}
catch ( task::exception e )
{
std::cout << e.getHumanReadable() << std::endl;
}
1: I'm not using inheritance to make identifier names look nicer. I'm using identifier names to make inheritance look nicer!
[edit]never mind the second point, I didn't read your code right.[/edit]
[edit again]Well, that's one way of doing it (by the way, using namespaces rather than nested classes is totally irrelevant), but it's not ideal.
In fact, it's close to useless. The whole point is that the type of the exception is contained in the thrown object, so that the exception handling code can potentially correct the problem. Your solution would be a bit better if the type was public, though, because then the type would be available to the exception handling code. Anyway, I specifically want the exception handling to be polymorphic.
Look, I know that what I'm trying to do is considered bad style. I just want to know whether there's any way of doing it; I can come up with alternatives just fine.[/edit again]
[Edited by - SoulSkorpion on November 24, 2004 3:19:06 AM]
[edit]never mind the second point, I didn't read your code right.[/edit]
[edit again]Well, that's one way of doing it (by the way, using namespaces rather than nested classes is totally irrelevant), but it's not ideal.
In fact, it's close to useless. The whole point is that the type of the exception is contained in the thrown object, so that the exception handling code can potentially correct the problem. Your solution would be a bit better if the type was public, though, because then the type would be available to the exception handling code. Anyway, I specifically want the exception handling to be polymorphic.
Look, I know that what I'm trying to do is considered bad style. I just want to know whether there's any way of doing it; I can come up with alternatives just fine.[/edit again]
[Edited by - SoulSkorpion on November 24, 2004 3:19:06 AM]
class Except : public std::runtime_error{public: class BadInit; class OpFailed; // ...};class Except::BadInit : public Except{ // ...};class Except::OpFailed : public Except{ // ...};
Quote:Original post by SoulSkorpioni can see how that would be benificial, but it would hardly be practical seeing you would have to derive the corrisponding exceptions for each class that throws an exception, if you have alot of spare dilly-dally time it might be viable :)
1: I'm not using inheritance to make identifier names look nicer. I'm using identifier names to make inheritance look nicer!
[edit]never mind the second point, I didn't read your code right.[/edit]
[edit again]Well, that's one way of doing it (by the way, using namespaces rather than nested classes is totally irrelevant), but it's not ideal.
In fact, it's close to useless. The whole point is that the type of the exception is contained in the thrown object, so that the exception handling code can potentially correct the problem. Your solution would be a bit better if the type was public, though, because then the type would be available to the exception handling code. Anyway, I specifically want the exception handling to be polymorphic.
Look, I know that what I'm trying to do is considered bad style. I just want to know whether there's any way of doing it; I can come up with alternatives just fine.[/edit again]
[Edited by - silvermace on November 24, 2004 7:34:15 AM]
Thanks, whoever-you-are, that works great :)
....
Yeah, that occured to me a few hours ago. Kind of "parallel inheritance", 'cause the classes derived from Task that want their own exceptions will have to have their exceptions derive from task as well...
....
Quote:i can see how that would be benificial, but it would hardly be practical seeing you would have to derive the corrisponding exceptions for each class that throws an exception, if you have alot of spare dilly-dally time it might be viable :)
Yeah, that occured to me a few hours ago. Kind of "parallel inheritance", 'cause the classes derived from Task that want their own exceptions will have to have their exceptions derive from task as well...
I think that's a bit silly.
My assertion is thus a class should only contain those names that are needed to use that class. You don't need to know about BadInit to use your Except class.
class Task{public: namespace Exception { class Base: public std::runtime_error {} class BadInit: public std::runtime_error {} class OpFailed: public std::runtime_error {} }; void Init() throw(BadInit); void DoStuff() throw(BadInit, OpFailed); void DeInit() throw(BadInit);};
My assertion is thus a class should only contain those names that are needed to use that class. You don't need to know about BadInit to use your Except class.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement