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

巧了我就是萌 提交于 2019-12-31 07:59:25

问题


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?


回答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




回答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 recepe for name conflicts, at least in my experience, and should be avoided except in very limited scopes and places, I generally use your #2.




回答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() { ... }



回答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.




回答5:


I'd like to add one more way, using using-declaration:

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

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

This way saves you from typing namespace name many time if class have many functions



来源:https://stackoverflow.com/questions/10816600/c-namespaces-how-to-use-in-header-and-source-files-correctly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!