当编译器开始编译代码时(通常从顶部开始)并遇到这一行:
friend void B::fB(A& a);
-
此时,编译器不知道 B 的类型信息,因此会引发错误(“B”:不是类或命名空间名称)。
-
通过类 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;
}