2009-11-05 32 views
6

Como la amistad entre clases no se hereda en C++, ¿cuál es la mejor manera de "falsificarla"?¿Heredando amistad en C++?

Estaba pensando en exponer la interfaz privada de la clase amiga a través de métodos protegidos en la clase base heredada, pero eso implica tener que escribir (y mantener) la misma interfaz dos veces.

¿Hay alguna otra manera?

Respuesta

6

El uso de una clave es una posible solución.

La idea es que se puede desbloquear las operaciones sólo si tiene una clave ... sino un ejemplo vale miles de palabras por lo que vamos a inmersión:

// 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); 
}; 

La cuestión de ser copia de la llave construible está hasta discusión No veo lo que puedes ganar previniéndolo.

Otra ventaja es que puede tener varias teclas, dependiendo del método al que desee acceder, de esta manera otorga una amistad "parcial", y sus amigos "parciales" no pueden meterse con sus partes privadas, a pesar del famoso reclamo!

EDITAR:

Este método se llama Limited amistad, y se discutió en comp.lang.c++.moderated.

La principal ventaja de este método en comparación con Private Interface, es el acoplamiento flojo, ya que solo son necesarias las declaraciones avanzadas.

+0

Dado que 'Key' es una clase vacía, ¿tiene realmente algún efecto stack-wize/memory-wize, o el compilador lo trata como" azúcar sintáctico "solamente? – sold

+2

Una clase vacía aún 'pesa' algo (al menos un byte de datos, a menudo más debido a problemas de alineación). Hay una optimización llamada Optimización de Base Vacía, que consiste en heredar de la clase vacía para evitar incurrir en esta sobrecarga. Por lo tanto, podría elegir tener 'NeedAccess' heredando en privado de' Key' y devolver una referencia en lugar de una copia ... pero una referencia también 'pesa' algo. –

0

No estoy seguro si esto no es lo que ya está pensando pero aquí hay un ejemplo Virtual Friend

2

Los hijos de la clase con frinedship que preguntarnos no deben hacer los padres el acceso para ellos.

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 para su ejemplo. :-) – Tenner

Cuestiones relacionadas