[C++] Deklaracja przyjaźni a nazwy z qualified-id

0

Hej,

Mam pytanie odnośnie qualified-id. Jest to nazwa, w której występuje czworokropek (operator zakresu) - ::.

Pytanie dotyczy deklaracji przyjaźni. Mamy taki oto kod:

class X;

class A
{
    friend class ::X;
    friend class X;
};

Jak nie napiszemy pierwszej linijki to wystąpi błąd w linijce z operatorem zakresu. Ale dlaczego?! Przecież ::X czy X oznacza tutaj to samo (zakładając ze klasa A znajduje się w zakresie globalnym i X oznacza globalną klasę X) - a przy X kompilator nie zaprotestuje, jakby nie było 1-szej linijki.

Dlaczego tak się dzieje ? :|

Z góry dziękuję za pomoc :)

0

przyklad:

namespace E
{
    class A
    {
        friend class F::X;
    };
}

namespace F
{
    class X{};
}

generuje dokladnie taki sam blad jak u Ciebie z friend ::X. zwroc uwage, ze tutaj blad ten jest sensowny! kompilator analizuja F::X nie ma zielonego pojecia, czymże owo F jest - czy to jest klasa, namespace czy ki diabeł. Twoj oryginalny przykald rozni sie jedynie od tego tym, ze u Ciebie namespace F jest namespacem '', globalnym.
w moim przykladzie, nalezy dopisac fwd decl: namespace F{class X;} na poczatku i od tej pory dla kompilatora wszystko jest jasne.

patrzac teraz z drugiej strony:

namespace E
{
    class A
    {
        friend class X;

        int z;
    };
}

namespace F
{
    using namespace E;

    class X
    {
        X(){ A().z = 5;}
    };
}

oczywiscte jest, ze F::X nie ma dostepu do 'z', poniewaz friend mowi o X, czyli E::X. Zmiana namespace'a F na E "rozwiazuje problem", gdyz wtedy X staje sie lokalny dla E, friend spodziewa sie lokalnego -- i jest wszystko dopasowane.

proba spiecia 'na chama' friendowanego X'a jako zewnetrzengo, np. dopisania w 'namespace E' frazy 'using namespace 'F' celem zwiazania X'a z wlasciwa F::X natychmiast wywala, ze F nie jest uznawane jako namespace. Czy F::, czy usingnamespaceF - F jest zewnetrzne, wiec musi byc w 100% zdefiniowane. Wymagany uprzedni fwd decl (jak poprzednio) i wtedy using-namespace-F jest ok:

namespace F{class X;}

namespace E
{
    using namespace F;

    class A
    {
        friend class X;

        int z;
    };
}

namespace F
{
    using namespace E;

    class X
    {
        X(){ A().z = 5;}
    };
}

Wszystko gra? Fwd decl jest, X jest znane jako zawartosc F::, friend jest zadeklarowany na X.
I zonk! Dostepu NIE MA.
Friend deklaruje przyjazn dla nieokreslonego, kontekstowego, "tutejszego" X'a, czyli:

  • albo pochodzacego z klasy A,
  • albo z namespace E,
  • albo z namespace '', czyli globalnego

Using (jak widać) nie ma nic do rzeczy w tym miejscu. X siedzi w F::, wiec nie pasuje do niczego widzialnego przez friend. Napisanie F::X oczywiscie rozwiazuje sprawe, napisanie ::X spowoduje, ze X bedzie szukany w global namespace..

kolejny przypadek roznicy miedzy kontekstowe-a-:

namespace E
{
    class A
    {
        friend class X;

        int z;

        class X
        {
            X(){ A().z = 5;}
        };
    };
}

X jest kontekstowe, wiec moze byc lokalne, wiec jego sprawdzenie jest opoznione az calosc zostanie przeanalizowana. Dopisanie we friendzie A::X, mimo ze znaczy 'to samo', sugeruje kompilatorowi niekontekstowosc/zewnetrznosc i natychmiast powoduje ze kompilator wyrzuca blad nieodnalezienia X - dokladnie tak jak wczesniej. I tak jak wczesniej, umieszczenie friend A::X juz PO definicji inner-class'y okaze sie poprawnym zapisem - klasa A::X jest juz znana, wiec w punkcie uzycia konkretnego A::X udaje sie ja znalezc..

