Disadventages of Nested Classes and Anonymous Namespaces

Uwaga! Informacje na tej stronie mają ponad 5 lat. Nadal je udostępniam, ale prawdopodobnie nie odzwierciedlają one mojej aktualnej wiedzy ani przekonań.

# Disadventages of Nested Classes and Anonymous Namespaces

Fri
28
Aug 2009

Some of techniques I have been using to arrange my C++ code were anonymous namespaces and nested classes. I liked them till I've discovered their big disadventage - they are not compatible with forward declarations. Here is an example. Let's say we have two classes - Problematic and Second - and we want to place them in separate HPP+CPP files, while Second will use Problematic. The obvious solution is to define them like this:

////// Problematic.hpp

class Problematic
{
};

////// Second.hpp

#include "Problematic.hpp"

class Second
{
  Problematic *obj;
  void CreateObj();
};

We all know that the fewer inclues the better (especially we should avoid including headers in other headers), so it's good to only declare Problematic class in Second header and include its definition in CPP file. We can do it as Problematic class is used in the Second header only by pointer (references are also OK) and not by value.

////// Second.hpp

class Problematic;

class Second
{
  Problematic *obj; // Here class declaration is enough
  void CreateObj();
};

////// Second.cpp

#include "Second.hpp"
#include "Problematic.hpp" // Included here, not in HPP

void Second::CreateObj()
{
  obj = new Problematic(); // Here full class definition must be known
}

Now suppose the Problematic class is nested in a ProblemFactory class like this:

////// Problematic.hpp

class ProblemFactory
{
public:
  class Problematic
  {
  };
};

It's still OK to use it just like in the code above because nesting classes in C++ (opposite to Java) is only the matter of scope and Problematic still remains independent class. But unfortunately now there is no way we could declare Problematic class without including Problematic.hpp header with its whole definition. We must do it this way:

////// Second.hpp

#include "Problematic.hpp" // :(

class Second
{
  ProblemFactory::Problematic *obj;
  void CreateObj();
};

So now I avoid class nesting and prefer to prefix class names, e.g. class ProblemFactory_Problematic.

Similar issue appears when we want to use anonymous namespaces. It's good to know that functions and global variables defined and used only in one CPP file can be marked as "local", so there will be no linking error when two such functions have same name. This can be done in two ways - by using static keyword or an anonymous namespace.

////// Example.cpp

static int g_GlobalCounter;

static void Init()
{
}

Anonymous namespace offers easy way to mark whole enclosed block of code as local to the CPP file, but there is one issue. You cannot declare a class from such anonymous namespace in a header file, so this example is invalid:

////// Container.hpp

// I want to make Item class local, but I cannot declare it like this:
class Item; // Won't work.

class Container
{
  std::vector<Item*> m_Items;
  void Add();
};

////// Container.cpp

#include "Container.hpp"

namespace
{
  int g_GlobalCounter;
  
  void Init()
  {
  }
  
  class Item
  {
  };
}

void Container::Add()
{
  m_Items.push_back(new Item());
}

There is simple solution to this problem. We just need to give the namespace a name and then we can write Item class declaration like this:

////// Container.hpp

namespace ContainerImpl {
  class Item; // OK :D
}

class Container
{
  std::vector<ContainerImpl::Item*> m_Items;
  void Add();
};

////// Container.cpp

#include "Container.hpp"

namespace ContainerImpl
{
  int g_GlobalCounter;
  
  void Init()
  {
  }
  
  class Item
  {
  };
}

using namespace ContainerImpl;

void Container::Add()
{
  m_Items.push_back(new Item());
}

The content of this new namespace is not local to this single CPP file, but this namespace make the full class name (ContainerImpl::Item) unique so there is no chance to accidentaly conflict with other Item class.

Comments | #c++ Share

Comments

STAT NO AD
[Stat] [STAT NO AD] [Download] [Dropbox] [pub] [Mirror] [Privacy policy]
Copyright © 2004-2019