DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 14 of 14

Thread: Nested Class Definitions

  1. #1
    Join Date
    Dec 2003
    Posts
    38

    Nested Class Definitions

    In most C++ textbooks class definitions are very simplistic, ie., normally you have private: followed by a few identifiers and then public: followed by a few member functions. Is it a good idea to use class or even define class definitions within another class definition with the possibility of having member functions defined within. Or is this bad practice?

    EVAC

  2. #2
    Join Date
    Jul 2005
    Posts
    26
    I do not know whether it is a good practice, but from what I can tell, I never actually used it.

    Sometimes when I needed a struct that is solely used in one class, I made it a member of that class. Most of the times, a littel later on, I decided that it would be better if the class members were automatically initialized, destroyed, need an member variable access function or whatever, so I made a class of it. Once done, I feel queasy with the nested syntax and moved the nested class out of the outer class definition.

    Another time I realized that I need the class to be returned by a member function of the outer class and feel bad about requiring my clients to create or handle a nested class.

    OTOH it is a very common practice in Java - although I mostly dislike the syntax.

    Well, maybe there are situations when nested classes are handy or stylish and someone can give an example.

  3. #3
    Join Date
    Nov 2003
    Posts
    4,118
    Actually, nested classes are quite useful in certain cases. The Pimpl idiom for example requires that each class define a nested Pimpl struct:
    http://www.devx.com/cplus/Article/28105


    Even if you don't use this idiom, a nested class can solve a few encapsulation issues rather neatly. The main criterion for using a nested class is: "am I sure that no other client/class should use this nested class?" If the answer is positive, then a nested class is probably a good design choice. Notice that if you have public member functions in the enclosing class that return the nested class or expose its existence in any other way, then nesting was probably a bad idea to begin with.
    Danny Kalev

  4. #4
    Join Date
    Jul 2005
    Posts
    26
    Quote Originally Posted by Danny
    Actually, nested classes are quite useful in certain cases. The Pimpl idiom for example requires that each class define a nested Pimpl struct
    You are right that is is convenient for the pimpl idiom to use a nested class, although it is not required. I'd personally consider this as an exception.

    Quote Originally Posted by Danny
    Even if you don't use this idiom, a nested class can solve a few encapsulation issues rather neatly.
    What do you particularly think about?

    Quote Originally Posted by Danny
    The main criterion for using a nested class is: "am I sure that no other client/class should use this nested class?" If the answer is positive, then a nested class is probably a good design choice.
    That is exactly my point: I sometimes thought it were a good design choice until new project requirements lead me to a point where it would be best to dispose the nested class to the clients. I could have saved up the required modifications if I just had not nested the class. Apart from a more beautiful looking design, I do not see a clue in nesting a classes.

  5. #5
    Join Date
    Dec 2003
    Posts
    38
    Hey thanks guys for the assistance. Much appreciated. Both responses were definitely on point. I especially like the "I feel queasy" sentiment. :p

    EVAC

  6. #6
    Join Date
    Nov 2003
    Posts
    4,118
    Quote Originally Posted by Oliver
    You are right that is is convenient for the pimpl idiom to use a nested class, although it is not required. I'd personally consider this as an exception.


    What do you particularly think about?
    In cases when a class needs a helper class that's reposnsible for some internal bookkeeping, and you want to hide that helper class from clients, a nested class can do the trick. Take for example a string class and a helper class that's reposinsible for determining its collating order. The collating order class isn't meant to be used by other classes or algorithms, or it might be changed frequently according to customers' demands, so you can implement it as a nested class. Another example: a function object implemented inside a class.
    If you're looking for a real world example, here's one:
    http://www.dinkumware.com/htm_cpl/ve...ctor%3Cbool%3E
    The type vector<bool>::reference is actually a nested class. It makes much sense to use a nested class in this case because other STL containers define reference as a fundamental datatype (i.e., plain references).
    Last edited by Danny; 07-29-2005 at 09:11 PM.
    Danny Kalev

  7. #7
    Join Date
    Jul 2005
    Posts
    26
    Yes, Danny, you're absolutely right about helper classes as pointed out in your example. Moreover, what I didn't consider in my previous posts, I sometimes use nested function object classes.

    Maybe I was way too occupied by my design mistakes (when I needed to "unnest" a class later), so I did not consider this usage.

    Well, what we maybe might drew out of this discussion is, that nested class designs should be handled with care and foresight but can be really useful to encapsulate class usage and prevent namespace pollution.

    Would you agree with that?

  8. #8
    Join Date
    Nov 2003
    Posts
    4,118
    Quote Originally Posted by Oliver
    Yes, Danny, you're absolutely right about helper classes as pointed out in your example. Moreover, what I didn't consider in my previous posts, I sometimes use nested function object classes.

    Maybe I was way too occupied by my design mistakes (when I needed to "unnest" a class later), so I did not consider this usage.

    Well, what we maybe might drew out of this discussion is, that nested class designs should be handled with care and foresight but can be really useful to encapsulate class usage and prevent namespace pollution.

    Would you agree with that?
    I agree with that but it's a very general statement;) after all, you can (rigtfully!) say exactly the same thing about any C++ feature: exceptions, RTTI, namespaces, template template arguments, overloading and so on and so forth. I think nested classes are one of many tools in a programmer's arsenal. When you consider other alternatives and find that nested classes offer the best design -- you know it's the right choice. To repeat what I said previously, if you have any public member function that exposes the nested class, say

    Code:
    enclosing::nested  myfunc();
    It's a sign that this was a design mistake (probably).
    Danny Kalev

  9. #9
    Join Date
    Jul 2005
    Posts
    26
    Quote Originally Posted by Danny
    I agree with that but it's a very general statement;) after all, you can (rigtfully!) say exactly the same thing about any C++ feature: exceptions, RTTI, namespaces, template template arguments, overloading and so on and so forth.
    Yes, the first part was general, but the last part of this sentence was more specific:
    Quote Originally Posted by Oliver
    useful to encapsulate class usage and prevent namespace pollution
    You cannot tell this about exceptions, RTTI, (namespaces), overloading etc. Can you?

    Ok, let's turn the tables: What are the pros and cons of nested classes in your opinion (not the possible applications).

  10. #10
    Join Date
    Nov 2003
    Posts
    4,118
    The pros: simplifying design, higher level of encapuslation, resilience to changes (clients don't know that their class has a hidden nested class that has changed) and in some cases, efficiency although this is the least significant factor here.

    cons: complicating design (it's anot a contradiction -- when a nestec class isn't an optimal choice, and there are simpler solution, it could lead to code clutter), readability -- readers don't always know if the code they're viewing is part of the enclosing class or the nested class.

    BTW, namespace pollution is not an issue at all. I'll put it more bluntly: if namespace pollution is your aim, then there are much better ways to accomplish this than messing with nested class. It used to be the case in the pre-namespace era biut today, why not use use namespaces in the first place instead of nested classes?
    Danny Kalev

  11. #11
    Join Date
    Jul 2005
    Posts
    26
    Quote Originally Posted by Danny
    The pros: simplifying design, higher level of encapuslation, resilience to changes (clients don't know that their class has a hidden nested class that has changed) and in some cases, efficiency although this is the least significant factor here.
    Why should the design be more simple if a nested class is used? Try layouting nested classes in UML - this doesn't look simpler.

    Higher level of encapsulation is not always a pro, and I cannot see the point where or who should benefit just from nesting a class. I'd consider it much more important that the classes are defined/declared in the same file(s) to keep the versions compatible. You cannot reach this just by nesting a class.
    Same goes for resilience to changes. Why should a nested class be more resilient than an "unnested" one?

    Efficiency? Ehm, how should this come?

    Quote Originally Posted by Danny
    cons: [...] readability -- readers don't always know if the code they're viewing is part of the enclosing class or the nested class.
    If they are not defined in the header file, they are fully qualified, aren't they?

    Another important point: Bad reusability of the nested class.

    Quote Originally Posted by Danny
    BTW, namespace pollution is not an issue at all. I'll put it more bluntly: if namespace pollution is your aim, then there are much better ways to accomplish this than messing with nested class. It used to be the case in the pre-namespace era biut today, why not use use namespaces in the first place instead of nested classes?
    Pardon? This would be the main reason for me to nest a class. Sure, you can create a namespace for every class that requires a small helper class, but this would be the ultimate reason for me to nest the class: To avoid polluting the global namespace, use a simple name for the helper class and do not wrap each and every small class (/hierarchy) in a separate namespace.

  12. #12
    Join Date
    Nov 2003
    Posts
    4,118
    Quote Originally Posted by Oliver
    Why should the design be more simple if a nested class is used? Try layouting nested classes in UML - this doesn't look simpler.

    Higher level of encapsulation is not always a pro, and I cannot see the point where or who should benefit just from nesting a class. I'd consider it much more important that the classes are defined/declared in the same file(s) to keep the versions compatible. You cannot reach this just by nesting a class.
    Same goes for resilience to changes. Why should a nested class be more resilient than an "unnested" one?
    --> I think this thread is on the verge of reiterating the same views over and over again, so I'll be brief here.
    As for resilience: look at the Pimpl idiom. Clients don't even know that their class's implementation details has changed and dont need to compile it. You can't achive that if the nested class is moved outside.
    If UML has a problem representing nested classes properly, then that's UML's problem, not a C++ problem nor a design problem. UML used to have difficulties with virtual inheritance, so does that mean it should be avoided?
    Quote Originally Posted by Oliver
    Efficiency? Ehm, how should this come?
    As I said, it' a minor issue but in most cases, the alternative would be to use a pointer to the helper class, allocate it dynamically, destroy it later and all that jazz, or perhaps using callbacks and virtual functions. In some cases, a small and wel-focused nested class is the ideal solution with minimum overhead.

    Quote Originally Posted by Oliver
    If they are not defined in the header file, they are fully qualified, aren't they?
    ==>Once you're inside the body of a function or block, they're not always fully qualified and it's possible to lose track of which function belongs to which class. It all depends on how coherent the code is. Another problem occurs with nested template classes. Some compilers have a very hard time dealing with them, and the syntax gets awry, too.

    Quote Originally Posted by Oliver
    Another important point: Bad reusability of the nested class.
    ==>That's not an issue. As I've said before, you nest a class when you *know* that it's not meant to be resued in any other way; the sole prupose of such a class is to serve the enclosing class, so by using nesting you deliberately avoid any potential "reuse" that is certainly undesirable. Look at the Pimpl idiom again and see how unreusable the nested class is, as an example. I think you're stretching the point of reusability too much. Not every class is meant to be reused, and nested classes are an efficient technique for marking such classes. This is similar to having non virtual destructors as a means of marking classes that aren't meant to be derived from.


    Quote Originally Posted by Oliver
    Pardon? This would be the main reason for me to nest a class. Sure, you can create a namespace for every class that requires a small helper class, but this would be the ultimate reason for me to nest the class: To avoid polluting the global namespace, use a simple name for the helper class and do not wrap each and every small class (/hierarchy) in a separate namespace.
    That's a bad idea. Namespaces aren't meant to be used in this way -- you don't define a separate namespace for every class! you define it for a project, a set of related classes, a library etc. Nesting as a namespace pollution prevention mechanism isn't a good idea, period. You nest classes when it's the right design choice; you declare classes in namespaces and (nested namespaces) to avoid name clashes.


    Anyway, I believe that we both have beaten this subject to death so unless other people have new comments and questions, I think it's time to adjourn this session...
    Last edited by Danny; 08-01-2005 at 10:43 PM.
    Danny Kalev

  13. #13
    Join Date
    Jul 2005
    Posts
    26
    Quote Originally Posted by Danny
    look at the Pimpl idiom. Clients don't even know that their class's implementation details has changed and dont need to compile it. You can't achive that if the nested class is moved outside.
    Huh? AFAIK this is not a metter of whether a class is nested. See for example one of the first google results: http://www.gamedev.net/reference/art...rticle1794.asp

    Quote Originally Posted by Danny
    If UML has a problem representing nested classes properly, then that's UML's problem, not a C++ problem nor a design problem. UML used to have difficulties with virtual inheritance, so does that mean it should be avoided?
    No, but this IMHO is an indication that the design is not more simple to grasp with standard state-of-the-art design layout tools.

    Quote Originally Posted by Danny
    As I said, it' a minor issue but in most cases, the alternative would be to use a pointer to the helper class, allocate it dynamically, destroy it later and all that jazz, or perhaps using callbacks and virtual functions. In some cases, a small and wel-focused nested class is the ideal solution with minimum overhead.
    Sorry, but I really do not see why a nested class should execute faster than an unnested class. I also do not see how nesting a class corresponds to the memory allocation model or what it has to do with callbacks and virtual functions (although we will often use e.g. nested function object classes as kind-of callbacks). Would you please point out how exactly nesting a class improves performance, how minor it ever is?

    Quote Originally Posted by Danny
    ==>Once you're inside the body of a function or block, they're not always fully qualified and it's possible to lose track of which function belongs to which class. It all depends on how coherent the code is.
    As I wrote before, I think this only applies to inlined declarations. Non-inlined declarations are always fully qualified, aren't they?
    Code:
    class A
    {
      void foo() { ... };
      class B
      {
        // Not qualified because declared in class header.
        void foo() { ... };
        void bar();
      };
    };
    
    // Fully qualified declaration.
    // Or is there a way to avoid full qualification?
    void A::B::bar()
    { ... }
    Quote Originally Posted by Danny
    ==>That's not an issue. As I've said before, you nest a class when you *know* that it's not meant to be resued in any other way; the sole prupose of such a class is to serve the enclosing class, so by using nesting you deliberately avoid any potential "reuse" that is certainly undesirable.
    Definite knowledge would be good.

    Quote Originally Posted by Danny
    Look at the Pimpl idiom again and see how unreusable the nested class is, as an example.
    The pimple idiom also has some drawbacks. If the internally used class is designed just like the pimpl wrapper, there is no point in not letting the user of the class decide whether he wants to use the pimpl wrapper or the impl itself.

    Quote Originally Posted by Danny
    This is similar to having non virtual destructors as a means of marking classes that aren't meant to be derived from.
    We can surely derive from classes with nonvirtual destructors (Herb Sutter wrote an article about that in his GotW, I just can't find it now). We just must not do so if we are to destroy the objects virtually. Sutters words.

    Quote Originally Posted by Danny
    That's a bad idea. Namespaces aren't meant to be used in this way -- you don't define a separate namespace for every class!
    That was what I said: "I don't want to wrap every single class in a namespace just because it uses a simple helper class". So finally, nesting a class helps me preventing namespace pollution - even within my namespace (I did not write "global namespace"); the alternative would be to use nested namespaces, and - as you agree - that's not the best thing one can do. So nesting classes finally helps preventing namespace pollution.

    Quote Originally Posted by Danny
    Anyway, I believe that we both have beaten this subject to death so unless other people have new comments and questions, I think it's time to adjourn this session...
    Again just leave out the unanswered issues open? Quit the discussion? Ok, then we just have to quit. But IMHO if a poster decides to quit a discussion, he should leave the last word to the other discussion partners, not just write his opinion and end with "end of discussion".

  14. #14
    Join Date
    Nov 2003
    Posts
    4,118
    Quote Originally Posted by Oliver
    Again just leave out the unanswered issues open? Quit the discussion? Ok, then we just have to quit. But IMHO if a poster decides to quit a discussion, he should leave the last word to the other discussion partners, not just write his opinion and end with "end of discussion".
    Yes, quit the discussion unless you have something really new to add. What you wrote in your last post is a rerun of previous (and not entirely accurate) ideas that you'd expressed here before. So unless someone else has a question about this topic or a new insight, I think it's best to quit here.

    And one final tip for you: a bit of humility. Admit that there are things you don't know or which you didn't think about. Telling me why Pimpl isn't always the best solution is exactly the line of defensive trolls you excel at. We didn's discuss the merits of this pattern; we used it as an example of nested class usage, so there's no point in trying to divert the subject or manipulate the discussion just to let you save face, OK?
    PS: my warning from the other thread applies to this one as well. If you have any personal matters to settle with me, do it privately. This forum isn't the right place for it.
    Danny Kalev

Similar Threads

  1. Replies: 2
    Last Post: 05-24-2005, 06:56 AM
  2. Help with class/applet
    By none_none in forum Java
    Replies: 17
    Last Post: 04-28-2005, 03:00 PM
  3. Replies: 5
    Last Post: 10-17-2002, 01:58 PM
  4. Replies: 1
    Last Post: 10-20-2001, 05:27 PM
  5. Replies: 333
    Last Post: 06-19-2001, 09:25 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center