C++ 友元函数

在 C++ 中,使用 friend 修饰的函数,称为友元函数。类的私有成员(private)和只能在本类中访问,类的保护成员(protected)只能在本类或者子类中访问,但类的友元函数可以访问类的私有成员和保护成员。

记住:类的友元函数是定义在类外部,但有权访问类的所有私有成员和保护成员。另外,尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。

声明友元函数

在 C++ 中,友元函数使用 friend 关键字修饰。例如,下面示例中的 func() 函数就是一个友元函数。

class ClassName
{
public:
    friend void func();
};

void func()
{
    // do something
}

友元函数示例

请看下面示例:

#include <iostream>
using namespace std;

class Student
{
public:
    Student(string name, int age)
    {
        this->name = name;
        this->age = age;
    }

    void sayHello() const
    {
        cout << "I am " << this->name << " and i am " << this->age << " years old!" << endl;
    }

private:
    string name;
    int age;
};

// 非成员函数
void show(Student stu)
{
    cout << "Call Show, Name = " << stu.name << ", Age = " << stu.age << endl;
}

int main(void)
{
    Student stu("GetIoT.tech", 3);
    show(stu);
    return 0;
}

使用 g++ main.cpp 命令编译该示例,出现如下错误:

main.cpp: In function ‘void show(Student)’:
main.cpp:26:40: error: ‘std::string Student::name’ is private within this context
   26 |     cout << "Call Show, Name =" << stu.name << " Age = " << stu.age << endl;
      |                                        ^~~~
main.cpp:19:12: note: declared private here
   19 |     string name;
      |            ^~~~
main.cpp:26:65: error: ‘int Student::age’ is private within this context
   26 |     cout << "Call Show, Name =" << stu.name << " Age = " << stu.age << endl;
      |                                                                 ^~~
main.cpp:20:9: note: declared private here
   20 |     int age;
      |         ^~~

这是因为我们在类的外面调用 show() 函数访问类的私有成员,程序当然会报错。

现在,我们在 Student 类中将 show() 函数声明为友元函数,修改程序如下:

class Student
{
public:
    Student(string name, int age)
    {
        this->name = name;
        this->age = age;
    }

    void sayHello() const
    {
        cout << "I am " << this->name << " and i am " << this->age << " years old!" << endl;
    }

    friend void show(Student stu);

private:
    string name;
    int age;
};

使用 g++ main.cpp && ./a.out 命令编译运行以上示例,输出结果如下:

Call Show, Name = GetIoT.tech, Age = 3

Leave a Reply