类与对象(c++)——取地址运算符重载,初始化列表,类型转换

1.取地址运算符重载

1.1 const成员函数

a)将const修饰的成员函数称之为const成员函数,const修饰成员函数放到成员函数参数列表的后 ⾯。

b)const实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进⾏修改。 const 修饰Date类的Print成员函数,Print隐含的this指针由Date* const this变为const Date* const this。

例如:

class Date{public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// void Print(const Date* const this) constvoid Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;};
void Date::Print()
{cout << _year << "/" << _month << "/" << _day << endl;
}int main(){// 这⾥⾮const对象也可以调⽤const成员函数是⼀种权限的缩⼩Date d1(2024, 7, 5);d1.Print();const Date d2(2024, 8, 5);d2.Print();return 0;}

注意:如果Print后面没有定义const,则当Date被const修饰时就存在权限放大,编译器就会报错。

1.2取地址运算符重载

取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载,⼀般这两个函数编译器⾃动⽣成的就可以够我们⽤了,不需要去显示实现。除非一些很特殊的场景,⽐如我们不想让别⼈取到当前类对象的地址,就可以自己实现⼀份,返回⼀个错误或空地址。

class Date
{ 
public :Date* operator&(){return this;// return nullptr;const Date* operator&()const{return this;// return nullptr;}private :int _year ;  int _month ; int _day ; 
};

2.初始化列表(构造函数)

a)实现构造函数时,初始化成员变量主要使⽤函数体内赋值,构造函数初始化还有⼀种方式,就是初始化列表,初始化列表的使⽤方式是以⼀个冒号开始,接着是⼀个以逗号分隔的数据成员列表,每个"成员变量"后面跟⼀个放在括号中的初始值或表达式。

例如:

class Time
{
public:Time(int hour):_hour(hour){};void Print()const{cout << _hour << endl;}
private:int _hour;
};int main()
{Time t1(24);t1.Print();return 0;
}

结果:

b)每个成员变量在初始化列表中只能出现一次语法理解上初始化列表可以认为是每个成员变量定义初始化的地方

例如:反复定义成员_hour

           报错:

c)引用成员变量const成员变量没有默认构造的类类型变量,必须放在初始化列表位置进⾏初始 化,否则会编译报错。

例如:

class Time
{
public:Time(int hour):_hour(hour){}void Print()const{cout << _hour << endl;}
private:int _hour;
};class Date
{
public:Date(int& x, int year = 1, int month = 1, int day = 1):_year(year), _month(month), _day(day), _t(12), _rp(x), _n(1){// error C2512: “Time”: 没有合适的默认构造函数可⽤// error C2530 : “Date::_ref” : 必须初始化引⽤// error C2789 : “Date::_n” : 必须初始化常量限定类型的对象}void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;Time _t;// 没有默认构造int& _rp;// 引⽤const int _n; // const 
};
int main()
{int i = 0;Date d1(i);d1.Print();return 0;
}

第一这里的Time类作为Date类中的成员变量,初始化的时候,会去调用初始化_t的默认构造函数,但是注意,Time中是没有默认构造函数的哟(前面小编文章“默认构造函数”中有详细讲解,只有不传参,全缺省,编译器自动生成的构造函数,这三类才是默认构造函数),所以这里_t必须在初始化列表中初始化;

第二这里成员变量_rp也必须在列表初始化;第三const修饰的也必须在列表初始化。

注意:这里不是引用成员变量const成员变量没有默认构造的类类型变量这三种变量的,成员变量可以放在初始化列表初始化,也可以放在构造函数里面初始化,如上图。

d) C++11⽀持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显示在初始化列表初始化的成员使⽤的。

例如:

class Date
{
public:Date():_month(2),_day(1){if (_ptr == NULL){cout << "malloc failed" << endl;}for (int i = 0; i < 3; i++){_ptr[i] = i;}}void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private:// 注意这⾥不是初始化,这⾥给的是缺省值,这个缺省值是给初始化列表的// 如果初始化列表没有显⽰初始化,默认就会⽤这个缺省值初始化int _year = 1;int _month = 1;int _day;Time _t = 1;const int _n = 1;int* _ptr = (int*)malloc(12);
};

e)尽量使⽤初始化列表初始化,因为那些你不在初始化列表初始化的成员也会⾛初始化列表,如果这个成员在声明位置给了缺省值,初始化列表会⽤这个缺省值初始化。如果你没有给缺省值,对于没有显示在初始化列表初始化的内置类型成员是否初始化取决于编译器,C++并没有规定。对于没有显示在初始化列表初始化的⾃定义类型成员会调⽤这个成员类型的默认构造函数,如果没有默认构造会编译错误。

