C++类基础(四)

news2024/11/18 3:47:23

访问限定符与友元
● 使用 public/private/protected 限定类成员的访问权限

//main.cpp
struct Str
{
//结构体默认的访问权限,可以省略
//public:
    int x = 0;
private:
    int y = 0;
};

int main()
{
    Str m_str;
    //OK: 在同一个翻译单元内,结构体struct Str { ... }以外的任何地方都可以访问公有成员x
    //更普遍地: 只要是公有成员,就可以在结构体外访问它
    std::cout << m_str.x << std::endl;

    //Error: 'y' is a private member of 'Str',即只能在结构体struct Str { ... }内访问私有成员y
    //结构体Str类内声明的成员函数即使在类外定义,也算作结构体struct Str { ... }内
    //更普遍地: 只要是私有成员,就只能在结构体内访问它
    std::cout << m_str.y << std::endl;
    return 0;
}

– 访问权限的引入使得可以对抽象数据类型进行封装

struct Str
{
    //结构体的成员(比如内部数据)完全暴露给用户,导致用户可以操作这些成员,当出现成员的增删或者修改等等,会使程序崩溃或出现未定义的行为
    int x = 0;
    int y = 3;
};

– 类与结构体缺省访问权限的区别

struct Student
{
    //当没有书写private或protected或public访问权限说明符时,以下四个成员都是公有成员,即结构体的缺省访问权限是public
    char Name[10];
    int Age = 0;
    char Sex = 'F';
    void memberfunction() { }
};

class Student
{
    //当没有书写private或protected或public访问权限说明符时,以下四个成员都是私有成员,即类的缺省访问权限是private
    char Name[10];
    int Age = 0;
    char Sex = 'F';
    void memberfunction() { }
};
struct Student
{
//当有访问权限说明符时,各个访问权限生效的区域如下
private:
    ... //private:之后,protected:之前的成员都是私有成员
protected:
    ... //protected:之后,public:之前的成员都是私有成员
public:
    ... //public:之后,};之前的成员都是私有成员
};
//将关键字struct更换成class,以上定义仍然符合C++语法标准

● 使用友元打破访问权限限制 关键字 —— friend

int main(); //main函数的声明
class Str2;
class Str
{
    friend int main(); //在类Str之前声明main函数,然后将main函数声明为类Str的友元,所以main函数内可以访问类Str中的private成员、protected成员和public成员,所以#1处的代码合法
    friend Str2; //在类Str之前声明类Str2,然后将类Str2声明为类Str的友元,所以类Str2内可以访问类Str中的private成员、protected成员和public成员,所以#2处的代码合法
    inline static int x = 3; //私有成员,类内访问
};
class Str2
{
public:
    void fun()
    {
        std::cout << "Use private member 'x' of class Str in class Str2: " << Str::x << std::endl; //#2 OK
    }
};
int main()
{
    std::cout << Str::x << std::endl; //#1 OK
    Str2 my_Str2;
    my_Str2.fun();
    return 0;
}

– 声明某个类或某个函数是当前类的友元 慎用!

int main();
class Str2;
class Str
{
    friend int main();
    friend Str2; //C++标准要求: 类Str2内可以访问类Str中所有的成员(即使是私有成员),反过来类Str不可以访问类Str2的protected成员和private成员
    inline static int x = 3;
};
class Str2
{
public:
    void fun()
    {
        std::cout << Str::x << std::endl; //OK
    }
};
int main()
{
    std::cout << Str::x << std::endl; //OK
    Str2 my_Str2;
    my_Str2.fun();
    return 0;
}
//同上面的例子
class Str
{
  inline static int x = 3;
};
class Str2
{
    //将类Str2声明为类Str的友元,类Str2对类Str依然保持内部成员所具有的访问限制属性
    friend Str;
    void fun()
    {
        std::cout << Str::x << std::endl; //Error: 'x' is a private member of 'Str'
    }
};
class Str4;
class Str
{
    inline static int x = 3;
    friend Str4; //OK,将Str4声明成private权限限制符合C++语法标准
};
class Str2
{
    inline static int x = 4;
protected:
    friend Str4; //OK,将Str4声明成protected权限限制符合C++语法标准
};
class Str3
{
    inline static int x = 5;
public:
    friend Str4; //OK,将Str4声明成public权限限制符合C++语法标准
};
class Str4
{
public:
    void showStrX()
    {
        std::cout << "Str::x: " << Str::x << std::endl; //OK
    }
    void showStrX2()
    {
        std::cout << "Str2::x: " << Str2::x << std::endl; //OK
    }
    void showStrX3()
    {
        std::cout << "Str3::x: " << Str3::x << std::endl; //OK
    }
};

