none
clase amiga (friend) no se hereda en las derivadas RRS feed

  • Pregunta

  • Hola, 

    Les expongo el problema mediante código recortado. La lógica es que A es una clase que opera sobre objetos derivados de B, y cada objeto derivado tiene una referencia a esta para controlar algunos parámetros. 

    class A
    {
    friend class B;
    protected:
    void Add(B *obj);
    void Del(B *obj);
    }

    class B
    {
    protected:
    A &ref;
    }

    class C : B
    {
    void f() { ref.Add(this); }; // 'A::Add': No se puede tener acceso al miembro protected miembro declarado en la clase A
    }

    ¿Se puede realizar esto de una forma limpia o tengo que añadir todas las derivadas de B como friend de A o bien implementar métodos en B que llamen a A para ser llamados desde C?

    Un saludo,

    Jordi Ortola Lorente

    • Editado marranxo martes, 16 de octubre de 2012 10:52
    martes, 16 de octubre de 2012 10:15

Respuestas

  • Quería apuntar, por si alguien se encuentra con el mismo problema, como lo he solucionado: 

    class A
    {
    friend class B;
    protected:
    void Add(B *obj);
    void Del(B *obj);
    }

    class B
    {
    protected:
    A &ref;
    void AddToA() { ref.Add(this); };
    void DelFromA() { ref.Del(this); };
    }

    class C : B
    {
    void f() { AddToA(); };
    }

    Es un poco sucio, dado que hay que hacer un wrapper en la clase base B de cada método de la clase A que se quieran usar en las derivadas de B (C) , pero aún así es lo mejor que se me ha ocurrido. La otra opción era quitar los scopes de protected a A pero me parece más feo, al igual que añadir en A cada derivada de B como friend. 

    Las respuestas limpias y adecuadas siguen siendo bienvenidas.

    Un saludo,

    Jordi Ortola Lorente


    • Marcado como respuesta marranxo martes, 16 de octubre de 2012 15:40
    martes, 16 de octubre de 2012 14:38

Todas las respuestas

  • Quería apuntar, por si alguien se encuentra con el mismo problema, como lo he solucionado: 

    class A
    {
    friend class B;
    protected:
    void Add(B *obj);
    void Del(B *obj);
    }

    class B
    {
    protected:
    A &ref;
    void AddToA() { ref.Add(this); };
    void DelFromA() { ref.Del(this); };
    }

    class C : B
    {
    void f() { AddToA(); };
    }

    Es un poco sucio, dado que hay que hacer un wrapper en la clase base B de cada método de la clase A que se quieran usar en las derivadas de B (C) , pero aún así es lo mejor que se me ha ocurrido. La otra opción era quitar los scopes de protected a A pero me parece más feo, al igual que añadir en A cada derivada de B como friend. 

    Las respuestas limpias y adecuadas siguen siendo bienvenidas.

    Un saludo,

    Jordi Ortola Lorente


    • Marcado como respuesta marranxo martes, 16 de octubre de 2012 15:40
    martes, 16 de octubre de 2012 14:38
  • Pues no veo la necesidad de ocultar A::Add() y por lo tanto, forzarse a usar friend.  Recuerde que friend es un transgresor contra el principio de encapsulación de la programación orientada a objetos.  En lo personal evaluaría el por qué de tener Add() como protected y consideraría hacerlo public.

    En cuanto a su problema original, pues es normal.  A confía en B (friend class B) pero eso no significa que confíe en cualquier derivado de B.  Su forma de solucionar esto es válida:  B está diciendo que confiará en todos sus derivados al proveer un método protected que da acceso a A.


    Jose R. MCP
    Code Samples

    martes, 16 de octubre de 2012 15:19
    Moderador
  • La necesidad se la explicaré en un momento, y es que cuando das un proyecto por terminado y te piden extensiones de última hora te las tienes que arreglar realizando este tipo de cosas en muchos casos, intentando ser lo más limpio posible. 

    Por cierto, también sería válido que la clase base B implementara un método A& GetARef() { return ref; };

    Gracias por la aclaración y un saludo.


    martes, 16 de octubre de 2012 15:32