#include <iostream>
using namespace std;
class x;
class y
{
public:
void f(x);
};
class x
{
private:
int i;
public:
friend void y::f(x);
friend void g(x, int);
};
void y::f(x x)
{
x->i = 47;
}
void g(x xx,int i)
{
xx->i = i;
}
int main()
{
return 0;
}
//编译错误
运行这段代码会出现编译错误的情况,这是因为c++编译器要求在引用任一变量之前必须声明,所以class y必须在它的成员y::f(x)被申明为class x的一个友元之前声明,但y::f(x)要被申明,class x又必须先声明,这样编译器根本无法正确操作,另外编译器也不知道y::g(x)这个函数的全部定义以确定它的大小以及如何传递它。
解决方法:在y::f(x*)引用一个x对象的地址。因为编译器知道如何传递一个地址,这一地址的大小是一定的,而不管被传递的对象类型大小。如果试图传递整个对象,编译器就必须知道x的全部定义以确定它的大小以及如何传递它。
看下面修改过的代码:
#include <iostream>
using namespace std;
class x;
class y
{
public:
void f(x*);
};
class x
{
private:
int i;
public:
friend void y::f(x*);
friend void g(x*, int);
};
void y::f(x* x)
{
x->i = 47;
}
void g(x* xx,int i)
{
xx->i = i;
}
int main()
{
return 0;
}
//编译成功
通过传递x的地址,编译器允许程序员在声明y::f(x*)之前做一个不完全的类型指定。这一点是在class x的申明时完成的,这里仅仅告诉编译器,有一个叫x的class,所以当它被引用时不会产生错误,只要程序员的引用不涉及名字以外的信息。