powiąż to teraz z Tym co probowales zrobic, uwzgledniajac ze u Ciebie wszystko bylo w namespace '' czyli globalnym - i wszystko powinno byc jasne :)

0

OK, dzięki wielkie za odpowiedź :) Mam dwa pytania, potem dokończę czytać resztę posta, żeby mi się wszystko nie pomieszało :)


quetzalcoatl napisał(a)

w moim przykladzie, nalezy dopisac fwd decl: namespace F{class X;} na poczatku i od tej pory dla kompilatora wszystko jest jasne.

OK, a gdyby F było klasą to na początku trzeba byłoby napisać już jej definicję + w środku jej deklarację czy definicję klasy X.

class F
{
    public:
    class X{};
};

namespace E
{
    class A
    {
        friend class F::X;
    };
}

Czyli jeśli przed właściwą klasą (nazwą na końcu tej "sklejanki" operatorami ::) występują jakieś inne klasy to muszą one być już wcześniej wszystkie zdefiniowane, tak ?


quetzalcoatl napisał(a)

oczywiscte jest, ze F::X nie ma dostepu do 'z', poniewaz friend mowi o X, czyli E::X. Zmiana namespace'a F na E "rozwiazuje problem", gdyz wtedy X staje sie lokalny dla E, friend spodziewa sie lokalnego -- i jest wszystko dopasowane.

Kolejna regułka, której się nie przyglądnąłem nigdy - nazwa w namespace zawsze ma przed sobą nazwę tej przestrzeni w której jest, tak ? Czyli jak w deklaracji przyjaźni występuje np. nazwa B::F, a ta deklaracja przyjaźni jest w klasie C, która jest w przestrzeni o nazwie H, to deklaracja przyjaźni tak na prawdę wygląda tak: H::F ?


Z góry dzięki za odpowiedź, po niej dokończę czytać bo chcę się upewnić odnośnie tych 2 rzeczy :)

0
alexas napisał(a)

OK, a gdyby F było klasą to na początku trzeba byłoby napisać już jej definicję + w środku jej deklarację czy definicję klasy (...) Czyli jeśli przed właściwą klasą (nazwą na końcu tej "sklejanki" operatorami ::) występują jakieś inne klasy to muszą one być już wcześniej wszystkie zdefiniowane, tak ?

Tak.
W innym wypadku, nie jestes w stanie wyrazic poprawnie deklaracji klasy X.
Niech bedzie np. ze X ma byc w klasie Cos, ktore jest w klasie Swiat w namespace Bum, czyli Bum::X, porownaj:

class X;

oznacza fwd-decl z 'okolicy lokalnej' - cos innego

Bum::class X;

oznacza fwd-decl Bum::X - cos innego, w dodatku wymaga aby Bum::X bylo juz-znane

namespace Bum { class X; }

oznacza fwd-decl X w namespace Bum - nie wymaga, aby X bylo znane, ale znaczy cos innego niz chcemy

namespace Bum { class Swiat::Cos::X; }

niby ok, ale wymaga aby Swiat oraz Cos oraz X byly juz-znane..

namespace Bum { class Swiat{ .... class Cos{ .... class X; .... } .... } }

oznacza to co chcemy - fwddecl nieznanej-jeszcze nazwy X, bedacej class, siedzacej w class Cos, w class Swiat, w namespace Bum. ALE: COS oraz SWIAT sa definicjami! Dlatego umiesciem tam wielokropki -- pola, metody, wszystko tam musi byc podane. Tylko i wylacznie X jest forward-deklaracja, zreszta niskiego sensu - poniewaz skoro "COS" jed deFINIOwane, to deFINIcja typu X tez sie musi w nim pojawic lada moment ponizej... Stad wynika wprost "wymaganie", aby Swiat i Cos byly "zdefiniowane".. A tak mówiąc scisle - to nie wymaganie. Ty po prostu nie jestes w stanie zadeklarowac X inaczej niz poprzed podanie definicji Cos,Swiat siedzacych w Bum..

Z teog wlasnie "malego" powodu, wprowadzono NAMESPACE'y. I tym przede wszystkim sie one roznia od klas+static. Zwroc uwage, ze w/w przypadek wymusza podanie pelnej definicji Swiat i Cos, a co z namespace Bum? ona NIE MUSI byc pelna! W przeciwienstwie do ciał typów/metod/etc, ciała namespace'ow sa zawsze OTWARTE i przez to "zawsze nie do końca pełne" - mam nadzieje ze nie musze tlumaczyc. Wyciagajac typ X na zewnatrz i umieszczajac go w analogicznym pod-namespace:

