Nested classes deriving from base classes

Started by
5 comments, last by Mayrel 19 years, 5 months ago
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:

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);
};


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)?
-------------"On two occasions, I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able to rightly apprehend the kind of confusion of ideas that could provoke such a question."- Charles Babbage (1791-1871)
Advertisement
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;
}
"I am a donut! Ask not how many tris/batch, but rather how many batches/frame!" -- Matthias Wloka & Richard Huddy, (GDC, DirectX 9 Performance)

http://www.silvermace.com/ -- My personal website
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]
-------------"On two occasions, I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able to rightly apprehend the kind of confusion of ideas that could provoke such a question."- Charles Babbage (1791-1871)
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 SoulSkorpion
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]
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 :)

[Edited by - silvermace on November 24, 2004 7:34:15 AM]
"I am a donut! Ask not how many tris/batch, but rather how many batches/frame!" -- Matthias Wloka & Richard Huddy, (GDC, DirectX 9 Performance)

http://www.silvermace.com/ -- My personal website
Thanks, whoever-you-are, that works great :)

....

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...
-------------"On two occasions, I have been asked [by members of Parliament], 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able to rightly apprehend the kind of confusion of ideas that could provoke such a question."- Charles Babbage (1791-1871)
I think that's a bit silly.

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.
CoV

This topic is closed to new replies.

Advertisement