C++: Namespaces -- How to use in header and source files correctly?

71,225

Solution 1

From a code readability standpoint, it is probably better in my opinion to use the #2 method for this reason:

You can be using multiple namespaces at a time, and any object or function written below that line can belong to any of those namespaces (barring naming conflicts). Wrapping the whole file in a namespace block is more explicit, and allows you to declare new functions and variables that belong to that namespace within the .cpp file as well

Solution 2

The clearest is the option you didn't show:

int MyNamespace::MyClass::foo()
{
    //  ...
}

It's also very verbose; too much so for most people. Since using namespace is a recipe for name conflicts, at least in my experience, and should be avoided except in very limited scopes and places, I generally use your #2.

Solution 3

Are there any differences between these two practices

Yes. #1 and #2 are examples of a using-directive and a namespace definition respectively. They are effectively the same in this case but have other consequences. For instance, if you introduce a new identifier alongside MyClass::foo, it will have a different scope:

#1:

using namespace MyNamespace;
int x;  // defines ::x

#2:

namespace MyNamespace {
  int x;  // defines MyNamespace::x
}

is one considered better than the other?

#1 Pros: a little more terse; harder to accidentally introduce something into MyNamespace unwittingly. Cons: may pull in existing identifiers unintentionally.

#2 Pros: more clear that definitions of existing identifiers and declarations of new identifiers both belong to MyNamespace. Cons: easier to unintentionally introduce identifiers to MyNamespace.

A criticism of both #1 and #2 is that they are referring to an entire namespace when you probably only care about the definition of members of MyNamespace::MyClass. This is heavy-handed and it communicates the intent poorly.

A possible alternative to #1 is a using-declaration which includes only the identifier you're interested in:

#include "MyClass.h"
using MyNamespace::MyClass;

int MyClass::foo() { ... }

Solution 4

I'd like also to add that if you decide due to some reason to implement a template specialization in a cpp file and just rely on using namespace you will run into the following problem:

// .h file
namespace someNameSpace
{
  template<typename T>
    class Demo
    {
      void foo();
    };
}

// .cpp file
using namespace someNameSpace;

template<typename T>
void Demo<T>::foo(){}

// this will produce
// error: specialization of 'template<class T> void someNameSpace::Demo<T>::foo()' in different namespace [-fpermissive]
template<>
void Demo<int>::foo(){}

Otherwise if you apply #2 method this will be fine.

Solution 5

I think the practice #1 is not correct C++ code at all. This code snippet defines ::MyClass::foo symbol, where the real full qualified name is ::MyNamespace::MyClass::foo.

To learn about namespaces you can read section 7.3 of the draft let's say for standard http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3690.pdf

This concept is pretty old from 1998 or so, so you can use any standard or books of B.Stroustroup to learn about it.

In C++ language the namespace is a named scope. The namespace, as opposed to the class definition, is open to adding new functions to it.

The construction "using namespace NS;" in C++ is called as using-directive, and it can be used for several goals in my practice:

  1. You can use this directive in another namespace to combine(mix) names from a different namespace.
  2. In the context of the compilation unit it appends synonyms to all variables in namespace NS.

To define symbol, you can use two mechanisms - you can use the explicit qualification with all namespaces via operating in global namespace in C++ source file.

Or You can open namespace and add definitions to it (practice #2).

Share:
71,225

Related videos on Youtube

nickolay
Author by

nickolay

Updated on April 20, 2022

Comments

  • nickolay
    nickolay about 2 years

    Consider a pair of two source files: an interface declaration file (*.h or *.hpp) and its implementation file (*.cpp).

    Let the *.h file be like the following:

    namespace MyNamespace {
      class MyClass {
      public:
        int foo();
      };
    }
    

    I have seen two different practices for using namespaces in source files:

    *.cpp showing practice #1:

    #include "MyClass.h"
    using namespace MyNamespace;
    
    int MyClass::foo() { ... }
    

    *.cpp showing practice #2:

    #include "MyClass.h"
    namespace MyNamespace {
    
      int MyClass::foo() { ... }
    
    }
    

    My question: Are there any differences between these two practices and is one considered better than the other?

    • Benjamin Bannier
      Benjamin Bannier about 12 years
      There's also option 3: Just us the full name, e.g. int MyNamespace::MyClass::foo() ....
    • David
      David about 12 years
    • nickolay
      nickolay about 12 years
      @Dave not duplicate. These questions complement each other. Recommend to add the link provided by Dave as "Read also..." to this question. My question will help novices to choose the correct style.
    • Firedragon
      Firedragon almost 12 years
  • Dan F
    Dan F about 12 years
    The question Dave linked in his comment to your question also outlines some key points in the differences (if any) between the two methods you're looking at
  • nickolay
    nickolay about 12 years
    Thanks very clear. Together we made a good FAQ page for namespaces users. :)
  • nickolay
    nickolay about 12 years
    Guys, I really do not know whose answer to select. They have intersection while complement each other.
  • nickolay
    nickolay about 12 years
    Guys, I really do not know whose answer to select. They have intersection while complement each other.
  • pedrostanaka
    pedrostanaka almost 9 years
    Just commenting to acknowledge that some IDE's like CLion will only detect implementations if you use option/practice #2.
  • John McFarlane
    John McFarlane about 8 years
    @PedroTanaka is this still the case? I have not noticed any such problem.
  • pedrostanaka
    pedrostanaka about 8 years
    @JMcF I haven't checked since the time I published the comment. In early versions of Clion the problem occurred.
  • pdaawr
    pdaawr almost 4 years
    The option 3 presented below int MyNamespace::MyClass::foo() {...} is working correctly in CLion 2020.2.1