【温故而知新-01】C++友元小记

一、开篇

友元的描述的对象是类和函数,函数可以是类的成员函数和非成员函数。当我们需要访问一个类的非公有成员时(private、protected),这时候友元就可以派上用场啦。

二、友元知识点

在实际使用中,友元可以是:函数和类。我们只需要使用friend关键字在类中对他们进行声明即可。

友元声明只能出现在类定义的内部,可以在类定义中的任意位置进行友元声明。但是,在实际使用中,最好在类定义的开始或者结尾处集中进行友元的声明,这样比较规范!!!

友元的声明仅仅指定了访问的权限,但是本质上不是一个函数声明,所以,如果我们需要使类的用户(类示例、派生类)能够调用某个友元函数,那么就需要在友元声明之外再对在这里插入代码片该函数进行一次声明。在实际使用中,通常把友元的声明和类本身放置在同一个头文件中

注意:许多编译器并没有强制限定友元函数必须在使用之前在类的外部进行声明。但是,在类的外部进行函数声明是一种比较保险的作用。

友元不是类的成员,所以,他不受所在区域访问控制级别的约束(public、private、protected对他无效)

三、友元的三种使用场景

友元存在三种使用场景:友元类友元成员函数友元非成员函数

(3-1)友元类

这这样一个场景:两个学生student_A和student_B,其中student_B是student_A的好朋友,所以希望能够访问student_A的私有数据,所以在设计中在student_A的类定义中将student_A声明为其友元类,这样则可以在student_B中访问student_A的私有数据成员。参考代码如下:

#include <iostream>

class student_B;
/**
 * @brief student_A
 */
class student_A{
    friend student_B;

private:
    int m_age = 25;
    std::string m_name = "xiaoZhang";

    std::string getStudentAName()
    {
        return m_name;
    }

    int getStudentAAge()
    {
        return m_age;
    }

};


/**
 * @brief student_B
 */
class student_B{
public:
    int getStudentInfo(student_A &stu)
    {
        std::cout<<"stu_A name:"<<stu.m_name<<"\r\n"<<"stu_A age : "<<stu.m_age<<std::endl;
    }

private:
    int m_age = 22;
    std::string m_name = "xiaoLi";
};


int main() {
    student_B stu_b;

    student_A stu_a;

    //通过studentB 访问studentA的私有数据成员
    stu_b.getStudentInfo(stu_a);

    return 0;
}

每个类负责控制自己的友元类和友元函数。友元关系不具有传递性。

(3-2)友元成员函数

可以在类中只把一个类的成员函数声明为友元函数。例如:有两个学生Student_A和Student_B,将Student_B的获取学生信息getInfo()声明为Student_A学生的友元函数,那么Student_B的getInfo()则可以访问Student_A学生的私有数据成员。参考代码如下:

#include <iostream>

/* 声明student_A */
class student_A;
int getStudentInfo(student_A &stu);

/* 定义student_B类 */
/**
 * @brief student_B
 */
class student_B{
public:
    /* 在student_B中先声明getStudentInfo()函数,但是不定义他 */
    int getStudentInfo(student_A &stu);

private:
    int m_age = 22;
    std::string m_name = "xiaoLi";
};

/* 定义student_A类 */
/**
 * @brief student_A
 */
class student_A{
    /* 声明student_B类的getStudentInfo()函数为student_A类的友元 */
    friend int student_B::getStudentInfo(student_A &stu);

private:
    int m_age = 25;
    std::string m_name = "xiaoZhang";

    std::string getStudentAName()
    {
        return m_name;
    }

    int getStudentAAge()
    {
        return m_age;
    }
};

/* 定义student_B类的getStudentInfo()成员函数 */
int student_B::getStudentInfo(student_A &stu) {
    std::cout<<"stu_A name:"<<stu.m_name<<"\r\n"<<"stu_A age : "<<stu.m_age<<std::endl;

    return 0;
}


int main() {
    student_B stu_b;

    student_A stu_a;

    /* 通过studentB 访问studentA的私有数据成员 */
    stu_b.getStudentInfo(stu_a);

    return 0;
}

在友元的三种使用方法中,将类的成员函数作为某一个类的友元函数,在程序的结构编写上需要格外注意代码的顺序,否则将会非常容易出错。以以上代码为例,必须按照如下的方式对代码进行结构上的处理:

  • 首先定义student_B类,其中声明getStudentInfo()函数,但是不能定义该函数。除此之外,还需要在student_B类定义之前先声明student_A类,因为在getStudentInfo()中使用到了student_A。

  • 接着,定义student_A类,在该类定义中先对student_B类的getStudentInfo()进行友元声明。

  • 最后定义getStudentInfo()函数,这样才能在该函数中使用student_A的私有成员。

(3-3)友元非成员函数

可以在类中把一个非成员函数声明为友元函数,那么该函数可以访问该类中的私有成员。例如下列代码:

#include <iostream>

/**
 * @brief student_A
 */
class student_A{
    //声明getStudentInfo()这个非成员函数作为student_A类的友元函数
    friend int getStudentInfo();

private:
    int age = 25;
    std::string name = "xiaoZhang";
    
    std::string getStudentAName()
    {
        return name;
    }
};

/**
 * @brief getStudentInfo
 * @brief 打印出学生的名字和年龄
 */
int getStudentInfo()
{
    //创建student_A的一个实例
    student_A a;
    
    //访问student_A的私有成员(私有属性、私有成员函数)
    std::cout<<"student name:"<<a.getStudentAName()<<std::endl;
    std::cout<<"student age:"<<a.age<<std::endl;

    return -1;
}


int main() {
    getStudentInfo();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iriczhao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值