重学C++系列之友元

news2024/12/30 4:08:16

一、什么是友元

        在C++中,为了提高程序的效率,在一些场景下,引入友元,但同时类的封装性就会被破坏。

二、怎么实现友元

        友元关键字(friend)


// 在类中声明另一个类的成员函数来做为友元函数
// 以关键字(friend)开头:比如friend 返回值类型 类名::类成员函数(参数列表)
friend void A::test(Test &t);



// 全局函数做友元函数

// friend 普通函数的声明

friend void print(Test &t);


// 友元类,要在另外一个类中声明
class 类名1
{


    friend class 友元类名;    // 在类里面声明友元类
}

三、友元的特点

        1、友元关系是单向的,不具备交换性。

        2、友元关系不能被继承。

        3、友元关系不具有传递性。

        4、友元不是类成员,但是它可以通过对象访问类中私有成员,友元作用在于提高程序的运行效率,但是,它破坏了类的封装和数据隐藏性。除非调用访问私有成员变量的频率频繁,才会考虑牺牲封装和数据隐藏性,来换取运行效率。

        5、模板类中声明的友元函数必须要指定具体类型才行,不能声明一个友元函数模板。

四、案例

        1、 在类中声明另一个类的成员函数来做为友元函数

#include <iostream>

using namespace std;

class Base;
class Test
{
public:
    // 不可以在类中实现,只能在类外实现, 此时编译器还没有编译Base类,无法识别出友元
    void show(Base &other); 
    // {
    //     cout << "a = " << other.a << endl;
    // }

};

class Base
{
private:
    int a;
public:
    Base(int a = 0)
    {
        this->a = a;
    }
    friend void Test::show(Base &other);
};

// 不可以在类中实现,只能在类外实现,此时编译器已识别出友元
void Test::show(Base &other)
{
    cout <<"void Test::show(Base &other)" << endl;
    cout << "a = " << other.a << endl;
}


int main()
{

    Base A(10);
    Test test;
    test.show(A);


    return 0;
}

 

        2、全局函数做友元函数 

#include <iostream>

using namespace std;


class Base
{
private:
    int a;
public:
    Base(int a = 0)
    {
        this->a = a;
    }
    // 全局函数声明为友元函数
    friend void show(Base &other);
};

// 全局函数声明为友元函数
void show(Base &other)
{
    cout << "void show(Base &other)" << endl;
    cout << "a = " << other.a << endl;
}


int main()
{

    Base A(10);
    show(A);
   


    return 0;
}

        3、友元类

#include <iostream>

using namespace std;

class Test; // 先声明一个类Test

class Base
{
private:
    int a;
public:
    Base(int a = 0)
    {
        this->a = a;
    }
    friend class Test;  // 把类Test声明为友元类
};

class Test
{
public:
   
    void show(Base &other)
    {
        cout << "void Test::show(Base &other)" << endl;
        cout << "a = " << other.a << endl;
    }

};

int main()
{

    Base A(10);
    Test test;
    test.show(A);


    return 0;
}

        4、模板类中声明的友元函数必须要指定具体类型才行,不能声明一个友元函数模板。

#include <iostream>

using namespace std;



template <class T>
class Test
{
private:
    T a;
public:
    Test(T a = T())
    {
        this->a = a;
    }
    // 定义一个友元函数模板,编译不能通过
    friend ostream& operator << (ostream& output, const Test<T> &other);


};

template <class T>
ostream& operator << (ostream& output, const Test<T> &other)
{
    output << "a = " << other.a << endl;
    return output;
}



int main()
{
    Test<int> A(10);
    cout << A << endl;
    


    return 0;
}

        改正:

#include <iostream>

using namespace std;



template <class T>
class Test
{
private:
    T a;
public:
    Test(T a = T())
    {
        this->a = a;
    }
    // 指定友元函数的具体模板类型,但是这样模板类的作用几乎失效
    friend ostream& operator << (ostream& output, const Test<int> &other);


};

// 指定模板类为int类型
ostream& operator << (ostream& output, const Test<int> &other)
{
    output << "ostream& operator << (ostream& output, const Test<int> &other)" << endl;
    output << "a = " << other.a;
    return output;
}



int main()
{
    Test<int> A(10);
    cout << A << endl;
    


    return 0;
}

