C++ 友元

友元是C++中用于打破封装的一种机制,允许指定的函数或类访问类的私有和保护成员。友元函数不是类的成员,但可以在其内部直接访问类的私有和保护成员。而友元类的所有成员函数都能访问另一个类的私有和保护成员。友元的使用虽然方便了代码编写,但也可能影响到数据安全性。理解友元的声明和使用是C++面向对象编程中的重要概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行。这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书写的麻烦。友元提供了在类的成员函数外部直接访问对象的私有成员(实际上所有成员都可访问,包括 protected)的功能,朋友是值得信任的,所以可以对他们公开一些自己的隐私。友元分为两种:友元函数和友元类

友元函数

在定义一个类的时候,可以把一些函数(包括全局函数和其他类的成员函数)声明为“友元”,这样那些函数就成为该类的友元函数,在友元函数内部就可以访问该类对象的私有成员了。

  1. 友元函数写在想要访问私有成员的类的内部;
  2. 友元函数不受在想访问私有成员的类中位置影响,不被 private, public 和 protected 约束;
  3. 友元函数本质上是全局函数或者另一个类的成员函数
  4. 不能将其他类的私有成员函数声明为某个类的友元函数;
  5. 将一个类 A 的成员函数作为另一个类 B 的友元函数时不能在 B 中直接定义友元函数,因为友元函数并不属于此类,全局函数也不能在其中声明,只能在类外声明,即友元函数在想访问私有成员的类中声明函数原型,在另一个类中声明不带 friend 的函数原型,在类外定义
  6. 友元函数必须在参数表中显式指明要访问私有成员的类对象

定义

全局函数声明为友元函数

friend  返回值类型  函数名(参数表);

类的成员函数声明为友元函数

friend  返回值类型  其他类的类名::成员函数名(参数表);

实现

类的成员函数声明为友元函数

三部曲:

  1. 增加前向声明,并定义一个需要实现友元函数的类,在类中声明友元函数的不带 friend 的函数原型;
  2. 声明友元函数原型;
  3. 类外补充定义(被访问私有成员的类定义之后)。
#include<iostream>
using namespace std;

/******* 第一步:前向声明 ********/
class B;   // 1 处使用类 B,但是 B 尚未定义,所以提前声明

class A{
public:
    // 错误,此时 B 还不完整,没有定义
    // void show(B b){
    //     cout<<b.name<<endl;
    // };
    void show(B b);   // 1
};

/******** 第二步:声明友元函数原型 ********/
class B{
public:
    B() {name = "aaron";x = 10;}
    friend void A::show(B b);  // 友元函数原型
private:
    string name;
protected:
    int x;
};

/******* 第三步:类外定义 *******/
void A::show(B b){
    cout<<b.name<<" "<<b.x<<endl;
}

int main(){
    B b;
    A a;
    a.show(b);
}

全局函数声明为友元函数

两部曲:

  1. 类内声明友元函数原型
  2. 类外定义
#include<iostream>
using namespace std;

/********** 第一步:类内声明友元函数原型 *********/
class B{
public:
    B() {name = "aaron";}
    friend void show(B b);  // 友元函数原型
private:
    string name;
};

/******* 第二步:类外定义 *******/
void show(B b){
    cout<<b.name<<endl;
}

int main(){
    B b;
    show(b);
}

友元类

一个类 A 可以将另一个类 B 声明为自己的友元,类 B 的所有成员函数就都可以访问类 A 对象的私有成员。在类定义中声明友元类的写法如下:

定义

在想访问私有成员的类的任意位置声明

friend  class  类名;

使用

友元类中先声明一个想访问私有成员的类的对象,然后将其作为数据成员即可访问。

#include<iostream>
using namespace std;

class B;

class A{
public:
    int x;
    A() {x = 1;c = 'a';s = "good";}
protected:
    char c;
private:
    string s;
    friend class B;
};

class B{
public:
    void showX(){
        cout<<a.x<<endl;
    }
    void showC(){
        cout<<a.c<<endl;
    }
    void showS(){
        cout<<a.s<<endl;
    }
private:
    A a;
};

int main(){
    B b;
    b.showX();
    b.showC();
    b.showS();
}

区别与联系

  1. 友元函数必须传入一个想访问私有成员的类对象作为参数,因此友元类和另一个类都需要创建对象;
  2. 友元类将被访问类对象作为数据成员,不需要额外创建被访问类对象,也不用传递参数。
  3. 类的私有函数不能作为友元函数,友元类的私有成员函数不能访问被访问类的私有成员。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值