when should I use nested class in c++ and why?

Started by
14 comments, last by daniel battaglia 16 years, 5 months ago
Hi, as the title suggested, in which situation should I choose the nested class/struct(as well as enum, typedef, etc) rather than place the defininition outside a certain class. Since there is few difference between the two from the syntax point of view, I believe the choice hugely depends on personal convention and experience. So from the "design" point of view, what is your choice? Thanks in advance ;)
Advertisement
I usually use nested definitions if the thing your defining is logically a part of the outer class. ie if it does not make sense to use it without the outer class. Of course that itself is a subjective decision :)
Typically I use nested classes for 'hiding' classes that the parent can dispatch. SC++L uses this approach for iterators, where the iterator is dispatched from the parent container class to be specialized for the instance of the container. In my own experience its not terribly useful, however I've used a nested class to hide the API for a small 3D framework, which suits the pattern pretty well.
Quote:Original post by Simian Man
I usually use nested definitions if the thing your defining is logically a part of the outer class. ie if it does not make sense to use it without the outer class. Of course that itself is a subjective decision :)

Yeah, in practice, sometimes it's too subtle to tell whether or not it is "logically a part of the outer class". Just follow your inituition and experience.

Quote:Original post by BlodBath
Typically I use nested classes for 'hiding' classes that the parent can dispatch. SC++L uses this approach for iterators,


But in STL we can directly use iterator from outside, so what are it "hiding" for? To be more specific, what's the difference if iterator is defined outside the container in STL?


Quote:Original post by jhq
Since there is few difference between the two from the syntax point of view

There is one gigantic difference: inner classes can access private class members. That means that an inner class can communicate with its outer class without having to go through the outer class' public interface. Because of this, making a class an inner class should be thought of as increasing the size of the class (a bad thing) while complicating its responsibilities (also a bad thing). Because of this, a class should be an inner class ONLY where it cannot reasonably be implemented using the outer class' public interface.

Some people like to make things inner classes just because they relate to the outer class or are "part of" the outer class. This is NOT a good idea. Making something an inner class is not a good way of providing namespacing, because of the extra privileges and responsibilities that doing so confers on the class.

Inner classes are also the correct way to implement the Observer pattern. Because of the amount of code required to do this without lexical scoping, however, it's rare to actually see this.
Quote:Original post by Sneftel
Some people like to make things inner classes just because they relate to the outer class or are "part of" the outer class. This is NOT a good idea. Making something an inner class is not a good way of providing namespacing, because of the extra privileges and responsibilities that doing so confers on the class.


std::vector<int> nums;
std::vector<int>::iterator = nums.begin();

It seems that the designers of the Standard Template Library completely disagree with you!

I personally think it is a good way to provide namespacing, and moreover, it allows you to keep an internally used class completely private...which you couldn't do otherwise.
It seems you've miss understood the definition you posted, opening up the "vector" header from VC++8 show this;

typedef _Vector_iterator<_Ty, _Alloc> iterator;


in the vector class.

The type, _Vector_iterator, is defined earlier in the header file and is NOT an inner class of Vector.
Quote:Original post by yahastu
Quote:Original post by Sneftel
Some people like to make things inner classes just because they relate to the outer class or are "part of" the outer class. This is NOT a good idea. Making something an inner class is not a good way of providing namespacing, because of the extra privileges and responsibilities that doing so confers on the class.


std::vector<int> nums;
std::vector<int>::iterator = nums.begin();

It seems that the designers of the Standard Template Library completely disagree with you!

I personally think it is a good way to provide namespacing, and moreover, it allows you to keep an internally used class completely private...which you couldn't do otherwise.


Consider std::list::iterator. Or std::map::iterator. How would one implement it without exposing too much in the public interface? std::vector has one of the few iterators that can be implemented using its public interface.
(embarrassed) oops!
OK, now I have deeper understanding about nested class. But what about those nested enum and typedef? Is there anything special I need to pay attention to? Or it just all depends on your convention?

This topic is closed to new replies.

Advertisement