2009-07-31 15 views

Odpowiedz

149

Alias ​​przestrzeni nazw jest wygodnym sposobem na odwoływanie się do nazwy długiej przestrzeni nazw za pomocą innej, krótszej nazwy.

Jako przykład, powiedzmy, że chcesz użyć liczbowych wektorów z uBLAS Boosta bez dyrektywy using namespace. Podając pełną nazw za każdym razem jest uciążliwy:

boost::numeric::ublas::vector<double> v; 

Zamiast tego można zdefiniować alias dla boost::numeric::ublas - powiedzmy chcemy skrócić ten właśnie ublas:

namespace ublas = boost::numeric::ublas; 


ublas::vector<double> v; 
+7

Aby możliwie wyjaśnić spadki, SO nie jest i nigdy nie zastąpi dobrego podręcznika C++. Na postawione pytanie odpowie odpowiedź na każdą taką książkę. A SO "funkcja" odpowiadania na własne pytania nie powinna być używana do dostarczania parafraz takich książek. –

+16

Bez urazy ... Po prostu wyjaśnić, dlaczego to zrobiłem: To było moje zrozumienie z komentarzy Joela z podcastu, że nawet pytania "na poziomie podstawowym" były uczciwą grą na SO i że można zadać pytanie i odpowiedź samemu, jeśli ta treść nie była jeszcze dostępna w SO w przystępnej formie. Ale najwyraźniej jest to mile widziane? –

+1

Istnieje na pewno etykieta, aby odpowiedzieć na własne pytanie, aby uniknąć irytacji; w tym przypadku jest oczywiste, że nigdy ** nie było prawdziwym pytaniem. Na przykład http://stackoverflow.com/questions/494927/stack-overflow-etiquette-for-answering-your-own-question –

6

Dość prosto, #define nie zadziała.

namespace Mine { class MyClass { public: int i; }; } 
namespace His = Mine; 
namespace Yours { class Mine: public His::MyClass { void f() { i = 1; } }; } 

Kompiluje dobrze. Umożliwia pracę w przypadku kolizji nazw i klas.

namespace Nope { class Oops { public: int j; }; } 
#define Hmm Nope 
namespace Drat { class Nope: public Hmm::Oops { void f() { j = 1; } }; } 

W ostatnim wierszu "Hmm: Oops" jest błędem kompilacji. Pre-procesor zamienia go na Nope :: Oops, ale Nope jest już nazwą klasy.

+0

Tak prosty, ale nieporęczny w tym samym czasie ...;) – Hermes

+2

Co #define? Być może twoja odpowiedź odnosi się do poprzedniej wersji pytania? – einpoklum

1

Więcej na ten temat http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-1-of-n

Chodzi przede wszystkim o wyborze alias dłuuugi nazwą przestrzeni nazw, takich jak:

namespace SHORT = NamespaceFirst::NameSpaceNested::Meow

potem można typedef

typedef SHORT::mytype

zamiast

typedef NamespaceFirst::NameSpaceNested::Meow::mytype

Składnia ta działa tylko dla nazw, nie może zawierać klasy, typy po namespace NAME =

1

pamiętać również, że aliasy nazw i używając dyrektyw są rozwiązywane w czasie kompilacji, a nie czas pracy. (Mówiąc dokładniej, oba są narzędziami używanymi do informowania kompilatora, gdzie jeszcze szukać przy rozwiązywaniu nazw, jeśli nie może znaleźć określonego symbolu w bieżącym zakresie lub żadnym z jego zakresów nadrzędnych.) Na przykład, żaden z nich nie będzie skompilować:

namespace A { 
    int foo; 
    namespace AA { 
     int bar; 
    } // namespace AA 
    namespace AB { 
     int bar; 
    } // namespace AB 
} // namespace A 
namespace B { 
    int foo; 
    namespace BA { 
     int bar; 
    } // namespace BA 
    namespace BB { 
     int bar; 
    } // namespace BB 
} // namespace B 

bool nsChooser1, nsChooser2; 
// ... 

// This doesn't work. 
namespace C = (nsChooser1 ? A : B); 
C::foo = 3; 

// Neither does this. 
// (Nor would it be advisable even if it does work, as compound if-else blocks without braces are easy to inadvertently break.) 
if (nsChooser1) 
    if (nsChooser2) 
     using namespace A::AA; 
    else 
     using namespace A::AB; 
else 
    if (nsChooser2) 
     using namespace B::BA; 
    else 
     using namespace B::BB; 

teraz ciekawy umysł może zauważyli, że constexpr zmienne są również używane w czasie kompilacji, i zastanawiam się, czy mogą one być stosowane w połączeniu z obu aliasu lub dyrektywy. Według mojej wiedzy nie mogą, chociaż mogę się mylić. Jeśli chcesz pracować ze zmiennymi o tej samej nazwie w różnych obszarach nazw i wybierać między nimi dynamicznie, musisz użyć referencji lub wskaźników.

// Using the above namespaces... 
int& foo = (nsChooser1 ? A::foo : B::foo); 

int* bar; 
if (nsChooser1) { 
    if (nsChooser2) { 
     bar = &A::AA::bar; 
    } else { 
     bar = &A::AB::bar; 
    } 
} else { 
    if (nsChooser2) { 
     bar = &B::BA::bar; 
    } else { 
     bar = &B::BB::bar; 
    } 
} 

Użyteczność powyższego może być ograniczona, ale powinna służyć temu celowi.

(Moje przeprosiny za wszelkie błędy, które mogłem pominąć w powyższym.)