int main()
{
    Str4 myStr;
    myStr.showStrX(); //输出3
    myStr.showStrX2(); //输出4
    myStr.showStrX3(); //输出5
    return 0;
}

在这里插入图片描述

void fun();
class Str
{
    inline static int x = 100;
    friend void fun();
};

void fun()
{
    std::cout << Str::x << std::endl; //OK
}
int main()
{
    fun();
    return 0;
}

在这里插入图片描述
– 在类内首次声明友元类或友元函数

class Str
{
    inline static int x = 100;
    friend class Str2; //首次声明友元类Str2,即使编译器由上往下解析并且之前没有类Str2的声明,编译器仍然会解析成功
    friend void fun(); //首次声明友元函数fun(),同上,编译器将fun()解析为友元函数
};
class Str2
{
    
};

void fun()
{
    
}

● 注意使用限定名称引入友元并非友元类(友元函数)的声明

void function(); //#1
class Str
{
    inline static int x = 100;
    friend class Str2; //首次声明友元类Str2,即使编译器由上往下解析并且之前没有类Str2的声明,编译器仍然会解析成功
    friend void fun(); //首次声明友元函数fun(),同上,编译器将fun()解析为友元函数
    friend void ::function(); //编译器不会将::function()解析为function()的声明,所以必须在#1处加上function()的声明
};

– 友元函数的类外定义与类内定义

class Str
{
    inline static int x = 100;
    friend class Str2 //Error: Cannot define a type in a friend declaration
    {
        
    }
};
class Str
{
    int x = 100;
    friend void fun();
};
void fun() //友元函数的类外定义
{
    Str val;
    std::cout << val.x << std::endl;
}
int main()
{
    fun();
    return 0;
}

在这里插入图片描述

– 隐藏友元( hidden friend ):常规名称查找无法找到(The Power of Hidden Friends in C++)

class Str
{
    int x = 100;
    friend void fun() //fun()不是类Str的成员,是类Str的隐藏友元函数
    {
        Str val;
        std::cout << val.x << std::endl;
    }
};
int main()
{
    fun(); //全局域中无fun()的声明,常规名称查找无法找到,报错
    return 0;
}

● 好处:减轻编译器负担,防止误用

void fun(); //全局域中声明fun()或者在类内声明隐藏友元类外定义隐藏友元,见友元函数的类外定义
class Str
{
    int x = 100;
    friend void fun() //fun()不是类Str的成员,是类Str的隐藏友元
    {
        Str val;
        std::cout << val.x << std::endl;
    }
};

int main()
{
    fun(); //OK
    return 0;
}

● 改变隐藏友元的缺省行为:在类外声明或定义函数

class Str
{
    int x = 100;
    friend void fun(const Str& val) //隐藏友元有一个传入参数
    {
        std::cout << val.x << std::endl;
    }
};

int main()
{
    Str myStr;
    fun(myStr); //对fun()传入了Str类型的参数myStr,常规名称查找无法找到后,触发实参类型依赖查找ADL(Argument Dependent Lookup),会在类Str内检测是否有匹配的函数
    return 0;
}

在这里插入图片描述

参考
深蓝学院:C++基础与深度解析

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

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

相关文章

单车价值超整车售价?智能汽车「新赛道」扎堆供应商

