定义类X,类Y,在类X中声明类Y的成员函数g()为类X的友元函数
常见的几种错误写法及原因:
错误写法1
class Y;
class X
{
public:
X(int i) :i(i) {}
friend void Y::g(X& object);
void print()
{
cout << i;
}
private:
int i;
};
class Y
{
public:
void g(X& object)
{
object.i += 1;
}
};
结果编译器显示 Y 的成员函数g()无法访问类X的私有成员i:
原因:在类X中声明Y的成员函数为友元时,此时类Y还没有定义。第一行的class Y,仅作为声明告诉编译器有这个类,而不知道这个类究竟包含了什么。所以在类X中声明成员函数g()为友元的语句无效
错误写法2
通过对刚刚写法的分析,我们很容易想到把类Y的定义放到类X前以消除这个错误,但是这样可行吗?
class X;
class Y
{
public:
void g(X& object)
{
object.i += 1;
}
};
class X
{
public:
X(int i) :i(i) {}
friend void Y::g(X& object);
void print()
{
cout << i;
}
private:
int i;
};
此时编译器显示,类Y的成员函数g()仍然无法访问类X的私有成员
原因:与上一个错误类似。在类Y中定义g()函数时,编译器并不知道g()作为了类X的友元,因为此时类X还没有定义,而只是在第一行作了声明。
正确写法:
class X;
class Y
{
public:
void g(X& object);
};
class X
{
public:
X(int i) :i(i) {}
friend void Y::g(X& object);
friend class Z;
friend void h(X& object);
void print()
{
cout << i;
}
private:
int i;
};
void Y::g(X& object)
{
object.i += 1;
}
通过把成员函数g()的定义写在类外,可以避免出现以上两种情况
总结:
编译器的编译顺序是从上至下,像这种相互使用的用法,只能先声明,最后统一实现。避免了在这一方使用那一方时出现那一方还未定义而报错的情况。
补充:
这是否说明类的友元函数只能在类外定义呢? 答案是 否定的:当定义在类Y里的友元函数不访问类x的私有成员时,这样定义没问题。