f)初始化列表中按照成员变量在类中声明顺序进⾏初始化,跟成员在初始化列表出现的的先后顺序⽆关。建议声明顺序和初始化列表顺序保持⼀致。

这里通过一个例题来说明:这里打印的结果会是什么呢?1 1吗?

class A
{
public:A(int a):_a1(a), _a2(_a1){}void Print() {cout << _a1 << " " << _a2 << endl;}
private:int _a2 = 2;int _a1 = 2;
};int main()
{A aa(1);aa.Print();
}

结果其实是:          1和一个随机值

首先这里实例化时,传了1作为参数,那是不是_a1初始化为1,_a2再用_a1初始化为1呢?当然不是,这里初始化的顺序是以成员变量申明的顺序初始化的,首先初始化的是_a2,在这个时候_a1还没有初始化,所以_a2就被初始化成了一个随机值,再去初始化_a1,这时通过传入的参数1,就被初始化为1。

3. 类型转换

a)C++⽀持内置类型隐式类型转换为类类型对象,但是需要有相关内置类型为参数的构造函数。

例如:

class A
{
public:A(int a1):_a1(a1){}A(int a1, int a2):_a1(a1),_a2(a2){}void Print(){cout << _a1 << " " << _a2 << endl;}
private:int _a1 = 1;int _a2 = 2;
};int main()
{// 1构造⼀个A的临时对象,再⽤这个临时对象拷⻉构造aa1// 编译器遇到连续构造+拷⻉构造->优化为直接构造A aa1 = 1;aa1.Print();// C++11之后才⽀持多参数转化A aa3 = { 2,2 };aa3.Print();return 0;
}

结果:

这里首先用1构造了一个A的临时变量,再将这对象临时拷贝构造aa1。aa3也是同理。

这里如果是用引用的话:

const A& aa2 = 1;

1创建一个临时变量,再拷贝给aa2,但是临时变量具有常属性,需要const修饰,所以引用要加const,不能使权限放大。(这里小编前面“类与对象(引用)”的文章中有更详细的讲解)。

b)构造函数前⾯加explicit就不再支持隐式类型转换

例如:

class A
{
public:// 构造函数explicit就不再⽀持隐式类型转换explicit A(int a1):_a1(a1){}explicit A(int a1, int a2):_a1(a1),_a2(a2){}void Print(){cout << _a1 << " " << _a2 << endl;}
private:int _a1 = 1;int _a2 = 2;
};int main()
{A aa1 = 1;aa1.Print();A aa3 = { 2,2 };aa3.Print();return 0;
}

报错:

4.友元

a)友元提供了⼀种突破类访问限定符封装的⽅式,友元分为:友元函数和友元类,在函数声明或者类声明的前⾯加friend,并且把友元声明放到⼀个类的⾥⾯。

class A
{// 友元声明friend void func1(const A& aa);
private:int _a1 = 1;int _a2 = 2;
};void func1(const A& aa)
{cout << aa._a1 <<" "<< aa._a2 << endl;
}
int main()
{A aa;func1(aa);return 0;
}

结果:

如果没有友元声明func1函数是不能访问aa中的私有成员变量。

b)外部友元函数可访问类的私有和保护成员,友元函数仅仅是⼀种声明,他不是类的成员函数

c)友元函数可以在类定义的任何地⽅声明,不受类访问限定符限制。(即在private,public中定义都可以)

d)⼀个函数可以是多个类的友元函数。

例如:

// 前置声明,否则A的友元函数声明编译器不认识B
class B;class A
{// 友元声明friend void func(const A& aa, const B& bb);
private:int _a1 = 1;int _a2 = 2;
};class B
{// 友元声明friend void func(const A& aa, const B& bb);
private:int _b1 = 3;int _b2 = 4;
};void func(const A& aa, const B& bb)
{cout << aa._a1 << endl;cout << bb._b1 << endl;
}int main()
{A aa;B bb;func(aa, bb);return 0;
}

这里函数func需要访问aa和bb的私有成员变量,所以就要在A,B中都必须要有友元声明,还要注意,这里在B中进行友元声明时,前面已经有A类,但在A中友元声明时,前面还没有B类,所以就要进行前置声明,否则A的友元函数声明编译器不认识B。