汽车网络安全赛道正在进入新周期。 1月初&#xff0c;HL Mando与全球汽车网络安全方案提供商Argus Cyber Security达成协议&#xff0c;扩大网络安全技术合作。前者将Argus CAN入侵检测系统&#xff08;IDS&#xff09;解决方案应用于刹车和转向等电气化系统产品。 目前&#x…

希尔排序基本思想示例及代码

希尔排序是插入排序的一种&#xff0c;直接插入排序相关内容可见&#xff1a; https://blog.csdn.net/weixin_43978384/article/details/128836898?spm1001.2014.3001.5502 1、算法思想 希尔排序又称“缩小增量”的排序&#xff0c;属于插入排序的一种。希尔排序的基本思想是…

Springboot+ssm企业员工考勤管理系统

毕业的进度&#xff1a; 第一阶段 系统概要设计&#xff0c;设计系统架构&#xff0c;数据库模型 第二阶段 完成模块的开发与测试 第三阶段 实现主要模块 本公司员工管理系统的设计与实现以Springboot作为框架&#xff0c;B/S模式以及MySql作为后台运行的数据库。…

2023年深圳积分入户考这个软考高级证书错不了!加分真高!

信息系统项目管理师是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目之一&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职称资…

最完整的文档成像工具包:GdPicture.NET Crack

GdPicture.NET企业级智能 PDF 和文档处理 SDK&#xff0c;使用最先进的人工智能、机器学习和模糊逻辑算法的高度复杂的 API 集。经过超过 15 年专注于创新的持续研究&#xff0c;GdPicture.NET 已成为市场上最全面的PDF、OCR、条形码、文档图像和格式的 SDK 。 最佳文档影像 SD…

设计模式之装饰器模式,以C++为例。

昨天更新了适配器&#xff0c;今天来盘一盘装饰器模式。装饰器模式以一种动态的方式给对象添加额外的职责&#xff0c;好似“装饰”在对象身上一样&#xff0c;通常通过继承和委托来实现。 目录 一、装饰器模式介绍 二、游戏人物如何使用装饰器模式 三、进阶写法&#xff08;…

VScode ssh远程登陆到服务器阅读代码

1、背景介绍在工作中经常使用ssh远程访问服务阅读代码&#xff0c;但是通过ssh远程访问后没有图形界面&#xff0c;阅读代码非常不方便&#xff0c;本文向大家介绍使用VScode通过ssh远程登陆到服务器&#xff0c;本地可视化阅读查看服务器的代码文件。2、安装VS CodeVisual Stu…

Nginx优化

一.设置Nginx运行进程个数 1.查看cpu个数 grep processor /proc/cpuinfo 使用top 按1,也可以查看cpu的核心数 2.设置Nginx进程数 我的cpu数量是4,修改为4 vim /usr/local/nginx/conf/nginx.conf 二.Nginx运行CPU亲和力 vim /usr/local/nginx/conf/nginx.conf 4核4线程配置 注…

叠氮试剂1379690-01-3,3-Azido-D-alanine HCl,3-叠氮-D-丙氨酸HCl

产品规格&#xff1a;3-叠氮-D-丙氨酸HCl&#xff0c;3-Azido-D-alanine HCl1.CAS号&#xff1a;1379690-01-32.分子式&#xff1a;C3H7ClN4O23.分子量&#xff1a;166.566284.包装规格&#xff1a;1g&#xff0c;5g&#xff0c;10g&#xff0c;包装灵活&#xff0c;有100mg包装…

06-Servlet

目录1.Servlet 技术a)什么是 Servletb)手动实现 Servlet 程序&#xff01;这里要自己引入jar包&#xff0c;配置一下tomcat服务器c)url 地址到 Servlet 程序的访问d)Servlet 的生命周期e)GET 和 POST 请求的分发处理f) 通过继承 HttpServlet 实现Servlet 程序g)使用 IDEA 创建S…

小程序项目学习--第八章:播放页功能-代码重构-分包优化-打包发布

第八章:播放页功能-代码重构-分包优化-打包发布 01_(掌握)播放页-歌词分页的上下滚动区域 隐藏滚动条 .lyric-list ::-webkit-scrollbar {display: none; }歌词分页的上下滚动区域动态设置样式 思考什么时候是第一句歌词&#xff0c;什么时候是最后一句歌词 <swiper-ite…