namespace Bum { namespace Swiat2 { namespace Cos2 { class X; } } }

jest absolutnie poprawna forward-decl., i od tej pory mozesz uzywac kwalifikowanego Bum::X a klasy Bum::Swiat oraz Bum::Cos moga sobie byc zadeklarowane/zdefiniowane (prawie) gdziekolwiek, i rowniez do tych namespace'ow mozesz w (prawie) dowolnym miejscu cos dodatkowego dopisac..

@Twoj przyklad, por.:

 // forward decl:
namespace F_internal
{
    class X;
}
...
...
namespace E
{
    class A
    {
        friend class F_internal::X;  // OK! zwroc uwage, ze typ F jest kompletnie nieznany
    };
}
...
...
// i gdziestam kiedys definicja:
namespace F_internal
{
    class X{};  
}

// uzycie przez F:

using namespace F_internal;  // po co sie meczyc.. import calego swojego _impl

class F
{
     F() { delete new X(); }  // ot tak, tak jakby X bylo w F - dzieki using - ale faktycznie jest w F_impl
};
alexas napisał(a)

Kolejna regułka, której się nie przyglądnąłem nigdy - nazwa w namespace zawsze ma przed sobą nazwę tej przestrzeni w której jest, tak ? Czyli jak w deklaracji przyjaźni występuje np. nazwa B::F, a ta deklaracja przyjaźni jest w klasie C, która jest w przestrzeni o nazwie H, to deklaracja przyjaźni tak na prawdę wygląda tak: H::F ?

Nie. Moze tak wygladac, ale nie musi.

W poprzednim poście starałem się Ci pokazać różnice pomiędzy kwalifikowanymy identyfikatorami, a niekwalifikowanymi
X - unqualified
Swiat::X - qualified
koniec rozroznienia. Innych typow identyfikatorow nie ma. wszystkie nazwy sa albo takie, albo takie.
Roznica miedzy nimi brzmi:

  • niekwalifikowane podlegaja lokalnemu dopasowywaniu do najblizszej pasujacej definicji osiagalnej w danym scopie
  • kwalifikowane sa rozumiane jako twarde wiazania do podanych konkretnych definicji lezacych na konkretnej podanej sciezce, patrzac od samej gory drzewa nazw
    Co wiecej, zwroc uwage na rekurencyjnosc tych terminow, w ponizszej nazwie:
namespace Ah{namespace Oh{namespace Uh{
   ...
   blahblah    Swiat::Cos::X ;
   ...
}}}

X, Cos - sa kwalifikowane
Swiat - jest niekwalifikowany
-> to znaczy, ze lokalizacja identyfikatorow 'Cos' i 'X' jest sztywna i konkretna, i kompilator bedzie sie spodziewal, ze sa znane, i bedzie ich szukal odpowiednio we "Swiat::" oraz "Cos::"
-> to znaczy ze lokalizacja identyfikatora 'Swiat' jest luzna i zostanie dopasowana kontekstowo
--->> to znaczy, ze Swiat::X != Ah::X !!!!

ponizsze przyklady pokazuja w jaki sposob dziala nazwy (nie)kwalifikowane i maja nie wiele wspolnego z "friend". on jest tutaj tylko jako przyklad uzycia jakiejs nazwy. wszystko rozbija sie o scope'y i kwalifikowanie nazw!

namespace E // przyklad 1
{
    class A
    {
        friend struct X;
        int z;

        struct X{ X(){A().z = 1;}};
    };
}

poprawny. friend struct X oznacza kontekstowe X, ale w momencie jego definicji nie ma nic takiego (jest ponizej) - wiec nie dopasowuje sie do inner-structX. kod jest poprawny gdyz na ma dostep ot tak, z racji bycia inner-..

namespace E // przyklad 2a
{
    class A
    {
        friend struct X;
        int z;
    };

    struct X{ X(){A().z = 1;}};
}

poprawny, na mocy tego co wczesniej, struct X lezy w kontekscie (namespace F) wyrazenia friend-X

