当编译器开始编译代码(通常从顶部)并遇到这一行:
friend void B::fB(A& a);
此时,编译器不知道 B 的类型信息,因此会引发错误( 'B' : is not a class or namespace name )。
通过类 B 的前向声明,编译器在其与所有成员的实际声明之前就知道 B 的类型是 Class。
在 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 类之前对 B 进行完整定义。
注意:A 类的定义依赖于 B 的类型,也依赖于 B 的定义(即 B::fB),所以单靠前向声明无法解析,完整的 B 类定义需要在 A 类之前定义。
4 运行这段代码
////////
class B
{
public:
void fB(A& a){};
void fB2(A& a){};
};
class A
{
public:
friend void B::fB(A& a);
void fA(){}
};
还是错误!!!
因为 B 类成员函数 fB 和 fB2 具有 A 类型的参数,但编译器不知道 A 的类型信息,所以通过 A 类的前向声明,我们可以让编译器知道 A 的类型信息。注意:B 类定义仅依赖于A 的类型不是 A 的成员,因此 A 的前向声明解决了步骤 4。
- 最终代码
//////////////////////
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 练习:
// 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;
}