e)友元类中的成员函数都可以是另⼀个类的友元函数,都可以访问另⼀个类中的私有和保护成员。

例如:

class A
{// 友元类声明friend class B;
private:int _a1 = 1;int _a2 = 2;
};
class B
{
public:void func1(const A& aa){cout << aa._a1 << endl;cout << _b1 << endl;}void func2(const A& aa){cout << aa._a2 << endl;cout << _b2 << endl;}
private:int _b1 = 3;int _b2 = 4;
};
int main()
{A aa;B bb;bb.func1(aa);bb.func2(aa);return 0;
}

结果:

f)友元类的关系是单向的,不具有交换性,比如A类是B类的友元,但是B类不是A类的友元。

例如:

g)友元类关系不能传递,如果A是B的友元,B是C的友元,但是A不是B的友元。

h)友元提供了便利。但是友元会增加耦合度,破坏了封装,因此友元不宜多⽤。

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

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

相关文章

形态学图像处理(Morphological Image Processing)

形态学图像处理(Morphological Image Processing) 前言 ‍ 本博客为个人总结数字图像处理一课所写&#xff0c;并给出适当的扩展和相应的demo。 写博客跟做 checkpoint​ 很像&#xff0c;毕竟个人还不能达到那种信手拈来的境界&#xff0c;忘了就是从零开始训练&#xff0…

如何在K8s集群中管理与使用GPU

背景 随着人工智能的兴起&#xff0c;GPU作为重要的智算算力类型愈发受到重视&#xff0c;而Kubernetes&#xff08;k8s&#xff09;作为业界主流的集群管理系统&#xff0c;如何方便管理、使用GPU也是其需要解决的一大问题&#xff0c;故此收集整理了K8s管理与使用GPU的相关资…

kubepi管理k8s集群,演示如何连接阿里云k8s容器

一、背景 对k8s容器运维的过程中&#xff0c;如果是自建k8s的话&#xff0c;一般会安装dashboard&#xff0c;方便管理&#xff1b;如果是阿里云k8s容器&#xff0c;它是有提供web ui&#xff0c;但是它有个不便之处–需要定期登录&#xff0c;且缺少命令控制台。 当你需要使…

Conda 安装纯净版ComfyUI

网上有很多整合包&#xff0c; 我个人喜欢纯净版&#xff0c; 自已搭建 1 拉代码 git clone https://github.com/comfyanonymous/ComfyUI 如果没有装过git,下载安装: https://git-scm.com/ https://git-lfs.com/ 2 创建环境 cd ComfyUI conda create -n ComfyUI python3.11…

LeetCode:700. 二叉搜索树中的搜索

目录 题目描述: 代码: 题目描述: 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和一个整数值 val。 你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在&#xff0c;则返回 null 。 示例 1: 输入&#xff1a;root [4,2,7,1,3…

摄影:相机控色

摄影&#xff1a;相机控色 白平衡&#xff08;White Balance&#xff09;白平衡的作用&#xff1a; 白平衡的使用环境色温下相机色温下总结 白平衡偏移与包围白平衡包围 影调 白平衡&#xff08;White Balance&#xff09; 人眼看到的白色&#xff1a;会自动适应环境光线。 相…

【大选】2024年美国总统选举数据分析可视化

前言 • &#x1f453; 可视化主要使用 Plotly • &#x1f50e; 数据处理主要使用 pandas • &#x1f449; 本文是我自己在和鲸社区的原创 1.项目背景描述 2024年美国大选是该国政治生活中的重要事件&#xff0c;吸引了全球的关注。本报告通过对选举数据的分析&#xff0c…

Linux进阶:常用操作

systemctl&#xff1a; 控制系统服务的启动、关闭 系统内置服务均可被systemctl控制第三方软件&#xff0c;如果自动注册了可以被systemctl控制第三方软件&#xff0c;如果没有自动注册&#xff0c;可以手动注册 语法&#xff1a;systemctl start | stop | restart | disable…

JVM类加载过程-Loading

一、Class对象的生命周期 .class文件是如何加载到内存中:.class文件是ClassLoader通过IO将文件读到内存,再通过双亲委派的模式进行Loading,再Linking、以及Initializing,代码调用等一系列操作后,进行GC,组成完整的生命周期; 二、双亲委派模式(Loading的过程): 1、类…

002创建ASP.NET Core项目-数据库优先

创建数据库和表 创建数据库和表 添加关系 Product表引用Category 创建ASP.NET Core Web项目 根据数据库创建Models 在【程序包管理器控制台输入命令】 Scaffold-DbContext Data Source.;Initial Catalogshopdb;Usersa;Password123456;TrustServerCertificatetrue’Microso…