namespace E // przyklad 2b
{
    struct X;
    
    class A
    {
        friend struct X;
        int z;
    };

    struct X{ X(){A().z = 1;}};
}

poprawny, na mocy tego co wczesniej, struct X lezy w kontekscie (namespace F) wyrazenia friend-X, fwd-decl nic nie wnosi

namespace E // przyklad 3
{
    class A
    {
        friend struct X;
        int z;

        struct X{ X(){A().z = 1;}}; // qualified:  ::E::A::X
    };

    struct X{ X(){A().z = 1;}}; // qualified:  ::E::X
}

rowniez poprawny. friend faktycznie odnosi sie do E::X a nie E::X

z kolei

namespace E // przyklad 4a
{
    class A
    {
        int z;

        struct X{ X(){A().z = 1;}}; // qualified:  ::E::A::X

        friend struct X;
    };

    struct X{ X(){A().z = 1;}}; // qualified:  ::E::X
}

jest bledny! bardziej-lokalny X zdefiniowany PRZED friend-X przykrywa zewnetrzne X

namespace E // przyklad 4b
{
    class A
    {
        int z;
        
        struct X;
        
        friend struct X;
        
        struct X{ X(){A().z = 1;}}; // qualified:  ::E::A::X
    };

    struct X{ X(){A().z = 1;}}; // qualified:  ::E::X
}

jest bledny!! bardziej-lokalny X zadeklarowany PRZED friend-X przykrywa zewnetrzne X, fwd-decl spowodowal zmiane kontekstu! porownaj z przykladem 2b!

//struct X;  // przyklad 5a

namespace E
{
    class A
    {
        friend struct X;
        int z;
    };
}

struct X{ X(){E::A().z = 1;}};

bledny, gdyz friend-X odnosi sie do czegos kontekstowego, ale struct-X lezy poza jego kontekstem (namespace F). fwd-decl X nic nie pomoze

namespace E // przyklad 5b
{
    //struct X;

    namespace F
    {
        class A
        {
            friend struct X;
            int z;
        };
    }

    struct X{ X(){E::F::A().z = 1;}};
}

bledny, gdyz friend-X odnosi sie do czegos kontekstowego, ale struct-X lezy poza jego kontekstem (namespace F). fwd-decl X nic nie pomoze

namespace E // przyklad 6a
{
    //struct X;
    
    namespace F
    {
        class A
        {
            friend struct ::X;
            int z;
        };
    }

    struct X{ X(){E::F::A().z = 1;}};
}

bledny, gdyz friend-X odnosi sie do czegos w default/global namespace. fwd-decl nie pomoze.

//struct X;   // przyklad 6b

namespace E
{
    namespace F
    {
        class A
        {
            friend struct ::X;
            int z;
        };
    }
}

struct X{ X(){E::F::A().z = 1;}};

bledny, ale fwd-decl zmieni kontekst i poprawi! ::X mowi o konkrecie w global namespace, wiec jesli odkomentujesz fwd-decl - szukany identyfikator bedzie juz istnial w miejscu friend-::X

namespace E // przyklad 7a
{
    class A
    {
        private: struct F
        {
            struct X{};
        };

        friend class F::X;
    };

    namespace F
    {
        struct X{ X(){ E::A::F::X(); }}; // test dostepu
    }
}

bledny. friend-F::X mowi o konkretnym 'X' w kontekstowym 'F', wiec dopasowuje sie do zdefiniowanego tuz-wczesniej inner-structX, ktory i tak by mial dostep. strukturaX zewnetrza nie dostaje dostepu

namespace E // przyklad 7b
{
    class A
    {
        friend class F::X;

        private: struct F
        {
            struct X{};
        };
    };

    namespace F
    {
        struct X{ X(){ E::A::F::X(); }};
    }
}

bledny. friend-F::X mowi o konkretnym 'X' w kontekstowym 'F', jednak w punkcie tym F jest kompletnie nie znane! wiec jaka mowa o konkretnym X w F?

namespace E
{
    namespace F
    {
        struct X;
    }

    class A
    {
        friend class F::X; // zagadka:) poprawne? ktore F::X ?

        private: struct F
        {
            struct X{};
        };
    };

    namespace F
    {
        struct X{ X(){ E::A::F::X(); }};
    }
}

