Tutorial Study Image

C++ 友元函数


2023年5月28日, Learn eTutorial
1057

一个类的私有数据不能被另一个类的非成员函数访问。有时我们希望两个类共享一些函数和数据成员。在这种情况下,我们可以将函数声明为这些类的**友元**,从而允许它访问类的私有和受保护数据成员。本教程将通过简单的例子涵盖 C++ 中友元函数的含义、为什么需要友元函数以及友元函数有哪些特殊特性等重要概念。

什么是友元函数?

简介

**友元函数**是一个外部提供的函数,它可以访问类成员的受保护和私有数据。这意味着一个函数,它不是一个类的成员,但它有权访问该类的受保护和私有成员,被称为**友元函数**。

函数模板、成员函数、类或类模板,或者函数,都可以被视为友元。如果一个类是友元,那么该类的每个成员也都是友元。友元函数是典型的外部函数,被赋予了特殊的访问权限,它们不是类成员。

有时,允许某个类访问另一个类的私有成员是有益的。例如,LinkedList 类可能被允许访问 Node 的私有成员。

例如

程序演示了友元函数的概念


#include<iostream>
using namespace std;

class A {
    int x;
    public:

        A() {
            x = 50;
        }
    friend class B; //friend class
};

class B {
    public: void display(A & t) {
        cout << endl << "value of x=" << t.x;
    }
};

main() {
    A _a;
    B _b;
    _b.display(_a);
    return 0;
}
 

输出


value of x=50

在这种情况下,类 B 已在类 A 中被声明为友元。因此,B 是类 A 的友元。类 A 的私有成员可供类 B 访问。

C++ 中的友元函数

友元函数: 友元函数可以被赋予特定的权限来访问私有和受保护成员,就像友元类一样。

友元函数可以是:

  1. 另一个类的成员
  2. 一个全局函数
  • 在 C++ 中,有一种特殊的函数称为友元函数,尽管它不被视为类的成员,但它有能力访问类的私有和受保护数据。
  • 友元函数似乎是一个非成员函数或类的普通函数,它在类内部使用“friend”关键字声明为友元。当一个函数被声明为友元时,它被授予所有访问权限。
  • 关键字“friend”只出现在友元函数的函数声明中,而不出现在函数定义中。
  • 调用友元函数时,不使用点运算符和对象名称。它可能接受对象作为参数,其值需要被访问。
  • 类的任何部分,例如 public、private 或 protected,都可以用来声明友元函数。

语法


class <class_name>    
{    
    friend  <return_type> <function_name>(arg list);  
};
 

语法解释

  • friend: 关键字“friend”表示此函数只是一个友元函数。
  • returnType: 函数的返回类型是 returnType。
  • functionName: 它是已添加为类友元的函数的名称。
  • arg list: 给定的参数列在 arg list 中。

示例

使用友元函数确定两个数字中哪个更大的程序


#include<iostream>
using namespace std;

class Largest {
    int x, y, z;
    public:
        void set_data();
    friend void find_max(Largest);
};

void Largest::set_data() {
    cout << "Please Enter the First Number:";
    cin >> x;
    cout << "Please Enter the Second Number:";
    cin >> y;
}

void find_max(Largest t) {
    if (t.x > t.y)
        t.z = t.x;
    else
        t.z = t.y;

    cout << "Maximum Number is\t" << t.x;
}

main() {
    Largest l;
    l.set_data();
    find_max(l);
    return 0;
}
 

输出


Please Enter the First Number: 50
Please Enter the Second Number:100
Maximum Number is : 100

为什么我们需要友元函数?

在某些特殊情况下,我们需要友元函数,这些情况下需要直接访问类的私有数据,而无需使用该类的对象。考虑以下类:Director 和 Doctor。对于这些类的每个对象,我们可能希望使用 gross_salary 函数。该函数不一定属于这些类中的一个。

它们也用于运算符重载,因为它们更直观。友元函数方法可以用于重载常用的二元算术运算符。

友元函数的一些特殊特性

  • 友元函数的范围与它被指定为友元的类不同。因此,该功能根本不局限于单个类。
  • 友元函数可以是另一个类的成员,甚至是一个不在类范围内的函数。
  • 在不改变其含义的情况下,友元函数可以在类的私有或公共部分声明。
  • 由于友元函数在类的范围之外,因此不能使用类对象调用它们。
  • 友元函数可以像任何其他成员函数一样被调用,无需对象。
  • 友元函数可以接受类对象作为参数。
  • 友元函数不能直接访问成员名称。必须在每个成员名称中使用对象名称和点运算符。例如,Doctor.pay,其中 pay 似乎是对象的名称。

友元类

友元类可以使用它被声明为友元的另一个类的数据、成员和函数。当我们需要授予特定类访问不同类的私有和受保护成员的权限时,就会使用它们。

所有被声明为另一个类的友元类的成员函数都转换为该友元类的友元函数。为了连接这些类,需要友元函数。

友元类的语法


class S; //forward declaration

class P{
  // Other Declarations
  friend class S;
};

class S{
  // Declarations
};
 

在上面的示例中,类 S 被认为是类 P 的友元。因此,类 S 可以访问类 P 成员的私有数据。这并不意味着类 P 的成员可以访问类 S 成员的私有数据。在实体正式定义之前,编译器通过前向声明被告知其存在。

为了让编译器知道类 S 存在,我们使用前向声明声明了它,从而允许我们在类 P 中使用类 S 对象。

需要注意的是,类的友元关系不是继承的或相互的,除非我们明确这样设置。这意味着,因为类 S 是类 P 的友元,所以类 S 也将是类 P 的子类的友元。

演示友元类的程序


#include <iostream>
using namespace std;

// forward declaration
class ClassY;

class ClassX {
  int digit1;

  // friend class declaration
  friend class ClassY;

  public:
      // constructor to initialize num1 to 10
      ClassX() : digit1(10) {}
};

class ClassY {
    int digit2;

    public:
        // constructor to initialize num2 to 5
        ClassY() : digit2(5) {}

    // member function to multiply num1
    // from ClassX with num2 from ClassY
    int multiply() {
        ClassX m;
        return m.digit1 * digit2;
    }
};

int main() {
    ClassY n;
    cout << "Multiplication: " << n.multiply();
    return 0;
}
 

输出


Multiplication :50

在上面的程序中,声明了两个类 X 和 Y。ClassX 将 ClassY 作为友元类。因此,ClassY 可以访问 ClassX 的成员函数。我们在 ClassY 中开发了一个名为 multiply() 的函数,它返回数字 1 和 2 相乘的结果。

我们可以在 ClassY 内部创建 ClassX 的对象,因为 ClassY 是一个友元类。提前声明 ClassY 是可以实现的。