2009-11-05 17 views
6

Ponieważ przyjaźń klasowa nie jest dziedziczona w C++, jaki jest najlepszy sposób na jej "sfałszowanie"?Dziedziczenie przyjaźni w C++?

Myślałem o odsłonięciu prywatnego interfejsu klasy przyjaciela za pomocą metod chronionych w odziedziczonej klasie bazowej, ale to powoduje konieczność napisania (i utrzymania) tego samego interfejsu dwukrotnie.

Czy istnieją inne sposoby?

Odpowiedz

6

Użycie klucza jest możliwym rozwiązaniem.

Chodzi o to, że można odblokować operacje tylko jeśli masz klucza ... ale przykładem jest wart tysiące na słowie więc niech nurkowania:

// Step 1: The key 
class NeedAccess; 

namespace details { class Key { friend NeedAccess; Key() {} }; } 

// Step 2: NeedAccess 
class NeedAccess 
{ 
protected: 
    static details::Key GetKey() { return details::Key(); } 
}; 

// Step 3: The big one 
class BigOne 
{ 
public: 
    void lockedMethod(details::Key); 
}; 

Sprawa klucz jest kopią constructable jest do dyskusji. Nie widzę, co możesz zyskać, zapobiegając temu.

Inną korzyścią jest to, że możesz mieć kilka kluczy, w zależności od metody, do której chcesz uzyskać dostęp, w ten sposób przyznajesz "częściową" przyjaźń, a twoi "częściowi" przyjaciele nie mogą sobie poradzić z prywatnymi częściami, pomimo sławne roszczenie!

EDIT:

Ta metoda nazywana jest ograniczona Przyjaźń i dyskutowano na comp.lang.c++.moderated.

Główną zaletą tej metody w porównaniu z Private Interface jest luźne połączenie, ponieważ potrzebne są tylko deklaracje forward.

+0

Ponieważ 'Key' jest pustą klasą, czy faktycznie ma jakieś efekty stack-wize/memory-wize, czy też kompilator traktuje to tylko jako" syntaktic-sugar "? – sold

+2

Pusta klasa nadal "waży" coś (co najmniej bajt wartości danych, często więcej z powodu problemów z wyrównaniem). Istnieje optymalizacja o nazwie Empty Base Optimization, która polega na dziedziczeniu z pustej klasy, aby uniknąć poniesienia tego obciążenia. Możesz więc wybrać opcję "NeedAccess" dziedziczącą prywatnie z 'Key' i zwracającą referencję zamiast kopii ... ale odwołanie również" waży "coś. –

0

Nie wiem, czy to nie jest to, co masz już myśli o ale oto Virtual Friend Przykład

2

Dzieci z klasy z frinedship zadać tam rodzica zrobić dostęp do nich.

class CrustyNeighbour 
{ 
    private: 
     friend class Bob; 
     void useWiFi(std::string const& data); 
}; 

class Bob 
{ 
    protected: 
     useWifi(CrustyNeighbour& neighbour,std::string const& data) 
     { neighbour.useWiFi(data);} 
}; 

class Mary: public Bob // Bob's offspring 
{ 
    void playHalo(WifiOwner& owner) // WifiOwner derived from CrustyNeighbour 
    { 
     useWifi(owner,gameData); // use wifi via his/her parent who access to eighbours wifi 
    } 
}; 
+0

+1 dla Twojego przykładu. :-) – Tenner