友元函数
友元的三种类型
- 全局函数做友元
- 类作友元
- 成员函数做有元
特点
- 友元函数不是成员函数,所以友元函数没有this指针。
- 它可以访问类的私有(private)和保护(protected)成员。
- 友元函数通常定义在类外,但在类中声明为友元。
- 注意友元的定义要么放在最开始,要么放在最后。
友元函数
在类的定义中,可以使用friend关键字来声明一个友元函数。
class MyClass
{
private:
int privateData;
public:
MyClass(int data) : privateData(data) {}
// 声明友元函数:告诉编译器printPrivateData是全局函数,也是MyClass类的友元函数。
friend void printPrivateData(const MyClass& obj);
};
// 定义友元函数
void printPrivateData(const MyClass& obj)
{
std::cout << "Private data: " << obj.privateData << std::endl;
}
友元类
友元类的声明在类的声明中,实现在该类外。
class A
{
public:
A(int _a):a(_a) {};
friend class B;
private:
int a;
};
class B
{
public:
void print(A &obj)
{
cout << obj.a << endl;
}
};
int main()
{
A a(10);
B b;
b.print(a);
}
类的友元关系没有继承性。
假如类B是类A的友元,类C继承于类A,那么友元类B是没办法直接访问类C的私有或保护成员。
class A
{
private:
int a_data;
public:
A(int data) : a_data(data) {}
friend class B; // 类B是类A的友元
};
class B
{
public:
// 由于B是A的友元,它可以访问A的私有成员
void printA(const A& obj)
{
std::cout << obj.a_data << std::endl;
}
// 但B不能访问C的私有成员,除非C显式地将B声明为其友元
};
class C : public A
{
private:
int c_data;
public:
C(int aData, int cData) : A(aData), c_data(cData) {}
// 如果我们希望B能够访问C的私有成员,我们需要在C中声明B为友元
// friend class B; // 如果取消注释这行代码,B就能访问C的私有成员了
};
int main() {
A a(10);
B b;
b.printA(a); // 正确:B可以访问A的私有成员
C c(20, 30);
b.printC(c); // 错误(假设有这样的函数):B不能访问C的私有成员,除非C声明B为友元
return 0;
}
友元关系没有传递性。
假如类B是类A的友元,类C是类B的友元,那么友元类C是没办法直接访问类A的私有或保护成员,也就是不存在“友元的友元”这种关系。