C++: Przestrzenie nazw - jak poprawnie używać w plikach nagłówkowych i źródłowych?

Rozważmy parę dwóch plików źródłowych: plik deklaracji interfejsu (*.h lub *.hpp) i jego plik implementacji (*.cpp).

Niech plik *.h będzie następujący:

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

Widziałem dwie różne praktyki używania przestrzeni nazw w plikach źródłowych:

*.cpp pokazanie praktyki # 1:

#include "MyClass.h"
using namespace MyNamespace;

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

*.cpp pokazanie praktyki # 2:

#include "MyClass.h"
namespace MyNamespace {

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

}

Moje pytanie: czy są jakieś różnice między tymi dwoma praktykami i czy jest ona uważana za lepszą od inne?

Author: Mogsdad, 2012-05-30

5 answers

Z punktu widzenia czytelności kodu, moim zdaniem lepiej jest użyć metody #2 z tego powodu:

Możesz być using wieloma przestrzeniami nazw naraz, a każdy obiekt lub funkcja napisane poniżej tej linii może należeć do dowolnej z tych przestrzeni nazw (z wyjątkiem konfliktów nazw). Owijanie całego pliku w blok namespace jest bardziej jawne i pozwala zadeklarować nowe funkcje i zmienne, które należą do tej przestrzeni nazw wewnątrz .również plik cpp

 46
Author: Dan F,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-30 12:52:08

Najczystsza jest opcja, której nie pokazałeś:

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

To również bardzo gadatliwe; zbyt wiele dla większości ludzi. Ponieważ {[1] } to recepta na konflikty nazw, przynajmniej z mojego doświadczenia, i należy unikać, z wyjątkiem bardzo ograniczonych zakresów i miejsc, I ogólnie używaj swojego #2.

 38
Author: James Kanze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-30 13:30:47

Czy są jakieś różnice między tymi dwoma praktykami

Tak. #1 i # 2 są przykładami using-directive i namespace definition. W tym przypadku są one faktycznie takie same, ale mają inne konsekwencje. Na przykład, jeśli wprowadzisz nowy identyfikator obok MyClass::foo, będzie on miał inny zakres:

#1:

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

#2:

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

Jest uważany za lepszy od inne?

#1 Plusy: trochę bardziej zwięzłe; trudniej przypadkowo wprowadzić coś do MyNamespace nieświadomie. Wady: może przypadkowo wyciągnąć istniejące identyfikatory.

#2 plusy: bardziej jasne, że definicje istniejących identyfikatorów i deklaracje nowych identyfikatorów należą zarówno do MyNamespace. Wady: łatwiejsze niezamierzone wprowadzenie identyfikatorów do MyNamespace.

Krytyka zarówno #1, jak i #2 polega na tym, że odnoszą się one do całej przestrzeni nazw, gdy prawdopodobnie zależy Ci tylko na tym o definicji członów MyNamespace::MyClass. Jest to ciężkie i źle komunikuje intencje.

Alternatywą dla #1 jest using-declaration, która zawiera tylko identyfikator, który Cię interesuje:

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

int MyClass::foo() { ... }
 5
Author: John McFarlane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-10 19:05:50

Chciałbym również dodać, że jeśli zdecydujesz się z jakiegoś powodu wdrożyć specjalizację szablonu w pliku cpp i po prostu polegać na using namespace napotkasz następujący 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(){}

W przeciwnym razie, jeśli zastosujesz metodę # 2, będzie dobrze.

 3
Author: Jordan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-04 12:26:59

Chciałbym dodać jeszcze jeden sposób, używając using-declaration :

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

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

W ten sposób oszczędzasz czas od wpisywania nazwy przestrzeni nazw, jeśli klasa ma wiele funkcji

 0
Author: Joanna,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-07 06:39:36