I\'ve done a bunch of Java coding recently and have got used to very specific package naming systems, with deep nesting e.g. com.company.project.db
. This works fine
Here are some reasons why and how C++ namespaces are different than Java or C# namespaces.
Avoiding conflicts
In Java/C# languages, namespaces are intended to avoid conflicts between names in different parts of class libraries. You may have class called "Watcher" in 5 different places in namespace hierarchy in C#. In C++, if you have same named classes occurring in your library then you put inside another class instead of creating namespaces. Such nested classes are all fine and encouraged and in fact the syntax also treats as if class is a namespace using :: operator.
How much nested namespaces should be?
Popular libraries like Boost, Eigen and of course, STL provides good examples. these libraries typically have pretty much everything stuffed in to one namespace like std::
or boost::
or eigen::
. Few components get their own namespace like std::ios
or boost:filesystem
. There is no consistent rules around when to use second level but it seems large or separately developed/maintained or optional components typically get their own namespaces. The third level is even more rare. Generally I use the structure company::project
and for large independently usable subsystem of projects company::project::component
.
Avoiding conflicts in external libraries
Now the big question: What if you get two libraries from two different people which has exact same namespaces and classes? This situation is fairly rare because most people tend to wrap their libraries at least in their project's name. Even if project names are same, its even rarer that you end up using libraries from both. However sometimes bad decisions are made for project names (ahm... "metro", "apollo" ...) or even namespaces are just not used at all. If that happens, you wrap #include for either or both libraries in to a namespace and conflict is resolved! This is one reason why people don't bother too much about conflicts because resolving them is trivial. If you follow the practice of using company::project
then conflicts become super rare.
Differences in languages
Although C++ provides using namespace
statement just like C#, its generally considered a bad practice to "import" everything in your own namespace. The reason for this is that a header can contain lots of "bad" stuff including redefining things that can totally surprise you. This is quite unlike C#/Java where you only get clean public interface when you do equivalent of using namespace
. (side note: in C++ you can achieve the same thing by using Pimpl pattern but its usually too much of extra plumbing and few libraries actually do it). So you almost never want to do using namespace
. Instead you do typedefs
(or using name =
) for what you actually want to use. This again makes deeply nested namespaces impractical to use.
Organizing code
In Java/C#, people tend to organize code in folders a lot. Typically as folder grows more than 20 or even 10 files, people would start thinking about folders. In C++, things are more diverse but for many large projects flatter directory structures are preferred. For example, standard library's std folder has 53 files and Facebook's folly project seems to go same route. I think one reason for this probably is the fact Java/C# folks use visual IDEs more and use mouse scrolls in folder navigation as opposed to console where you can use wild cards to find file in flat structure. Also C++ programmers absolutely don't shy away from putting multiple classes in single file and naming file as logical unit instead of same as class name unlike in C# or Java. This makes compilation faster which is very important for large projects. While there is no language-level requirement for having its own namespace for each folder many C++ developers prefers to assign its own namespace to each folder and keep folder hierarchy 2 or less levels deep.
Possible exception
In C++ you can refer to A::B::C::D
as just C::D
if you are already inside A::B
. So if you have private code or less used classes that you want to push further down then you might do so while still keeping your own relative depth to 2 or so. In this case, you might also want to create folder for each level just so file locations are predictable. In general, there are no gold standards in this area but you do not want to go overboard with deeply nested namespaces mimicking C#/Java.
Related
Avoiding collisions in header files; use a namespace wrapper?
Is there a 'right' way to approach namespaces in C++
Using fully qualified names in C++
Java packages vs. C++ libraries
Is there a better way to express nested namespaces in C++ within the header
How do you properly use namespaces in C++?
I'll throw in a couple of things I've heard but don't know the truthfulness of, please help confirm/dispel them.
C++ performance is (somehow) affected by long fully-specified method names e.g namespace1::namespace2::namespace3::classX::method123()
You might hit a limit on allowed symbol length in the compiler/linker
In C++, the basic unit of design and implementation is the class, not the namespace. Namespaces were intended as a means of preventing name clashes in large libraries, not for expressing concepts.
Classes have several advantages over namespaces:
However, I would look twice at any deeply nested relationship. That is really not a good way of designing software, and leads to unreadable code, whether you juse classes or namespaces.
You can have nested namespaces in C++.
They don't work the same as in java, though, obviously. Java packages are really much better defined and there is no real static init weirdness. With C++ namespaces are helpful but still have a fair bit of danger involved.
Java packages are not nested, they're flat. Any apparent nesting is nothing more than a naming convention.
For example, the package com.company.project.db
has no relation whatsoever to com.company.project
or com.company.project.db.x
. Code in com.company.project.db
has no more access to code in com.company.project.db.x
than would code in a.b.c
.
I think there is something missing in the previous answers, and it is one of the reasons I really like C++.
Imagine you are programming a graphical application and suddenly you realize that there is something common among all your widgets. You want all of them to have a new function. What do you do?
1) Edit the base widget class? OK, but most likely you do not have access to it. Maybe there is a licensing problem that prevents you from doing your own modification. Even if you can just do it, if it is something that only makes sense for your project, the authors will not include it in their future release, and upgrading the toolkit will be more painful
2) Create an interface class / multi-inheritance? Depending on your existing code it will be more or less of a pain to update every single class related with a widget. Do this and your code will cost more to maintain because everyone defining a new class must know that they are suppose to inherit from your interface. Becoming dependent of other people discipline is really risky.
The wonderful thing of C++ namespaces here is that you have an extra way to encapsulate stuff within an already existing system. Not only you can encapsulate within already existing libraries that you cannot edit, you can encapsulate similar concepts that you cannot easily insert into your hierarchy of classes/objects.
Java forces you to focus more on a pure OOP design. Sure that I am telling you might be a dirty hack and not elegant, but there are lots of lazy people programming who do not spend time fixing their designs.