Men.h
#pragma once
#include "iostream"
class A
{
//-- 声明类B是类A的友元类,则B可以访问类A的所有成员了。
friend class B;
private:
//public:
int data;
};
class B
{
public:
void callBAF(int i, A& a){
a.data = i;
std::cout << "a.data=" << a.data << std::endl;
}
};
class Men
{
//-- 声明该普通的非成员函数是本类的友元函数,它就能访问该类的所有成员
friend void funcFriendGlobal(const Men& tempMen);
public:
//-- 类外部可以直接调用,const 对象和非const对象都可以调用。 但const对象只能调用const函数
//void chengYuanHanShuFunc() const;
protected:
private:
//-- 私有,只能在本类 的成员函数中 被当前对象调用
void chengYuanHanShuFunc() const;
//-- 报错 a type qualifier is not allowed on a nonmember function 非成员函数不能使用限定符const
//friend void chengYuanHanShuFunc() const;
};
Men.cpp
#include "stdafx.h"
#include "Men.h"
#include "iostream"
using namespace std;
void Men::chengYuanHanShuFunc() const {
cout << "Men::ChengYuanHanShu" << endl;
}
global.h
#pragma once
#include "Men.h"
//-- 为了使得项目更加清晰,可把它提出来单独放置一个cpp中
void funcFriendGlobal(const Men& tempMen);
global.cpp
#include "stdafx.h"
#include "global.h"
//-- 为了使得项目更加清晰,可把它提出来单独放置一个cpp中
void funcFriendGlobal(const Men& tempMen){
//const对象调用const函数
tempMen.chengYuanHanShuFunc();
}
C.h
#pragma once
//class D;
#include "D.h" //-- 因为使用到了D:: 这样的命名空间,所以必须包含D.h的头文件
class C
{
//-- 可以声明D是C的友元类, D可以用C的所有。
//friend class D;
//-- 可以声明D中的这个成员函数 是C类的友元函数
friend void D::testCallCFunc(int i, C& c);
public:
private:
int cData;
void funcTestFriend(int i);
};
C.cpp
#include "stdafx.h"
#include "C.h"
#include "iostream"
using namespace std;
void C::funcTestFriend(int i){
cData = i;
cout << "测试C类的友元函数 data = " << cData << endl;
}
D.h
#pragma once
//#ifndef __C__
//#define __C__
//#include "C.h"
//#include "C.h" 不能引入C.h的头文件, 因为C.h的头文件包含了#include D.h
class C; //-- 类声明,仅仅声明了有D这样的一个类型,因为可能类C的在D之后(也就是说 在D.h中没有#include "C.h", 如果D.h开头#include "C.h",那么类C就定义在类D之前了)
//-- 而在本.h文件中 类D的定义又用到了类A, 所以这里先做一个类声明,这样编译就不会出错。
class D
{
public:
void testCallCFunc(int i, C& c); //-- 只能是C& c 或C* c而不能是 C c,C c 会报错。
};
//#endif
/* 来自百度
两个头文件相互包含会导致超前引用的问题,所谓超前引用是指一个类型在定义之前就被用来定义变量和声明函数。发生这种情况是无法编译通过的,不过可以采取一些手段解决该问题
超前引用导致的错误有以下几种处理办法:
1) 使用类声明
在超前引用一个类之前,首先用一个特殊的语句说明该标识符是一个类名,即将被超前引用。其使用方法是:
a) 用class ClassB;声明即将超前引用的类名
b) 定义class ClassA
c) 定义class ClassB;
d) 编制两个类的实现代码。
上述方法适用于所有代码在同一个文件中,一般情况下,ClassA和ClassB分别有自己的头文件和cpp文件,这种
方法需要演变成:
a) 分别定义ClassA和ClassB,并在cpp文件中实现之
b) 在两个头文件的开头分别用class ClassB;和class ClassA;声明对方
c) 在两个cpp文件中分别包含另外一个类的头文件
NOTE:这种方法切记不可使用类名来定义变量和函数的变量参数,只可用来定义引用或者指针。
2) 使用全局变量
由于全局变量可以避免超前引用,不用赘述。我的习惯是,把类对象的extern语句加在该类头文件的最后,大家喜欢怎样写那都没有什么大问题,关键是保证不要在头文件中胡乱包含。
3) 使用基类指针。
这种方法是在引用超前引用类的地方一律用基类指针。而一般情况下,两个互相引用的类并不涉及其基类,因此不会造成超前引用。
*/
D.cpp
#include "stdafx.h"
#include "D.h"
#include "C.h" //-- 注意要加入此头文件,这样才能编译通过
void D::testCallCFunc(int i, C& c){
c.cData = i;
c.funcTestFriend(i);
}
Main.cpp
// ConsoleApplicationC++14.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "Men.h"
#include "global.h"
#include "D.h"
#include "C.h"
//-- 为了使得项目更加清晰,可把它提出来单独放置一个cpp中
//void funcFriendGlobal(const Men& tempMen){
// //const对象调用const函数
// tempMen.chengYuanHanShuFunc();
//}
int _tmain(int argc, _TCHAR* argv[])
{
Men m;
funcFriendGlobal(m);
A a;
B b;
b.callBAF(33, a);
C c;
D d;
d.testCallCFunc(888, c);
return 0;
}