poprawny! friend-F::X mowi o konkretnym X w jakims F; patrzac z kontekstu tego miejsca, F zostalo wczesniej zadeklarowane jako namespace, w ktorym fwd-decl zadeklarowalo jakas nieznana strukture X; F::X na mocy tego zostaje rozpoznane jako (niecalkiem znana jeszcze) struktura X-w-F-w-E, a nie do inner-class ktora jest zadeklarowana po friend'zie. dzieki temu pozniejsza faktyczna implemetnacja namespaceF::structX ma dostep do prowatnej innerstruct..

przyklady sprawdzane na "gcc version 4.4.3 20100205 (release) (PLD-Linux)", niestety w chwili pisania innego pod reka nie mam. chetnie sie dowiem czy np. Comeau sie z w/w zgadza?

0
quetzalcoatl napisał(a)

chetnie sie dowiem czy np. Comeau sie z w/w zgadza?

http://www.comeaucomputing.com/tryitout/ - wklej i sprawdź.

0

bez przesady, znam ten link. i tak sie rozpisalem za bardzo, nie mam/mialem az tyle czasu zeby jeszcze przyklady przerzucac mailami.. moze jutro

0

Dzięki wielkie za odpowiedź :) Doceniam ile czasu nad nimi spędzasz ;)

Mam jeszce kilka pytań, i potem już dokończę czytać 2-giego posta. Tylko jak możesz to odpowiedz na te pytania już krótko, a nie tak wyczerpująco bo nie mogę tego ogarnac od razu. (PS. Sorry, ze pisze po pol-miesiecznej przerwie, ale nie moglem przez chwile zajmowac sie tymi rzeczami).


Twój pierwszy post:

quetzalcoatl napisał(a)

Wszystko gra? Fwd decl jest, X jest znane jako zawartosc F::, friend jest zadeklarowany na X.
I zonk! Dostepu NIE MA.
Friend deklaruje przyjazn dla nieokreslonego, kontekstowego, "tutejszego" X'a, czyli:
(...)

  • albo z namespace E,
    (...)
    Using (jak widać) nie ma nic do rzeczy w tym miejscu. X siedzi w F::, wiec nie pasuje do niczego widzialnego przez friend. Napisanie F::X oczywiscie rozwiazuje sprawe

F::X rozwiazuje sprawe, ale przeciez using wprowadzono wlasnie po to, żeby nie pisać F::. using ściąga zawartość całej swojej przestrzeni nazw do miejsca w którym zostało napisane (to using costam). Więc wg mnie sciągneło też klasę 'X', klasa 'X' jest więc już w 'namespace E', wiec to powinno figurować pod opcję:

"- albo z namespace E"...

Dlaczego tak nie jest - dlaczego jest błąd ?

quetzalcoatl napisał(a)

Dopisanie we friendzie A::X, mimo ze znaczy 'to samo', sugeruje kompilatorowi niekontekstowosc/zewnetrznosc i natychmiast powoduje ze kompilator wyrzuca blad nieodnalezienia X - dokladnie tak jak wczesniej. I tak jak wczesniej, umieszczenie friend A::X juz PO definicji inner-class'y okaze sie poprawnym zapisem - klasa A::X jest juz znana

'jest juz znana' ? Przecież ona jest znana cały czas - deklaracje/definicje w klasach wystepujace na końcu znane są nawet już na początku - tam nie obowiązują takie zakresy waznosci jak w funkcjach. Ze od definicji/deklaracji do końca, tylko po prostu - nazwa jest znana w całej klasie, niezaleznie od miejsca wystapienia definicji/deklaracji...

Wiec nie wiem dlaczego kompilator ma tu wywalic błąd :-/

Twój drugi post:

quetzalcoatl napisał(a)

Roznica miedzy nimi brzmi:

  • niekwalifikowane podlegaja lokalnemu dopasowywaniu do najblizszej pasujacej definicji osiagalnej w danym scopie

W danym scope mówisz... Czyli na przykład tutaj:

namespace BBB
{
    class A
    {
        friend class X;  //1
    };
}

class X
{};

namespace BBB
{
    class X
    {}; //2
}

Kompilator w linii *1 będzie szukał X w tej namespace, a jak nie znajdzie to poszuka czy są jakies nastepne dalsze rozwinięcia tego BBB, i znajdzie następne rozwinięcie i zaprzyjaźni A z klasą X w linii *2 - dobrze to rozumuję ? (bo tak jest wg Comeau).

