C++中的友元函数和友元类

C++中的友元函数主要应用于以下场景:

友元函数

第一种场景

代码中有一个全局函数,该函数想要去访问某个类的成员变量(该类的成员变量是private的,且该类并未提供任何获取获取私有成员变量的public方法),这时候可以在这个类中把该全局函数声明为友元函数,这样这个全局函数就具备了能够获取那个类的私有成员变量的资格。

例:通过友元函数获取Person类的各项字段信息:

main.cpp

复制代码
#include <iostream>
#include "Person.h"

void showPersonInfo(Person *person)
{
    std::cout << person->m_name << ", age is: " << person->m_age << ", sex is: " << person->m_sex << std::endl;
}
int main()
{
    Person *person = new Person("xp.chen", 20, 1);
    showPersonInfo(person);
    delete person;

    getchar();
    return 0;
}
复制代码

person.h

复制代码
#pragma once
class Person
{
private:
    char *m_name;
    int m_age;
    int m_sex;
public:
    Person(char *name, int age, int sex);
    ~Person();
public:
    friend void showPersonInfo(Person *person); // 将showPersonInfo()函数声明为友元函数
};
复制代码

person.cpp

复制代码
#include "Person.h"

Person::Person(char *name, int age, int sex)
:m_name(name)
, m_age(age)
, m_sex(sex)
{
}

Person::~Person()
{
}
复制代码

运行结果:

xp.chen, age is: 20, sex is: 1

第二种场景

在某个类(假设为A类)有一个成员函数,该成员函数想去访问另一个类(假设为B类)中的私有成员变量。这时候则可以在第二个类(B类)中,声明第一个类(A类)的那个成员函数为友元函数,这样第一个类(A类)就可以访问第二个类(B类)的私有成员变量了。

例:打印Person类的详细信息(包含姓名,年龄,性别,省份,城市,街道)

Person.h

复制代码
#pragma once

class Address;
class Person
{
private:
    char *m_name;
    int m_age;
    int m_sex;
public:
    Person(char *name, int age, int sex);
    ~Person();
public:
    void showDetailInfo(Address *addr); // 用于打印包含姓名,年龄,性别,省份,城市,街道的详细信息
};
复制代码

Address.h

复制代码
#pragma once
#include "Person.h"

class Address
{
private:
    char *m_province;
    char *m_city;
    char *m_district;

public:
    Address(char *province, char *city, char *district);
    ~Address();
public:
    friend void Person::showDetailInfo(Address *addr);
};
复制代码

Address.cpp

复制代码
#include "Address.h"

Address::Address(char *province, char *city, char *district)
:m_province(province)
, m_city(city)
, m_district(district)
{
}

Address::~Address()
{
}
复制代码

Person.cpp

复制代码
#include <iostream>
#include "Address.h"

Person::Person(char *name, int age, int sex)
:m_name(name)
, m_age(age)
, m_sex(sex)
{
}

void Person::showDetailInfo(Address *addr)
{
    std::cout << "Name: " << m_name << ", Age: " << m_age << ", Sex: " << m_sex << ", Province: " << addr->m_province << ", City: " << addr->m_city << ", District: " << addr->m_district << std::endl;
}

Person::~Person()
{
}
复制代码

main.cpp

复制代码
#include <iostream>
#include <stdlib.h>
#include "Address.h"

int main()
{
    Person *person = new Person("xp.chen", 20, 1);
    Address *address = new Address("JS", "KS", "ZhengRoad");
    person->showDetailInfo(address);

    delete person, address;
    system("pause");
    return 0;
}
复制代码

运行结果:

Name: xp.chen, Age: 20, Sex: 1, Province: JS, City: KS, District: ZhengRoad

友元类

友元类则更简单,可以将一个类(类A)声明成另一个类(类B)的友元类,那么类A就拥有了能够访问类B所有成员的资格,包括private, protected, public的。

例:将上述例子中的Address.h修改成:

复制代码
#pragma once
#include "Person.h"

class Address
{
private:
    char *m_province;
    char *m_city;
    char *m_district;

public:
    Address(char *province, char *city, char *district);
    ~Address();
public:
    friend class Person;
};
复制代码

声明类Person是类Address的友元类,再次运行程序:

Name: xp.chen, Age: 20, Sex: 1, Province: JS, City: KS, District: ZhengRoad

需要注意的是:

  • 友元的关系是单向的而不是双向的。如果声明了类 B 是类 A 的友元类,不等于类 A 是类 B 的友元类,类 A 中的成员函数不能访问类 B 中的 private 成员。
  • 友元的关系不能传递。如果类 B 是类 A 的友元类,类 C 是类 B 的友元类,不等于类 C 是类 A 的友元类。

另外,有的编译器也可以不写class关键字,也就是说可以写成:friend Person, 不过为了兼容性还是建议写上。

 



如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   夜行过客  阅读(3460)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
点击右上角即可分享
微信分享提示