五、总结

        友元的作用是在某些场景提高程序的效率,但是同时也破坏了类的封装性和数据的隐藏性。声明友元时,要注意友元的位置,编译器是否已经识别或者编译了所声明的友元,如果没有,就会报错,所以可以采用再类中定义友元,把友元类的函数在类外实现,具体例子看上面的案例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/806783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

golangd\pycharm-ai免费代码助手安装使用gpt4-免费使用--[推荐]

golangd-ai免费代码助手安装使用,pycharm可以使用&#xff0c;估计只要是xx的ide都是可以使用这个插件 目前GPT4以及gpt的大规模使用&#xff0c;如何快速掌握以及在ide中快速使用的办法&#xff0c;今天安装一款golangd编辑器的插件已经使用 一、安装以及使用 1.在golangd中…

texshop mac中文版-TeXShop for Mac(Latex编辑预览工具)

texshop for mac是一款可以在苹果电脑MAC OS平台上使用的非常不错的Mac应用软件&#xff0c;texshop for mac是一个非常有用的工具&#xff0c;广泛使用在数学&#xff0c;计算机科学&#xff0c;物理学&#xff0c;经济学等领域的合作&#xff0c;这些程序的标准tetex分布特产…

PKG内容查看工具:Suspicious Package for Mac安装教程

Suspicious Package Mac版是一款Mac平台上的查看 PKG 程序包内信息的应用&#xff0c;Suspicious Package Mac版支持查看全部包内全部文件&#xff0c;比如需要运行的脚本&#xff0c;开发者&#xff0c;来源等等。 suspicious package mac使用简单&#xff0c;只需在选择pkg安…

Druid连接池与Mybatis-Plus非Spring环境整合:报错异常:NoClassDefFoundError

最近在搞一个Netty与扫描枪通信项目;通过调研框架使用Mybatis-PlusDruid作为获取数据库数据,结果整合报了个错,顺便记录下: 一&#xff0c;配置文件: driverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://127.0.0.1:3306/xxxxxxx?useUnicodetrue&characterEncodin…

SQL编译优化原理

最近在团队的OLAP引擎上做了一些SQL编译优化的工作&#xff0c;整理到了语雀上&#xff0c;也顺便发在博客上了。SQL编译优化理论并不复杂&#xff0c;只需要掌握一些关系代数的基础就比较好理解&#xff1b;比较困难的在于reorder算法部分。 文章目录 基础概念关系代数等价 j…

面试 | 校招字符串相关高频算法题汇总【C++实现】

文章目录 1、反转字符串2、反转字符串||3、字符串最后一个单词的长度4、找字符串中第一个只出现一次的字符5、仅仅反转字母6、验证一个字符串是否是回文7、反转字符串中的单词【⭐】&#xff08;1&#xff09;移除给出字符串中的多余空格&#xff08;2&#xff09;反转整个字符…

Linux下安装VirtualBox虚拟机

1. 简介 VirtualBox是一款强大的x86和AMD64/Intel64虚拟化产品&#xff0c;适用于企业和家庭。VirtualBox不仅是为企业客户提供的一款功能丰富、高性能的产品&#xff0c;它也是根据GNU通用公共许可证(GPL)版本3条款作为开放源码软件免费提供的唯一专业解决方案。有关VirtualBo…

Modbus TCP使用例程

一、Modbus介绍 关于Modbus的介绍可参考前面的文章<modbus tcp协议介绍及分析>和<modbus rtu通信格式测试解析>这2篇文章。 二、Agile Modbus软件包介绍 Agile Modbus软件包的链接地址&#xff1a; https://gitee.com/RT-Thread-Mirror/agile_modbus Agile Modbus的…

Day46 算法记录| 动态规划 13(子序列)

这里写目录标题 300.最长递增子序列 674. 最长连续递增序列718. 最长重复子数组 300.最长递增子序列 视频解析&#xff1a; 第一层for循环遍历每一个元素&#xff0c; ------- 第二层for循环找到当前元素前面有几个小于该值的元素 结尾需要统计最多的个数 class Solution {pu…

如何有效地使用ChatGPT写小说讲故事?

​构思故事情节&#xff0c;虽有趣但耗时&#xff0c;容易陷入写作瓶颈。ChatGPT可提供灵感&#xff0c;帮你解决写作难题。要写出引人入胜的故事&#xff0c;关键在于抓住八个要素——主题、人物、视角、背景、情节、语气、冲突和解决办法。 直接给出故事模板&#xff0c;你可…

