One last subtlety I discovered while adding namespaces to EP Simulator has to do with forward declarations of classes. Most C++ programmers know you don’t have to include a header file with the class definition if you are using pointers or references to that class. For example:
class A;
class B {
A* a;
};
(Not so well known is you can do the same thing if the class is a parameter passed to a function by value or a return value — but that’s another story). Now what happens when you try this with namespaces?
// file A.h
namespace X {
class A {};
}
// file B.h
class A; // forward declaration - doesn't work!
namespace X {
class B {
A* a; // will not refer to X::A!
};
}
Well, unfortunately here there is a forwardly declared class A in the global namespace, and an A in namespace X. Even though class B is in namespace X too, it has no idea there is a class A in X too (unless you include file A.h, but that defeats the beauty of forward declarations). Well, what else can you try to make this work?
// B.h
class X::A; // also doesn't work
namespace X {
class B {
A* a; // will not refer to X::A!
};
}
This doesn’t work presumably because the compiler hasn’t a clue what the heck the X is qualifying the class name A. So what will work? You have to declare the class in the namespace itself. Thus either:
// B.h
namespace X { class A; } // OK
namespace X {
class B {
A* a; // A is X::A
};
}
or
// B.h
namespace X {
class A;
class B {
A* a; // X::A
};
}
If we are dealing with separate namespaces, then:
class A elsewhere
// B.h
namespace Y { class A; } // full declaration of
//
namespace X {
using Y::A;
class B {
A* a; // Y::A
};
}
The bottom line is namespaces may help organize your code, but they also make things more complicated. For a complex program though, I believe the advantages outweigh the drawbacks.
Thanks,
real nice help!
Thank you – it helped me!
The last example on the different namespaces case saved me quite a lot of time of madness and slef-hatred and despair. THANK YOU
What happens if class A is not in any namespace? You can’t use ‘using Y::A’ neither declare class A inside namespace X, because the ‘real’ A belongs to a .h wihout namespaces.
I’m not sure I fully understand your question. If class A is in the global namespace, you can reference it as ::A. You would need to do this to disambiguate an identically named class in a namespace, e.g. X::A. X::A would hide global namespace A unless you refer to it as ::A.