2012-05-11 21 views
13

De acuerdo con el libro C++ Primer, el autor mencionó que podemos especificar una función de miembro de clase como amigo de otra clase, en lugar de la clase completa (página 634).¿Especifica una función de miembro de clase como amigo de otra clase?

Entonces, he probado este código:

class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){} 
}; 
class B 
{ 
public: 
    void fB(A& a){}; 
    void fB2(A& a){}; 
}; 

sólo quería el FB() para ser amigo de la clase A, no la clase entera B. Pero el sobre el código producido un error: 'B' : is not a class or namespace name. (Estoy usando Visual C++ 2005)

Respuesta

14

trate de poner la definición B antes de las a:

class A; // forward declaration of A needed by B 

class B 
{ 
public: 
    // if these require full definition of A, then put body in implementation file 
    void fB(A& a); // Note: no body, unlike original. 
    void fB2(A& a); // no body. 
}; 

class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){} 
}; 

A necesita la definición completa de B. Sin embargo, B necesita saber acerca de A, pero no necesita la definición completa, por lo que necesita la declaración directa de A.

+0

Pero si en fB (A & A) Yo uso una para acceder a una variable en, por ejemplo, a.variable; eso sería ilegal porque A no se había definido aún. – ipkiss

+1

@ipkiss sí, porque entonces necesitaría la definición completa si lo hace en la declaración de la clase de encabezado. Pero si lo hizo en un archivo de implementación separado, puede incluir la declaración completa de A. – juanchopanza

2

Para que esto funcione, la definición completa de B debe conocerse antes de la definición de A.

Así adelante declare A, ya B no necesita el tipo completo, y cambiar las definiciones en torno a:

class A; 
class B 
{ 
public: 
    void fB(A& a){}; 
    void fB2(A& a){}; 
}; 
class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){} 
}; 
0

en primer lugar reenviar la clase A, por lo que es visible en la clase de definición B. luego defina la clase A que contenga una función amiga de la clase B.

0

Primero que todo, antes de usar un nombre de clase en particular, tendrá que declararlo primero. Por lo tanto, necesitará una declaración anticipada de la Clase B, ya que la está utilizando en la Clase A antes de que la Clase B haya sido declarada originalmente.

En segundo lugar, necesitará definir las funciones (que están usando variables de ambas clases, aquí las funciones de amigo) después de que ambas clases hayan sido definidas. O bien podemos enfrentar errores.

Por ejemplo

#include<iostream> 

using namespace std; 

class alpha1; 

class alpha2 
{ 
    public: 

     void put_bata(int a,int b); 
}; 

void alpha2 :: put_bata(int a,int b) 
{ 
    alpha1 net; 

    net.roll=a; 

    net.id=b; 

    net.get_data(); 
} 

class alpha1 
{ 
    int roll; 

    int id; 

    public: 

     void get_data(void) 
     { 
      cout<<roll<<endl<<id<<endl; 
     } 

     friend void alpha2 :: put_bata(int a,int b); 
}; 

int main() 
{ 
    alpha2 gamma; 

    gamma.put_bata(5,6); 

    return 0; 
} 

nos mostrará errores como put_bata intenta acceder rollo y la identificación antes de ser definido, incluso si tuviéramos una declaración adelantada de la clase, pero el código que figura a continuación se acaba de funcionar bien.

#include<iostream> 

using namespace std; 

class alpha1; 

class alpha2 
{ 
    public: 

     void put_bata(int a,int b); 
}; 

class alpha1 
{ 
    int roll; 

    int id; 

    public: 

     void get_data(void) 
     { 
      cout<<roll<<endl<<id<<endl; 
     } 

     friend void alpha2 :: put_bata(int a,int b); 
}; 

void alpha2 :: put_bata(int a,int b) 
{ 
    alpha1 net; 

    net.roll=a; 

    net.id=b; 

    net.get_data(); 
} 


int main() 
{ 
    alpha2 gamma; 

    gamma.put_bata(5,6); 

    return 0; 
} 
0

@juanchopanza @ipkiss En cuanto al problema que no se puede acceder a los miembros de datos de un interior fB (A & a) porque A no está definido todavía. En lugar de definirlo en un archivo separado e incluirlo, puede simplemente definir la función fB (A & a) después de la definición de clase A para que fB (A & a) pueda ver los datos miembros de A.

2

Cuando el compilador empieza a leer el código (por lo general de la parte superior) y se encuentra con esta línea:

friend void B::fB(A& a);

a continuación, el compilador no entiende qué quiere decir con esto B::. Incluso si ha definido esta clase más adelante en el código, pero el compilador no lo sabe.Por lo tanto, generalmente es bueno hacer una declaración de clase directa (class Name;) si la definición reside más adelante en el código.

2

Cuando el compilador comienza compilar el código (por lo general de la parte superior) y se encuentra con esta línea:

friend void B::fB(A& a); 
  1. en este punto, el compilador no sabe nada de información tipo de B por lo que arroja un error ('B': no ​​es una clase o nombre de espacio de nombres).
  2. por la declaración directa de la clase B, el compilador sabe sobre el tipo de B es la Clase por adelantado a su declaración real con todos los miembros.

  3. ejecución de código a continuación después de la declaración de avance de la clase B.

///////////////

class B; 
class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){}; 
}; 
class B 
{ 
public: 
    void fB(A& a){}; 
    void fB2(A& a){}; 
}; 

Aún error !!!

porque la declaración directa es solo una declaración de un identificador para el cual el programador aún no ha dado una definición completa. por lo que el compilador necesita una definición completa de B antes de la clase A.

Nota: la definición de clase A depende del tipo de B y también la definición de B (es decir, B :: fB) para que la declaración directa no pueda resolverse, complete la definición de clase B tiene que definir antes de la clase A.

4 ejecuta este código

////////

class B 
{ 
public: 
    void fB(A& a){}; 
    void fB2(A& a){}; 
}; 
class A 
{ 
public: 
    friend void B::fB(A& a); 
    void fA(){} 
}; 

Aún error !!!

debido a las funciones miembro de la clase B fB & FB2 tener argumentos de tipo A, pero el compilador no tiene ni idea sobre información de tipo de un modo mediante declaración delante de la clase A, podemos dejar que el compilador sabe acerca de información de tipo A. Nota: Clase definición B sólo depende del tipo a no los miembros de una manera que la declaración de avance de un paso determinación 4.

  1. código final

////// //////////////////

class A; // forward declaration of A needed by B 
class B 
{ 
public: 
    void fB(A& a); 
}; 

class A 
{ 
    int i; 
public: 
    friend void fA(A& a); //specifying function fA as a friend of A, fA is not member function of A 
    friend void B::fB(A& a); //specifying B class member function fB as a friend of A 
}; 

// fA is Friend function of A 
void fA(A& a) 
{ 
    a.i = 11; // accessing and modifying Class A private member i 
    cout<<a.i<<endl; 
} 

// B::fB should be defined after class A definition only because this member function can access Class A members 
void B::fB(A& a) 
{ 
    a.i = 22; // accessing and modifying Class A private member i in Class B member function fB 
    cout<<a.i<<endl; 
} 

int main() 
{ 
    A a; 
    fA(a); // calling friend function of class A 

    B b; 
    b.fB(a); // calling B class member function fB, B:fB is friend of class A 

    return 0; 
} 

6 Ejercicio:

// Cyclic dependency 
#include<iostream> 
using namespace std; 

class A; 

class B 
{ 
public: 
    void fB(A& a); 
    friend void A::fA(B& b); //specifying class A's member function fA as a friend of B 
}; 

class A 
{ 
    int i; 
public: 
    void fA(B& b); 
    friend void B::fB(A& a); //specifying class B's member function fB as a friend of A 
}; 

int main() 
{ 
    return 0; 
} 
+0

Entonces, ¿cómo resuelve el ejercicio? –

+0

@BrunoMartinez - No hay una solución perfecta para esto porque ambos son cíclicamente dependientes de la definición completa de cada uno. Mi intención de con este caso especial fue resaltar la importancia de desacoplar entidades en el diseño de software y obtener más claridad sobre la función Friend mientras trabajamos en esto. Supongo que ya sabrá que la opción posible para esto es crear una función amiga común – SrinivasPaladugu

Cuestiones relacionadas