Dopiero jakby nie znalazł w całym pliku zadnego dalszego BBB, to zaprzyjaźnił by z X globalnym - tak ?

quetzalcoatl napisał(a)
  • kwalifikowane sa rozumiane jako twarde wiazania do podanych konkretnych definicji lezacych na konkretnej podanej sciezce, patrzac od samej gory drzewa nazw

Co znaczy 'patrzac od samej gory' ?

jak mamy:

friend class A::B::C::X::Y::Z::klasa_zaprzyjazniona;

to przeciez kazdy wie, że zaprzyjaźniamy z klasą 'klasa_zaprzyjazniona', bo poczatek sciezki idzie od lewej strony, a nie z 'A' - bo poczatek sciezki nie idzie od prawej strony.

Chodziło Ci o tą oczywistą rzecz ;-P ?

quetzalcoatl napisał(a)

X, Cos - sa kwalifikowane
Swiat - jest niekwalifikowany

No ale mamy identyfikator kwalifikowany Swiat::X; i rozbijamy go na kawałeczki, skoro piszesz, że Swiat nie jest kwalifikowany ?

To żeby identyfikator kwalifikowany 'był w pełni kwalifikowany' to przed każdą nazwą w nim (przed kazdym 'kawałeczkiem') musi być :: ?

Czyli tutaj musiało by to wygladac tak - ::X; ?

quetzalcoatl napisał(a)

-> to znaczy ze lokalizacja identyfikatora 'Swiat' jest luzna i zostanie dopasowana kontekstowo
--->> to znaczy, ze Swiat::X != Ah::X !!!!

A wczesniej, pod moim cytatem pisales: "Moze tak wygladac, ale nie musi. ". W tym przykładzie tak nie wygląda. A kiedy by Swiat::X był == Ah::X ?


Dzięki wielkie z gory za odpowiedzi ;)

0

dość padnięty jestem, więc sorry za mało konkretną i luźną gadkę:

post1: "dlaczego tak jest?" - primo: napisalem sie, naprodukowalem, a nie zajrzalem do spec c++.. wydaje mi sie ze jesli drazyc temat dalej, warto to zrobic. niestety nie mam teraz czasu, wiec spada na Ciebie :)) a tak gdybajac ogolnie, w tej chwili, przychodzi mi do glowy tylko jedna rzecz: ten przyklad wydaje sie pokazywac, ze friend po prostu olewa klauzule using. moze jest jakis powod na to? friend jest do uzytku w deklaracjach klas, w plikach .hpp ktore beda #include'owane, otaczane innymi namespace/using etc. moze uwzglednianie usinga tworzyloby bardzi wiele nieprzewidzianych punktow zczepien nazw? nie wiem.. spec sie klania, moze bedzie wyjasnione:|

post1: "ona jest juz znana" - ee.. w CIALACH metod, wszystkie members danej klasy sa juz znane. ale using to nie cialo! using to fragment deklaracji. nie chcesz chyba powiedziec, ze ponizszy kod jest poprawny:

class WTF
{      abcd  pole;  // ?
        struct abcd { int x; }

        friend zzz::BLE; // ????
        struct zzz { void BLE(){} };
}

post2: "(bo tak jest wg Comeau)."
tak, dokladnie tak. szuka w 'kontekscie', czyli namespace BBB, czyli potem-zadeklarowane BBB powinno dostac dostep.

post2: "Dopiero jakby nie znalazł w całym pliku zadnego dalszego BBB, to zaprzyjaźnił by z X globalnym - tak ?"
nie.
po pierwsze, żeby w ogóle próbował spinac z zewnetrznym identyfikatorem, zewnetrzny identyfikator musialby byc juz znany, czyli hen przed deklaracja frienda, musialbys dac forward declaration typu X na poziomie namespace-default.
po drugie, zwroc uwage ponownie na przykald 5a+5b, w nim masz (przynajmniej pod g++:) ) ze czy z fwddecl, czy bez, friend NIE poszuka w outer namespace! specjalnie nazywalem gdzieniegdzie defaultnamespace jako namespace"" albo namespace::, jest on "topmost", ma nazwe wlasna - ::/"" choc "" mylace jest.. i wszystkie inne namespace sie w nim zawieraja. zeby WYJSC z identyfiaktorem POZA kontekst, czyli aktualny namespace, trzeba uzyc konkrentego wiazania do czegos - np. ::X, ale wtdy to bedzie znaczyc ze X musi byc w default i kropka. i w dodatku bedzie wymagalo aby X bylo fwddeclowane, albo zdefiniwoane wyzej..

