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?
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
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.
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
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 obokCzy są jakieś różnice między tymi dwoma praktykami
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() { ... }
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.
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
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