一:友元函数。这是个函数
Men.h
#pragma once
#ifndef __MEN__
#define __MEN__
#include "Human.h"
class Men : public Human
{
friend void func(const Men& tempmen);
private:
void funcmen2() const;
};
#endif // !__MEN__
Men.cpp
#include "Men.h"
void Men::funcmen2() const
{
cout << "void Men::funcmen2()" << endl;
}
Func.h
#pragma once
#ifndef __FUNC__
#define __FUNC__
#include "Men.h"
void func(const Men& tempmen);
#endif // !__FUNC__
Func.cpp
#include "Func.h"
void func(const Men& tempmen)
{
tmpmen.funcmen2();
}
注:friend void func(const Men& tempmen)不能算真正的声明,但有的编译器也会依据声明;最好将void func(const Men& tempmen)函数本身声明一次;
只要让函数func成为类Men的友元函数,那么func这个函数就能够访问类Men的所有成员(成员变量,成员函数),private、public、protected。
Men men;
func(men)
总结:友元函数 func(){}:是个函数,通过声明为某个类Men的友元函数,它就能访问这个类 Men 的所有成员,包括private、public、protected。
二:友元类
类可以把其他的类定义成友元类。如果 “你是” “我的” 友元类,那么就可以在"你的"成员函数中访问"我的"所有成员 包括private,public,protected。
修改类A,让类C成为类A的朋友(也就是让类C成为类A的友元类)
class C; //类C声明
class A{
friend class C; //这就是友元类的声明,虽然此时类C没有定义,但是系统不会报错
private:
int data;
};
class C{
public:
void callCAF(int x, A &a){
A.data = x; //正常情况下这个不行
std::cout << a.data << std::endl;
}
};
A a;
C c;
c.callCAF(3,a); //返回结果是 3
注意:每个类都负责控制自己的友元类和友元函数,所以:
<1>友元关系不能被继承。类C成为类A的友元类,但不能说类C的子类是类A的友元类;
<2>友元关系是单向的,比如上边类C是类A的友元类,但这并不表示类A是类C的友元类;
<3>友元关系没有传递性的,比如B是类A的友元类,类C是类B的友元类,这并不代表类C是类A的友元类。
三:友元成员函数
写这种友元成员函数,必须要注意代码组织结构,因为这里边有声明和定义这种依赖关系在里边。
A.h
#pragma once
#ifndef __A__
#define __A__
#include <iostream>
#include "B.h"
class A
{
friend void B::callABF(int i, const A& a);
private:
int data = 250;
};
#endif // !__A__
B.h
#pragma once
#ifndef __B__
#define __B__
#include <iostream>
//#include "A.h" 不可以,会报错,不论B.cpp中是否声明A.h。
using namespace std;
class A;
class B
{
public:
void callABF(int i, const A& a);
};
#endif // !__B__
B.cpp
#include "B.h"
#include "A.h" //若将A.h的声明定义在B.h中,通过引用B.h来包含A.h会报错,不太理解。
void B::callABF(int i,const A& a)
{
i = a.data;
cout << "a.data: " << i << endl;
}
//注意:
//在上述B.cpp代码中,若将A.h的声明定义在B.h中,通过引用B.h来包含A.h会报错,不太理解。
Test.cpp
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
int main()
{
A a;
B b;
b.callABF(100, a);
cin.get();
return 0;
}
总结:friend
优点:允许在特定情况下某些非成员函数访问类的private、protected成员,从而提出友元这么一个概念,使访问private、protected成员更灵活。
缺点:这也就破坏了类的封装性,降低了类的可靠性和可维护性。