程序1:顺序定义
class A{ //第一步:定义A
void function();
}
void A::function()
{
//这里假设function中不牵涉到对B类的操作
}
class B{ //第二步:定义B
friend void A::function(); //把A中的function定义为B的友元函数
}
程序2:非顺序定义
class A; //向前引用声明:我们仅仅声明,暂时不定义A
class B{
friend void A::function(); //因为此处要用到A,所以有了第一句class A,否则编译器根本不知道A是什么玩意
}//但其实是这句话其实是错的,因为A都尚未定义,我们有怎么能访问他的成员函数呢
//声明class A的是告知程序这个类的名字可以用,定义的作用是规定类的实现细节
class A{
void function();
}
void A::function()
{
//这里假设function中不牵涉到对B类的操作
}
B类中用到了A类,那么就要提前告诉编译器,有两种办法:
1.在A类定义在B类之前
2.如果先定义B类,那么就要向前引用声明,在B类定义语句前加上class A
那么问题来了,我们让A类的成员函数function()声明为B类的友元函数是为什么?
我们是为了A类的function函数中能操作B类中的成员啊!
先说程序1,我们在定义function函数的时候,class B都还没有定义,我们都不知道里面有什么,又谈何操作?!所以我们只能先定义class A,但是里面的function函数就只能暂时做个声明,紧接着把class B给定义了,再写class A的function函数的定义
程序1:改进
#include <iostream>
using namespace std;
class B; //声明B类的存在
class A{ //第一步,定义A类
public:
void function(B& b); //因为用B类定义了形式参数,这是声明B类的存在的原因
};
class B{
private:
int i = 0;
public:
friend void A::function(B& b); //此时已经只知道了A类的细节,所以可以访问他的函数定义
};
void A::function(B& b) //此时知道了B类的实现细节,可以访问他的数据成员
{
b.i++;
cout << b.i;
}
int main()
{
A a;
B b;
a.function(b);
return 0;
}
程序2:改进
#include <iostream>
using namespace std;
class A; //声明A类的存在
class B{
private:
int i = 0;
public:
friend void A::function(B& b); //但是不知道A类的细节,所以访问出错了
};
class A{
public:
void function(B& b);
};
void A::function(B& b)
{
b.i++;
cout << b.i;
}
int main()
{
A a;
B b;
a.function(b);
return 0;
}
那么问题有来了,通常我们会把每一个类封装到一个头文件之中,这两个类耦合这么严重,
A.h
#ifndef A_H
#define A_H
class B;
class A{
public:
void function(B& b);
};
#endif // A_H
B.h
#ifndef B_H
#define B_H
#include "A.h"
class B{
private:
int i = 0;
public:
friend void A::function(B& b);
};
#endif // B_H
A.cpp
#include<iostream>
#include "A.h"
#include "B.h"
void A::function(B& b)
{
b.i++; std::cout << b.i;
}
main.cpp
int main()
{
A a;
B b;
a.function(b);
return 0;
}