探究IOC容器刷新环节初始化前的预处理

目录 一、IOC容器的刷新环节快速回顾 二、初始化前的预处理prepareRefresh源码分析 三、初始化属性源 &#xff08;一&#xff09;GenericWebApplicationContext初始化属性源 &#xff08;二&#xff09;StaticWebApplicationContext初始化属性源 四、初始化早期事件集合…

25.UE5时间膨胀,慢动作,切换地图,刷BOSS

2-27 时间膨胀、慢动作、切换地图、刷BOSS_哔哩哔哩_bilibili 目录 1.刷新BOSS逻辑 2.时间膨胀实现慢动作 3.胜利画面&#xff0c;下一关 3.1胜利画面UI 3.2第一关、第二关游戏模式 3.3下一关按钮事件的绑定 1.刷新BOSS逻辑 实现当场上的怪物都死亡后&#xff0c;进行刷…

自己编写的前后端分离程序,解决跨域问题

跨域问题在前端解决很麻烦&#xff0c;既然前后端都是自己编写的&#xff0c;就直接在后端解决了。 1. 后端中 在controller文件中加上 CrossOrigin // 解决跨域问题&#xff0c;不加的话虽然数据能正常传输&#xff0c;但是前端页面会没有正常响应 2. 前端中 可以正常访问…

小米顾此失彼:汽车毛利大增,手机却跌至低谷

科技新知 原创作者丨依蔓 编辑丨蕨影 三年磨一剑的小米汽车毛利率大增&#xff0c;手机业务毛利率却出现下滑景象。 11月18日&#xff0c;小米集团发布 2024年第三季度财报&#xff0c;公司实现营收925.1亿元&#xff0c;同比增长30.5%&#xff0c;预估902.8亿元&#xff1b;…

E45.【C语言】练习:输入10个整数查找找并打印不相同的数字及个数

1.题目 输入10个整数查找找并打印不相同的数字及个数 输入示例 数组元素个数:10 20 50 30 10 60 90 70 30 10 20 输出示例 20 50 30 10 60 90 70 一共7个 2.初始代码 和E27.【C语言】练习&#xff1a;在一个整型数组中&#xff0c;只有一个数字出现一次&#xff0c;其他数…

播放器开发之ffmpeg 硬件解码方案

硬件编解码的概念 硬件编解码是⾮CPU通过烧写运⾏视频加速功能对⾼清视频流进⾏编解码&#xff0c;其中⾮CPU可包括GPU、FPGA或者 ASIC等独⽴硬件模块&#xff0c;把CPU⾼使⽤率的视频解码⼯作从CPU⾥分离出来&#xff0c;降低CPU的使⽤负荷&#xff0c;使得平台能 ⾼效且流畅…

DDD领域应用理论实践分析回顾

目录 一、DDD的重要性 &#xff08;一&#xff09;拥抱互联网黑话&#xff08;抓痛点、谈愿景、搞方法论&#xff09; &#xff08;二&#xff09;DDD真的重要吗&#xff1f; 二、领域驱动设计DDD在B端营销系统的实践 &#xff08;一&#xff09;设计落地步骤 &#xff0…

读懂top后显示内容

第一行&#xff1a;系统信息 top - 06:33:12 up 42 min, 1 user, load average: 0.04, 0.02, 0.00 06:33:12&#xff1a;当前时间。up 42 min&#xff1a;系统已经启动了 42 分钟。1 user&#xff1a;当前有 1 个用户登录。load average: 0.04, 0.02, 0.00&#xff1a;这三个…

2024年第十四届APMCM亚太杯数学建模A题B题C题思路+代码解析汇总

2024年第十四届亚太地区大学生数学建模竞赛 开赛后第一时间更新解题思路代码参考文章&#xff01; 点击链接加入群聊【2024亚太杯数学建模竞赛助攻】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&ksIq03p_73AYtWuH-bNy6VGD2652Um6y2&authKeyZsYwQzbxX0BKPyH…

Tomcat 如何管理 Session

Tomcat 如何管理 Session 我们知道&#xff0c;Tomcat 中每一个 Context 容器对应一个 Web 应用&#xff0c;而 Web 应用之间的 Session 应该是独立的&#xff0c;因此 Session 的管理肯定是 Context 级的&#xff0c;也就是一个 Context 一定关联多个 Session。 Tomcat 中主…