Downside of nested classes.

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Downside of nested classes.

Post by albinopapa » December 8th, 2017, 8:36 pm

Nested classes are nice, they get to have unrestricted access to parent members and keeps code separate and together at the same time.

Take chili's Event classes in the Keyboard and Mouse classes. He can reuse the name Event because each is in the scope of the their respective parent classes making Event more like Keyboard::Event and Mouse::Event. This keeps from having to name those classes KeyboardEvent and MouseEvent. This make sense after all, mouse events should come from the Mouse class and same for the Keyboard. So this is how things keep together. It keeps things separate inside the Keyboard class, delegating the responsibility of events to the Event class for each parent. This means you can create a Keyboard/Mouse::Event and just pass that as a parameter instead of having to pass the whole parent class.

The downside to all of this is forward declarations don't work for the nested class. Now Mouse/Keyboard.h are small enough files and never change so I'm not really worried about build times with them. I do like not having to #include files in my headers though. I can reduce the chances of circular dependencies this way. Also, I decrease the number of #include chains, which means I only have to #include those headers that are needed in the .h file and different ones if needed in the .cpp file.

Aside from nested classes, there are other hindrances to putting all #include statements in cpp files. Take for instance std::vector or std::unique_ptr. In order for them to work, they need to know during compilation what and where the type is they are going to be working on. Other than that, storing concrete objects ( not pointers or references ) will also require you to #include their header files. This one is a nail biter for me lol. I COULD just store a raw pointer and handle all memory management manually, thus allowing me to keep most of my header includes in the cpp files, but I care more about runtime performance than build performance, so I'll keep my concrete objects on the stack thank you.

That's all, just a "little" rant about forward declarations and nested classes.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: Downside of nested classes.

Post by chili » December 10th, 2017, 7:53 am

Yeah, the inability to forward decl nested classes is a point against them for sure. As for vector and uptr, I thought you could do vector<class T*> and uptr<class T>. Maybe I'm just misremembering.

In any case, following SOLID principles and depending on abstractions rather than concretions will mitigate this issue greatly. Though of course it is not always possible to do so.
Chili

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Downside of nested classes.

Post by albinopapa » December 10th, 2017, 10:08 am

Didn't know about vector<T*>, uptr<T*>, but I guess it makes sense, if you can do it in your own classes

Code: Select all

class Bar;
class Foo{ Bar* pBar;};
Then it would make sense that it should work for those STL classes as well.

I just remember having issues a while back when trying to work on an interface style game framework, but I think I was trying to use a concrete object in my unique_ptr instead of one of the interface pointers. Also, when I mean forward declaring templates I mean

Code: Select all

// Header
namespace std
{
     template<class T>class vector;
}
class Foo
{
     std::vector<Bar> m_bar;
};
// Source
#include <vector>
I guess I wasn't thinking about two things, 1) vector<Bar> is a concrete object, probably should be std::vector<Bar>* m_pvBar; 2) Bar is a concrete object inside vector so should probably be std::vector<Bar*>* m_pvpBar;.

That's not really the problem as I understand it though. The fact is, vector has a second template argument, the allocator, so it'd be something like

Code: Select all

namespace std
{
     template<class T, class Aloc = Allocator> vector;
}
class Foo
{
     std::vector<Bar*>* m_pvpbar;
};
Since the forward declaration signature has to match the actual signature, this make forward declarations of the STL classes very cumbersome, though probably not impossible.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Downside of nested classes.

Post by albinopapa » December 10th, 2017, 10:13 am

chili wrote: In any case, following SOLID principles and depending on abstractions rather than concretions will mitigate this issue greatly. Though of course it is not always possible to do so.
The abstractions part I think I understand. In the example I gave about the Keyboard::Event example, I could create a class that handles/interprets those events and be able to forward declare that class in the header files and keep my header files free of #includes, is that what you are referring to? I for some reason never think about creating another level of abstraction to solve some of my issues with regards to architecture. I should probably keep that in mind.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply