Gdy kompilator rozpoczyna kompilacji kodu (zwykle od góry) i napotka tę linię:
friend void B::fB(A& a);
- w tym momencie, kompilator nie ma pojęcia o informacji typu B więc zgłasza błąd ("B": nie jest nazwą klasy lub przestrzeni nazw).
przez deklarację klasy B, kompilator wie o typie B jest klasą z wyprzedzeniem do faktycznej deklaracji ze wszystkimi członkami.
bieg poniżej kod do przodu po deklaracji klasy 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){};
};
Still błędu !!!
ponieważ deklaracja przekazania jest tylko deklaracją identyfikatora, którego programista nie podał jeszcze pełnej definicji. więc kompilator potrzebuje pełnej definicji B przed klasą A.
Uwaga: definicja klasy A zależy od typu B, a także od definicji B (tj. B :: fB), więc sama deklaracja przekazania nie może zostać rozstrzygnięta, pełna definicja klasy B musi zdefiniować zanim klasy A.
4 uruchomić ten kod
////////
class B
{
public:
void fB(A& a){};
void fB2(A& a){};
};
class A
{
public:
friend void B::fB(A& a);
void fA(){}
};
Wciąż błąd !!!
ponieważ funkcje składowe klasy B fB & fB2 mając argumentów typu A, ale kompilator nie ma pojęcia o informacje o typ tak przez przodu deklaracji klasy A, możemy pozwolić kompilator wie o informacje typu A. Uwaga: klasa definicja B zależy tylko od rodzaju NOT członków A tak, że przód deklaracji krok resolve 4.
- ostateczny kod
////// //////////////////
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 Ćwiczenie:
// 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;
}
Ale jeśli w fB (A & A) używam dostęp do zmiennej w na przykład a.variable; byłoby to nielegalne, ponieważ A nie zostało jeszcze zdefiniowane. – ipkiss
@ipkiss tak, ponieważ wtedy potrzebowałbyś pełnej definicji, jeśli to w deklaracji klasy nagłówka. Ale jeśli zrobiłeś to w oddzielnym pliku implementacyjnym, możesz dołączyć pełną deklarację A. – juanchopanza