2015-06-04 10 views
7

Oto niektóre wymyślony przykład kodu:C++: Czy dziedziczenie z klasy przenosi je do przestrzeni nazw?

template<typename T> void Do(T arg) { (void)arg->b; } 

namespace A { 
    struct Foo { int a; }; 
} 

namespace B { 
    struct Foo { int b; }; 
    struct Bar : A::Foo { 
     void Blah() { Do((Foo *)0); } 
    }; 
} 

który podczas skompilowane z gcc 4.8.2 (dzyń daje podobny błąd):

namespacebug.cpp: In instantiation of ‘void Do(T) [with T = A::Foo*]’: 
namespacebug.cpp:10:34: required from here 
namespacebug.cpp:1:39: error: ‘struct A::Foo’ has no member named ‘b’ 
template<typename T> void Do(T arg) { (void)arg->b; } 
            ^

notatkę w błędzie to odnosi się do T = A::Foo nawet choć pod wywołuj strony Tworzę Foo w przestrzeni nazw B. Jeśli usunę dekoder klasy podstawowej (: A::Foo), wszystkie kompilacje będą w porządku.

To wydaje się sugerować, że dziedziczenie po A::Foo w jakiś sposób przenosi je do mojej przestrzeni nazw i dopasowuje do mojego użytku z Foo? Co to jest funkcja C++?

(Oczywiście, problem ten może być łatwo ustalony przez przestrzenie nazw moje użycie Foo, ale to nie jest pytanie.)

+0

'(void) arg-> b;' - co to oznacza? –

+2

@EdHeal, myślę, że to tylko po to, aby wymusić błąd. – StoryTeller

+0

@StoryTeller - Więc jaki jest sens robienia głupich rzeczy? –

Odpowiedz

5

Ponieważ reguły wstrzykiwane klasy-name, nazwa klasy jest widoczny tak, jakby to był jej członkiem.

9/2

nazwa-klasy jest wkładany w zakresie, w jakim jest on zadeklarowanym natychmiast po nazwa-klasywidać.Klasa o nazwie klasy jest również wstawiana w zakres samej klasy; jest to znane jako nazwa klasy wtryskiwanej. Do celów sprawdzania dostępu nazwa klasy wtryskiwanej jest traktowana tak, jakby była nazwą publiczną.

Więc to jest tak, jakby klasa A::Foo zawiera członkiem Foo których nazwy typu A::Foo. Ponieważ wyszukiwanie nazw w Bar::Blah() uważa członków bazowych Bar przed członkami przestrzeni nazw, wyszukiwanie nazwy dla Foo znajduje nazwę klasy wtryskiwanej o nazwach A::Foo.

+0

Dzięki! to jest to. – Aardappel

3

Czy dziedziczenie z klasy doprowadzić go do przestrzeni nazw?

Sortuj. Jeśli wyszukiwanie klasy zakończy się niepowodzeniem, to wyszukiwanie kontynuowane jest w klasie bazowej.

10,2 Nazwa użytkownika odnośników

...

5 W przeciwnym razie (tj C nie zawiera deklarację f lub wynikowy zestaw jest pustą deklaracją), S(f,C) jest początkowo pusty. Jeśli C ma klas bazowych, obliczyć odnośnika ustawiony dla f w każdej klasie bazowej podobiektu Bi bezpośredni i połączyć każdą taką odnośnika ustawić S(f,Bi) z kolei do S(f,C).

Wyszukiwanie nazwy użytkownika obejmuje również wyszukiwanie typów zagnieżdżonych. Później w tej samej sekcji, znajdziemy:

9 [Uwaga: statycznego elementu, typ zagnieżdżony lub moduł wyliczający zdefiniowane w klasie bazowej T jednoznacznie można znaleźć nawet jeśli obiekt ma więcej niż jedną bazę Podobiekt klasy typu T. Dwie podobiekty klasy bazowej współużytkują niestatyczne podobiekty członków swoich wspólnych wirtualnych klas bazowych. końcem uwaga]

+1

To jest dla członków. Jest to typ, a nie element członkowski i jest zgodny z typem klasy podstawowej. – Aardappel

+0

@Aardappel Prawidłowo. Jednak wstrzyknięta nazwa klasy jest członkiem klasy bazowej i jest dziedziczona tak jak inni członkowie. W ten sposób możesz napisać takie rzeczy jak 'struct A {}; struct B: A {}; int main() {B :: A(); } '. – hvd

+0

@Aardappel, wyszukiwanie nazw obejmuje także typy zagnieżdżone. Zobacz moją aktualizację. –