2014-11-16 11 views
19
class x 
{ 
    void xx() {} 
}; 

class y 
{ 
    friend void x::xx(); 
}; 

Wynika to z błędu jakDlaczego funkcja członka PRIVATE nie może być funkcją przyjaźni innej klasy?

error: friend function 'xx' is a private member of 'x'

Dlaczego nie mogę zadeklarować prywatna funkcja member aby być przyjacielem innej klasy?

+0

możliwy duplikat [Deklaracja przyjaciela w C++ - różnica między publicznym a prywatnym] (http://stackoverflow.com/questions/6407691/ friend-declaration-in-c-difference-between-public-and-private) – ha9u63ar

+10

@ hagubear Zdecydowanie nie jest to duplikat tego. – hvd

+0

Pytasz, dlaczego język na to nie pozwala? W pewnym momencie ktoś pomyślał (co zrozumiałe), że to zły pomysł. – juanchopanza

Odpowiedz

12

[class.friend]/9:

A name nominated by a friend declaration shall be accessible in the scope of the class containing the friend declaration.

Powód jest dość prosty; private członkowie przestrzegać jasną i określoną zasadę:

A member of a class can be

  • private ; that is, its name can be used only by members and friends of the class in which it is declared.

który osoby prywatne być nazwany w deklaracji wewnątrz niepowiązanych klas naruszałoby to zasadę: umożliwia inną klasę zależeć od szczegółów implementacji bez wyraźnie dopuszczone do . Staje się to problematyczne, na przykład podczas zmiany nazwy, typu lub podpis prywatnego członka, lub całkowitego usunięcia; to nie powinno naruszać interfejsu tej klasy.

ten można obejść poprzez całokształt x przyjacielem y:

class x { 
    void xx() {} 
}; 

class y { 
    friend x; 
}; 

Demo.

+0

Może nie rozumiem tego pytania, ale czy nie powinno to być odwrotnie, to znaczy, zrobić "Y" przyjaciela 'x'? W twoim przykładzie 'y' nie uzyskał dostępu do prywatnych metod' x'. –

+1

@IvanSmirnov Zamierzeniem oryginalnego fragmentu było umożliwienie członkowi 'x' dostępu do prywatnych danych' y'. – Columbo

+0

Ah, prawda, nie najbardziej intuicyjna rzecz. Dzięki, rozumiem. –

13

Pomysł utworzenia x::xxprivate powinien być taki, że x::xx jest szczegółem implementacji, na który inne klasy nie powinny polegać. Nie oznacza to tylko, że x::xx nie może być wywołany przez inne klasy, to znaczy, a raczej powinno to oznaczać, że np. zmiana nazwy na x::xx na x::xy nie powinna przerwać niczego poza samą klasą i przyjaciółmi klasy.

W twoim przypadku, zmiana nazwy x::xx do x::xy spowodowałoby klasę y wystąpienie błędu, mimo że nie jest przyjacielem x.

Sposobem na uniknięcie to zrobić y przyjacielem x, dzięki czemu można uzyskać dostęp xy „s private członków. Następnie może zadeklarować x::xx jako friend.

(Uwaga: bardziej bezpośrednia odpowiedź na pytanie "Dlaczego kompilator nie pozwala na to?" To "Ponieważ standard na to nie pozwala.", Co naturalnie prowadzi do następującego pytania: "Dlaczego standard nie pozwalają na to? ". Próbuję odpowiedzieć na to kolejne pytanie.)

+0

Mogę mieć funkcję wirtualnego członka, która jest prywatna i nadpisana w podklasie. Zmiana nazwy tej wirtualnej funkcji w klasie bazowej może coś złamać, prawda? ' – Columbo

+1

Podoba mi się rozróżnienie, na jakie pytanie * właśnie * odpowiadasz. –

+0

@ Columbo Masz rację. To jedna z różnic między "to znaczy" i "powinno oznaczać". :) – hvd

Powiązane problemy