#include<iostream>
using namespace std;
class B;
class A; // 此行可不加,这里加此行是因为下面举例子有用
class A {
public:
A(int n = 0): num(n) {} // 构造函数
friend void sum_1(A &a, B &b); // 全局函数 sum_1
void sum_2(B &b); // 成员函数 sum_2
private:
int num;
};
class B {
public:
B(int n = 0) : num(n) {} // 构造函数
friend void sum_1(A &a, B &b); // 全局函数 sum_1
friend void A::sum_2(B &b); // 友元函数 A::sum_2
private:
int num;
};
// 全局函数
void sum_1(A &a, B &b) {
int sum = a.num + b.num; // 访问了两个对象的私有变量
cout << a.num << " + " << b.num << " = " << sum << endl;
}
// 友元函数
void A::sum_2(B &b) {
int sum = num + b.num; // 访问了参数对象的私有变量
cout << num << " + " << b.num << " = " << sum << endl;
}
int main() {
A a(1);
B b;
sum_1(a, b); // 调用全局函数
a.sum_2(b); // 调用a的成员函数
system("PAUSE");
return 0;
}
class B;
编译器会报错:error C2061: 语法错误: 标识符“B”
本例中,先对类 B 进行了声明,但是没有定义。因为在类 A 的定义中,出现的函数 sum_1
和 sum_2
均要用到类B 名,所以必须事先声明“B”是一个类名,这样编译器才不会因为不知道”B“是什么而报错。
本例中,若将 A、B 类的定义顺序调换,其余均不变,则出现语法错误
#include<iostream>
using namespace std;
class B;
class A; // 此行可不加,这里加此行是因为下面举例子有用
class B { // A、B类的定义顺序变了
.../*中间的语句不变*/
};
class A {
.../*中间的语句不变*/
};
.../*后面的语句不变*/
在友元函数的实现中,会出现
这说明B类中没有成功的把A类的成员函数sum_2声明为自己的友元函数。 道理很很简单,和第1点很相似。若先定义B类,那么我们观察一下B类定义中的如下语句
friend void A::sum_2(B &b); // 友元函数 A::sum_2
该语句通过类名加域运算符,将A类的成员函数sum_2声明为友元函数。等等,是不是发现了什么,这是A类根本还没有定义,编译器只知道A是一个类名,A中具体有什么全然不知。如此,那么这一个语句当然无效咯!
likeqc
ends
原文:https://www.cnblogs.com/likeqc/p/13933692.html