tags:

views:

114

answers:

5

Hi, I'm having some toubt here. Hope you guys can share out some programming tips. Just curious to know whether is it a good programming practice if I do something like the code below.

class Outer {
public:
   class Inner {
   public:
      Inner() {}
   }

   Outer() {}
};

I have been doing this for structure where I only want my structure to be expose to my class instead of global. But the case is different here, I am using a class now? Have you guys facing such a situation before? Very much appreciated on any advice from you ;)

A: 

It's not an everyday thing, but it's not unheard of, either. You would do this if there were a class (Inner) that only makes sense to a client program when the client is using Outer.

jwismar
A: 

If you only want a class to be exposed in a certain file, you can use an unnamed namespace within that file. Then whatever code is within that namespace is only available within that file.

namespace
{
    //stuff
}
Ólafur Waage
+2  A: 

I'll break the answer into two parts:

  1. for cases where you only organize code, you should use namespaces instead of classes -- if the inner class isn't an entity that is only worked with from inside the class (especially only constructed in the class), then inner classes are a good idea -- another example STL function objects.
  2. in C++ there is absolutely NO DIFFERENCE between structures and classes except that structures have public members by default. Hence there's no real difference when you have classes -- it's more a matter of style.
Kornel Kisielewicz
+2  A: 

This is a good practice in many cases. Here's one where we implement a link list:

template <class T>
class MyLinkList {
  public:
class Node {
    public:
    Node* next;
    T data;
    Node(const T& data, Node* node) : next(node), data(data) {}
};

class Iterator {
    public:
    Node* current;
    Iterator(Node* node) : current(node) {}
    T& operator*() { return current->data; }
    void operator++(int) { current = current->next; }
    bool operator!=(int) { return current != NULL; }
};

  private:  
Node* head;

}

The above is just snippet that is not intended to be complete or compilable. The point is to show that Node and Iterator are inner classes to the MyLinkList class. The reason why this makes sense is to convey the fact that Node and Iterator are not independent to be stand alone by themselves, but they need to be qualified by MyLinkList (for instance MyLinkList::Iterator it)

Khnle
Can you tell me one reason why the Node is public, exposing the implementation?
Kornel Kisielewicz
If I remember correctly, if Node and Iterator are private, the compiler might cause an error if it sees something like **MyLinkList<int>::Node node** or **MyLinkList<int>::Iterator it**. I hope to convey the point that Node and Iterator should only make sense in the context of MyLinkList and not by themselves, which I think is the essence of the question.
Khnle
+2  A: 

This is purely a matter of style, however I think it is typically more common in the C++ community to use a namespace named detail for classes that are purely helpers or are purely used in the implementation of other classes. There are several advantages to using namespaces in place of inner classes, among them include: greater compatibility (how compilers resolve names in inner classes can be incredibly different between Visual C++ and GCC, for example), more encapsulation (in the inner/outer variant, the inner class has greater access to members of instances of the outer class), easier implementation (you don't have to fully qualify the helper class every single time in the implementation file, since you can put a using directive in the ".cpp" source file). If you are going to use an inner class, then you need to make the conscious decision to make that a part of your API.

Using Namespaces

namespace collection
{
     namespace detail 
     {
         class LinkedListNode
         {
             //...
         };
     }

     class LinkedList
     {
          // ...
     };
 }

Using Inner Classes

namespace collection
{
      class LinkedList
      {
           // ...
           class LinkedListNode
           {
               // ...
           };
           // ...
       };
 }
Michael Aaron Safyan
Thanks for the example, but I'm a bit confusing. Lets assume that I'm instantiating LinkedList object, and I only want LinkedList object to have contact with LinkedListNode. No others (either programmer or sub-object that drive from LinkedList object). I been thinking to separate the LinedListNode into other files (.cpp or .h), but just worry other programmers will trying to instantiate it without my permission. Would namespace going to help out this matter? Thank in advance ;)
huahsin68
@huahsin68, if you are using templates, then there is very little you can do to make it completely private, as the declaration will need to be visible. However, if you aren't, then you could use void* instead of LinkedListNode* in your declaration of LinkedList (your implementation will have to cast) and you could place LinkedListNode in an anonymous namespace in your ".cpp" implementation file. That said, it is well understood in the C++ community that namespace "detail" contains implementation details that are subject to change and that...
Michael Aaron Safyan
... using elements of namespace "detail", like using undocumented features, carries with it no guarantees and one uses such items at one's own peril.
Michael Aaron Safyan