post2: "Co znaczy 'patrzac od samej gory' ?"
przepraszam, to byl skrot myslowy.. sama gora miala oznaczac zapis "::klasa", czyli nazwa w pelni kwalifikowana, rozwiazywana od samego czubka drzewa nazw, czyli od defaultnamespace blahblah..

post2: "friend class A::klasa_zaprzyjazniona;/ to przeciez kazdy wie, że zaprzyjaźniamy z klasą 'klasa_zaprzyjazniona'"
nie w tym rzecz.
problem tkwi w tym, ze w tym zapisie ktory teraz podales, B,C,X,Y,Z,klasa - sa kwalifikowane i "twardo umiejscowione", zas A - nie jest. jest kontekstowe. ono nie jest zaczepione i moze zostac sparowane z roznymi rzeczami w zaleznosci od (......). przez to, patrzac globalnie, nawet przy tak dlugim ciagu ::-::-::, "klasa_zaprzyjazniona" tez nie jest scisle umiejscowiona - kompilator moze sie nie domyslic ze sadziles ze A jest na ::A..

post2: " (przed kazdym 'kawałeczkiem') musi być :: ?" / "::X; "
tak / tak
dopiero przy ::X jest w 100% jasne, ze chodzi o X-wCos-wSwiat-wDefaultNamespace. bez pierwszego ::, Swiat mogloby (i zostaloby) potraktowane jako lokalne lub w -aktualnym- namespace

post2: "A kiedy by Swiat::X był == Ah::X"
abstrahujac od frienda i using, przyklad moglby wygladac tak:

 // !=
ns Ah
    ns Oh
        ns Uh
        {
             class Swiat{ class Cos { class X{}; } }  //A
             class Ah{class Oh{class Uh{class Swiat{ class Cos { class X{}; } }  //B

             class Z
             { 
                Swiat::Cos::X pole; // typ A
                Ah::Oh::Uh::Swiat::Cos::X pole2;  // typ B, inny typ
                ::Ah::Oh::Uh::Swiat::Cos::X pole2;  // typ A
             }
        }
 // ==
ns Ah
    ns Oh
        ns Uh
        {
             class Swiat{ class Cos { class X{}; } }
             class Z
             { Swiat::Cos::X pole;
                Ah::Oh::Uh::Swiat::Cos::X pole2;  // ten sam typ
             }
        }

wydaje mi sie ze mozna je przeniesc rownie dobrze na problem frienda, gdyz w obu w/w przypadkach wszystkie typy sa jawnie zdefiniowane wczesniej i friend powinien je wylapac bez problemu. glowy nie dam, jestem po parunastu godzinach maratonu z idotycznym driverem do SC na PSION'ie i kiesko mysli mi sie.. dlatego napisalem przyklady na fieldach. jezeli interesuje Cie konkretnie problem ==/!= identyfikatorow kwa/niekwalif. ORAZ frienda, prosze, sprobuj samemu NIEwymyslac, A:skonstruowac takie przyklady w oparciu np. o w/w/w przyklady 1-..-5ab-..-6.. sadze ze sie da, moze nawet one juz tam sa..

0

Dzięki wielkie za pomoc :) Ale wrócę tu kiedy będzie mi to potrzebne, bo na razie tylko tak rozmyślałem teoretycznie. Na razie nie sposób tego ogarnąć...

PS. W Javie i w C# albo innych jezykach tez występują takie @#$^*(@#$ problemy ?

0

PS. W Javie i w C# albo innych jezykach tez występują takie @#$^*(@#$ problemy ?

Nie. ;]

0

Nie, takich problemów nie ma (są inne), ale nie ma także ficzerów - ale są w zamian inne ficzery.. słowem, mimo zawadiackiego uśmiechu piętro wyżej po 'nie' - zdecydować o lepszości języka, serio, jest ciężko

edit: języka. nie platformy/runtime/libraries/blah..

1 użytkowników online, w tym zalogowanych: 0, gości: 1