嘉明的云计算与大数据学习之大数据综合实验案例

1.实验环境 (1)Linux:Ubuntu 16.04。 虚拟机镜像下载链接&#xff1a;https://pan.baidu.com/s/1i_B-2rAfPM53jf7Besi0tw 提取码&#xff1a;WZJM (2)MySQL:5.7.16。 (3)Hadoop:2.7.1。 (4)HBase:1.1.5。 (5)Hive:1.2.1。 (6)Sqoop:1.4.6。 (7)R:4.1.2。 (8)Eclipse:3.8。 2.…

Docklight Scripting模拟串行端口

Docklight Scripting模拟串行端口 Docklight是测试、分析和模拟串行端口(RS232、RS485/422等)的工具。此程序允许您监视和测试两个串行端口之间的连接。该程序环境简单&#xff0c;安装在所有Windows XP/7/8/10版本上。Docklight Scripting是一种带有内部编辑器的脚本语言&…

电子会议桌牌——网络版

产品特征&#xff1a; 低功耗&#xff0c;常规使用3-5年电池寿命支持空中唤醒&#xff0c;刷新快速&#xff0c;几秒钟内看到结果点阵电子纸屏幕&#xff0c;视角接近180基于Web的应用界面&#xff0c;支持跨平台操作安装简单&#xff0c;快速布置电池供电不需要布线双面显示…

Python你绝对不知道的15个小技巧,知道的算我输

名字&#xff1a;阿玥的小东东 学习&#xff1a;Python语言、正在学习c语言 主页&#xff1a;阿玥的小东东 目录 前言 1.all or any 2.bashplotlib 3.collections 4.dir 5.from __future__ import 6.python的优点 7.geopy 8.python2.x中的编码不是 unicode &#xff…

转行自学Java没后悔,我的经历证明,改变永远没有错

我在北京工作6年&#xff0c;现在年薪42万&#xff08;仅代表个人收益&#xff09;&#xff0c;目前在搜狐畅游工作&#xff0c;参与过轩辕剑的项目研发&#xff0c;有几个大型项目实战的经历&#xff0c;不过最后这几款项目都失败了。我之所以选择当初学习Java&#xff0c;就一…

我靠CSGO搬砖项目,一个月净赚过万

作为一名四线小城市的平凡上班族&#xff0c;今年已经满30岁了&#xff0c;工资到手也才6000多&#xff0c;已经不记得有多少年没涨过了。 后来通过CSGO搬运项目&#xff0c;每月副业收益稳定在5万的收益。 废话不多说&#xff0c;先给大家瞅瞅我上个月带货的收益&#xff0c…

为什么要上机械设备ERP系统?对企业管理有什么帮助?

机械设备制造行业是国民经济增长的重要支撑&#xff0c;随着信息化的发展&#xff0c;机械设备制造企业面临各种各样的挑战&#xff0c;频繁地出现部门监管力度不够、生产计划难定、产品质量不过关、生产过程操作不规范以及原材料使用不当等&#xff0c;造成资源浪费的现象&…

规则引擎设计与实现

规则引擎设计与实现 「字节跳动第五届青训营」笔记 是什么 规则引擎是一种嵌入在应用程序中的组件&#xff0c;实现了将业务决策从应用程序代码中分离出来&#xff0c;并 使用预定义的语义模块编写业务决策。接受数据输入&#xff0c;解释业务规则&#xff0c;并根据业务规则…

用最简单的方法实现个人网站-wordpress结合LAMP架构实战

文章目录前言一、LAMP架构是什么&#xff1f;1.1 LAMP架构简介1.2 什么是apache?1.3 什么是MySQL&#xff1f;1.4 什么是php&#xff1f;二. wordpress是什么三. 搭建博客过程1. 实验环境2. 搭建LAMP架构3. 设置数据库并授权4. 上传wordpress并解压5. 修改配置文件6. 网页端进…