无线温湿度信息收集点模块的组成和工作状态及编程与组网建议

在传感技术与物联网的不断发展下&#xff0c;无线温湿度信息收集点模块作为一种重要的终端设备&#xff0c;被广泛应用于各个领域。本文将详细介绍该模块的组成和工作状态&#xff0c;并给出编程和组网的建议。 一、组成 该无线温湿度信息收集点模块由以下几个核心组成部分构成…

Banana Pi BPI-KVM – 基于 Rockchip RK3568 SoC 的 KVM over IP 解决方案

Banana Pi 已经开始开发基于 Rockchip RK3568 SoC 的 BPI-KVM 盒&#xff0c;但它不是迷你 PC&#xff0c;而是 KVM over IP 解决方案&#xff0c;旨在远程控制另一台计算机或设备&#xff0c;就像您在现场一样&#xff0c;例如能够打开和关闭连接的设备、访问 BIOS 等。 商业…

vagrant centos7 根目录扩容

目录 1 创建 centos7 虚拟机 2 扩容根目录 我知道的扩容方式有两种&#xff1a;1 直接扩容分区 &#xff1b;2 扩容逻辑卷。 我没找到为根目录设置到逻辑卷的方法&#xff0c;所以使用直接扩容分区。 1 创建 centos7 虚拟机&#xff0c; vagrant up vagrant ssh 查看磁盘…

Git-分支管理

文章目录 1.分支管理2.合并冲突3.合并模式4.补充 1.分支管理 Git分支管理是指在Git版本控制系统中&#xff0c;使用分支来管理项目的不同开发线路和并行开发的能力。通过分支&#xff0c;开发者可以在独立的环境中进行功能开发、bug修复等工作&#xff0c;而不会影响到主分支上…

文章详情页 - 评论功能的实现

目录 1. 准备工作 1.1 创建评论表 1.2 创建评论实体类 1.3 创建 mapper 层评论接口和对应的 xml 实现 1.4 准备评论的 service 层 1.5 准备评论的 controller 层 2. 总的初始化详情页 2.1 加载评论列表 2.1.1 实现前端代码 2.1.2 实现后端代码 2.2 查询当前登录用户的…

SFP6012A-ASEMI代理海矽美快恢复二极管参数、尺寸、规格

编辑&#xff1a;ll SFP6012A-ASEMI代理海矽美快恢复二极管参数、尺寸、规格 型号&#xff1a;SFP6012A 品牌&#xff1a;ASEMI 封装&#xff1a;TO-247AC 恢复时间&#xff1a;100ns 正向电流&#xff1a;60A 反向耐压&#xff1a;1200V 芯片大小&#xff1a;102MIL*2…

苍穹外卖day-04

苍穹外卖day-04 本项目学自黑马程序员的《苍穹外卖》项目&#xff0c;是瑞吉外卖的Plus版本 功能更多&#xff0c;更加丰富。 结合资料&#xff0c;和自己对学习过程中的一些看法和问题解决情况上传课件笔记 视频&#xff1a;https://www.bilibili.com/video/BV1TP411v7v6/?sp…

一、window安装vagrant

篇章一、window安装vagrant 前言 在日常的学习中&#xff0c;需要在Window中学习Linux相关的操作命令&#xff0c;在本地熟悉Linux服务器环境&#xff0c;因此需要在电脑中安装Vagrant虚拟机来管理所需安装的Linux系统&#xff08;也就是后续的Centos-7&#xff09;。 1、下…

无涯教程-jQuery - Bounce方法函数

弹跳效果可以与effect()方法一起使用。这会在垂直或水平方向多次反弹元素。 Bounce - 语法 selector.effect( "bounce", {arguments}, speed ); 这是所有参数的描述- direction - 效果的方向。可以是"上(up)"&#xff0c;"下(down)"&#xf…

Debian9离线安装docker

1. 前言 在服务器禁止外网访问的情况下&#xff0c;无法通过apt-get install安装docker&#xff0c;使得docker安装变得异常曲折 本地下载安装包&#xff0c;scp到服务器通过dpkg -i 手动安装&#xff0c;启动docker服务失败… … 各种坑&#xff0c;猛男也要落泪 &#x1f92…