2009-04-18 17 views
6

Me doy cuenta de que hay muchas preguntas con respecto a las clases de amigos en C++. Mi pregunta, sin embargo, está ligada a un escenario específico. Dado el siguiente código, ¿es apropiado usar un amigo de esa manera?C++ friend classes

class Software 
{ 
    friend class SoftwareProducer; 

    SoftwareProducer* m_producer; 
    int m_key; 
    // Only producers can produce software 
    Software(SoftwareProducer* producer) : m_producer(producer) { } 

public: 
    void buy() 
    { 
     m_key = m_producer->next_key(); 
    } 
}; 

class SoftwareProducer 
{ 
    friend class Software; 

public: 
    Software* produce() 
    { 
     return new Software(this); 
    } 

private: 
    // Only software from this producer can get a valid key for registration 
    int next_key() 
    { 
     return ...; 
    } 
}; 

Gracias,

Saludos,

Respuesta

8

Claro, eso es perfectamente razonable. Básicamente lo que has hecho es muy similar a un patrón de fábrica. No veo ningún problema con eso ya que su código parece implicar que cada objeto de Software debe tener un puntero a su creador.

Aunque, generalmente puede evitar tener clases de "Administrador" como SoftwareProducer, y solo tiene métodos estáticos en el Software. Dado que parece probable que haya solo un SoftwareProducer. Algo como esto quizá:

class Software { 
private: 
    Software() : m_key(0) { /* whatever */ } 
public: 
    void buy() { m_key = new_key(); } 
public: 
    static Software *create() { return new Software; } 
private: 
    static int new_key() { static int example_id = 1; return example_id++; } 
private: 
    int m_key; 
}; 

A continuación, sólo se puede hacer esto:

Software *soft = Software::create(); 
soft->buy(); 

Por supuesto, si usted planea en tener más de un objeto SoftwareProducer, a continuación, lo que ha hecho parece apropiado.

1

Creo que hacer SoftwareProducer como amigo del Software es aceptable, pero no veo ninguna razón por la cual el Software deba ser amigo de la clase SoftwareProducer. Es una dependencia innecesaria entre ellos. Puede tomar la tecla como un argumento constructor para la clase Software. También es posible que desee hacer que el destructor de la clase Software sea privado para que nadie, excepto SoftwareProducer, pueda destruirlos.

+0

He hecho de Software un amigo de SoftwareProducer para tener acceso al método next_key que es privado. – Alex

+0

¿No es al revés? Para permitir que el constructor privado del Software sea llamado desde SoftwareProducer, debe hacer que SoftwareProducer sea un amigo del Software, que como dije tiene sentido. Pero también hizo que Software sea un amigo de SoftwateProducer para que se pueda llamar al método next_key() que considero innecesario. – Naveen

+0

¿De qué otra forma podría una instancia de software acceder al método next_key de su productor si es privada? – Alex

1

No hablaré sobre el tema de la amistad, pero a mí me suelen molestar las dependencias cíclicas. El software depende de SoftwareProducer que depende del Software ... Intentaré refactorizar.

También tenga en cuenta que la relación de amistad abre las partes internas a todas las instancias de la otra clase. Eso es tanto como decir que su comentario en next_key es falso:

Haciendo next_key privada no permite ninguna clase de llamar, pero una vez que abra hasta Software clase, cualquier software puede llamar next_key en todos los SoftwareProducers.

+0

+1, técnicamente es correcto re: next_key() - cualquier Software puede llamarlo - pero tampoco es un riesgo de seguridad ya que tiene control sobre La definición y la amistad del software no son transitivas ni heredadas. También es bueno evitar las dependencias cíclicas cuando sea posible, pero a veces son necesarias. ¿Se puede proponer una mejor alternativa en este caso? –

+0

De hecho, no me gustan las dependencias cíclicas, es por eso que publiqué esta pregunta. Estoy de acuerdo en que es un ejemplo intrincado (purposamente). – Alex

+1

La mayoría de las dependencias cíclicas se pueden eliminar definiendo interfaces y dependiendo de ellas. Ahora, una vez que comience de esa manera, usar private + friend para controlar el acceso será mucho más difícil. Probablemente movería la operación de compra del Software a un Distribuidor/Tienda externo o incluso a un Desarrollador de Software, y pondría el control de acceso en la lógica en lugar del sistema de tipo. –