【C++干货基地】面向对象核心概念 const成员函数 | 初始化列表 | explicit关键字 | 取地址重载


在这里插入图片描述

🎬 鸽芷咕:个人主页

 🔥 个人专栏: 《C++干货基地》《粉丝福利》

⛺️生活的理想,就是为了理想的生活!

引入

  哈喽各位铁汁们好啊,我是博主鸽芷咕《C++干货基地》是由我的襄阳家乡零食基地有感而发,不知道各位的城市有没有这种实惠又全面的零食基地呢?C++ 本身作为一门篇底层的一种语言,世面的免费课程大多都没有教明白。所以本篇专栏的内容全是干货让大家从底层了解C++,把更多的知识由抽象到简单通俗易懂。

⛳️ 推荐

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。

文章目录

  • 引入
  • ⛳️ 推荐
  • 一、const 成员函数
    • 1.1 什么是const 成员函数
    • 1.2 const成员函数的注意事项
    • 总结
  • 二、取地址及const取地址操作符重载
    • 2.1 取地址操作的意义
  • 三、重新认识构造函数
    • 3.1构造函数体赋值
    • 3.2 初始化列表
      • 规则一
      • 规则二
  • 四、explicit关键字
    • 4.1 构造函数的隐式类型转换
    • 4.2 隐式转换的作用
    • 4.2 explicit关键字的使用

一、const 成员函数

1.1 什么是const 成员函数

cosnt 的成员函数其实就是在我们 函数的括号外 多加一个 const void Dlsplay() const

  • 其他的作用是修饰 隐含的 this 指针,使其不能修改。

在这里插入图片描述

1.2 const成员函数的注意事项

const 成员可以直接修饰this指针那么使用起来有什么要注意的嘛?

  • 下面我们看一下这些代码来思考一下
#include<iostream>
using namespace std;

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << "Print()" << endl;
		cout << "year:" << _year << endl;
		cout << "month:" << _month << endl;
		cout << "day:" << _day << endl << endl;
	}
	void Print() const
	{
		cout << "Print()const" << endl;
		cout << "year:" << _year << endl;
		cout << "month:" << _month << endl;
		cout << "day:" << _day << endl << endl;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};
void Test()
{
	Date d1(2022, 1, 13);
	d1.Print();
	const Date d2(2022, 1, 13);
	d2.Print();
}

int main()
{
	Test();
	return 0;
}
  1. const对象可以调用非const成员函数吗?
  • 不能 const 对象调用非const成员会导致,权限的放大所以会出现错误
  1. 非const对象可以调用const成员函数吗?
  • 可以 非const 成员调用 const 成员函数属于权限的缩小,权限是可以缩小的
  1. const成员函数内可以调用其它的非const成员函数吗?
  • 不可以,这样会导致权限的放大
  1. 非const成员函数内可以调用其它的const成员函数吗?
  • 可以,非const 成员,调用const 成员是权限的缩小

总结

1. 在成员函数里如果我们只对成员变量读访问,那么建议加上 cosnt指针。
2. 在成员函数里如果我们要对成员变量进行修改,不能加上 cosnt指针。(否者修改不了成员变量)

二、取地址及const取地址操作符重载

2.1 取地址操作的意义

取地址操作符顾名思义,就对我们的 & 取地址符号进行重载使其能获取到成员变量的地址

  • 但是一般都是默认生成的,除非我们想让取地址符号取的是指定位置的地址
class Date
{
public:
	Date* operator&()
	{
		return this;
	}
	const Date* operator&()const
	{
		return this;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};

三、重新认识构造函数

3.1构造函数体赋值

以往我们在定义构造函数的时候都是在构造函数内进行赋值的,那么我们创建成员变量是否也是在构造函数里面呢?

  • 如果构造函数是创建的话那么,我们声明成员变量的时候给的默认值是定义嘛?
class Date
{
public:
Date(int year, int month, int day)
 {
     _year = year;
     _month = month;
     _day = day;
 }
private:
int _year = 2022;
int _month = 06;
int _day = 25;
};
  • 构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。
  • 所以构造函数并不是初始化成员变量的地方,而我们在进行类声明的时候给的的默认值夜也只是声明

3.2 初始化列表

在C++中规定了所有成员变量在初始化的时候都是在初始化列表进行初始化的

  • 初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟
    一个放在括号中的初始值或表达式。
class Date
{
public:
	Date(int year, int month, int day)
		: _year(year)
		, _month(month)
		, _day(day)
	{}
private:
	int _year;
	int _month;
	int _day;
};
  1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
  2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
  • 引用成员变量
  • const成员变量
  • 自定义类型成员(且该类没有默认构造函数时)

规则一

  • 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。

这个我相信很好了解,初始化列表不管我们写没写都会在初始化列表进行初始化

  • 所以对于简单的变量初始化建议使用初始化列表
  • 一些复杂的类初始化可以使用在构造函数体内进行初始化

规则二

  • 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关

🍸 代码演示:

class A
{
public:
    A(int a)
       :_a1(a)
       ,_a2(_a1)
   {}
    
    void Print() {
        cout<<_a1<<" "<<_a2<<endl;
   }
private:
    int _a2;
    int _a1;
};
int main() {
    A aa(1);
    aa.Print();
}
  • 大家猜一猜这个程序运行会出现什么情况呢?

  • A. 输出1 1 B.程序崩溃

  • C.编译不通过D.输出1 随机值

这里的答案是选D
虽然我们在初始化列表先写的是 _a1 但是初始化列表是按照声明的顺序来进行初始化的,对 _a2(_a1) 进行初始化的时候 __a1 还是一个随机值,_a2 就被赋值成了 _a1 的随机值

四、explicit关键字

4.1 构造函数的隐式类型转换

构造函数不仅可以构造与初始化对象,对于单个参数或者除第一个参数无默认值其余均有默认值
的构造函数,还具有类型转换的作用。

class A
{
public:
	A(int x)
	{
		this->_x = x;
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _x;
};
int main()
{
	A a1(1);
	A a2 = 3;
	return 0;
}

这里我们既可以使用构造函数来进行赋值,还可以使用隐式类型转换的方法来进行赋值。

  • 其主要原理是 使用 = 号赋值时,会先用 1 构造一个临时变量然后再调用拷贝构造构造函数
  • 也就是 先构造->在拷贝构造

但是编译器目前太智能了,对同一个表达式连续的构造会合二为一优化为一步
在这里插入图片描述

  • 除第一个参数无默认值其余均有默认值的构造函数,还具有类型转换的作用。
class Data
{
public:
	Data(int year, int month = 10, int day = 1)
	{
		cout << "data()" << endl;
	}
	~Data()
	{
		cout << "~data()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Data a1(2021);
	Data a2 = 2022;
	return 0;
}

4.2 隐式转换的作用

隐式转换可以说是非常的好用了以后我们在很多地方都可以用到,以往我们使用链表存储类的话每次push 都需要,push 成员变量,但是有了隐式类型转换就可以直接插入自动转换为我们需要的类了。

  • 而且我们在类里面去给其他类进行使用缺省值的时候也是非常方便
class C
{
public:
	//explicit C(int x = 0)
	C(int x = 0)
		:_x(x)
	{}

	C(const C& cc)
	{
		cout << "C(const C& cc)" << endl;
	}

private:
	int _x;
};

C xx(1);//定义全局变量来赋缺省值

class B
{
private:
	// 缺省值
	int a = 1;
	int* p1 = nullptr;
	int* p2 = (int*)malloc(4);

	C cc1 = xx;  // 虽然可以,但是很费劲
	C cc2 = 2;
};

  • push 插入时直接使用隐式类型转换,不需要在插入相同类型的类了
class C
{
public:
	//explicit C(int x = 0)
	C(int x = 0)
		:_x(x)
	{}

	C(const C& cc)
	{
		cout << "C(const C& cc)" << endl;
	}

private:
	int _x;
};
class Stack
{
public:
	void Push(const C& c)
	{
		//
	}
};

int main()
{
	Stack st;
	C cc3(3);
	st.Push(cc3);

	st.Push(4);

	return 0;
}

4.2 explicit关键字的使用

explict 的关键字是用来修饰构造函数的一旦使用了 explicit 修饰构造函数,禁止类型转换
在这里插入图片描述


class A
{
public:
	explicit A(int x)
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _x;
};

class Data
{
public:
	explicit Data(int year, int month = 10, int day = 1)
	{
		cout << "data()" << endl;
	}
	~Data()
	{
		cout << "~data()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	A a1 = 2;
	Data a2 = 2020;

	return 0;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前端从零到一搭建脚手架并发布到npm

这里写自定义目录标题 一、为什么需要脚手架&#xff1f;二、前置-第三方工具的使用1. 创建demo并运行-4步新建文件夹 zyfcli&#xff0c;并初始化npm init -y配置入口文件 2.commander-命令行指令3. chalk-命令行美化工具4. inquirer-命令行交互工具5. figlet-艺术字6. ora-lo…

Oracle数据库的简单使用

Oracle简单使用 一、数据库的介绍二、Oracle介绍账号管理Oracle的安装Oracle服务的作用OracleRemExecService服务创建数据库 常用命令 三、SQL语言SQL分类实用的数据表添加注释数据操纵语言&#xff08;DML&#xff09;查询语句&#xff08;SELECT&#xff09;wherelikedistinc…

ShardingSphere:强大的分布式数据库中间件【图文】

ShardingSphere的诞生 ShardingSphere的结构 Sharding-JDBC :它提供了一个轻量级的 Java 框架&#xff0c;在 Java 的 JDBC 层提供额外的服务。使用客户端直连数据库&#xff0c;以 jar 包形式提供服务&#xff0c;无需额外部署和依赖&#xff0c;可理解为增强版的 JDBC 驱动&…

如何使用 Cloudflare 和 Mailgun 设置自定义电子邮件

作为一名软件工程师&#xff0c;您可能考虑拥有一个专业的电子邮件账户&#xff0c;以及自己的网站&#xff0c;比如 “infoexample.com”. 但这可能会花费一定金额&#xff0c;您可能不愿意支付。 但您知道您可以免费做到吗&#xff1f;事实上&#xff0c;有一种方法可以做到…

error解决expression before ‘static‘

问题现象 报警如下 跳转到提示第125行&#xff0c;但是这行明显是没有问题的。 问题分析 经过排查可以看到&#xff0c;是120行的末尾\在S32DS编译器里面被认为是“接下一行”的意思&#xff0c;120行注释掉之后&#xff0c;后面的121行、122行、123行均被注释掉&#xff0c;…

得物sign参数逆向分析与Python算法还原

文章目录 1. 写在前面2. 接口分析3. 断点分析4. Python算法还原 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚…

bp神经网络拟合函数未知参数【源码+视频教程】

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《复杂函数拟合案例分享》本专栏旨在提供 1.以案例的形式讲解各类复杂函数拟合的程序实现方法&#xff0c;并提供所有案例完整源码&#xff1b;2.…

Linux 操作系统非缓冲区的文件操作、时间编程

1、文件操作 1.1 基于缓冲区的文件操作 基于缓冲区的文件操作---高级Io 以f开头的是基于缓冲区的文件操作 printf是一个基于缓冲区的函数 输出条件&#xff1a; 1.程序正常运行 2.遇到换行\n也能输出 3.缓存区内存已满 1024大小 4.遇到fflush&#xff08;stdout&a…

Ansible-变量-迭代-jinja2模版

变量&#xff1a; 在ansible中&#xff0c;变量是用来存储和传递数据的容器。 这些变量可以包含各种类型的数据&#xff0c;列如数字、字符串、列表、字典。 可以增加ansible playbook的灵活性和重用性变量的使用&#xff1a; 声明&#xff1a;变量名值 引用&#xff1a;{{ 变量…

详细分析Java中的AuthRequest类(附Demo)

目录 前言1. 基本知识2. Demo3. 实战 前言 公共接口&#xff0c;定义了对第三方平台进行授权、登录、撤销授权和刷新 token 的操作 1. 基本知识 先看源码基本API接口&#xff1a; import me.zhyd.oauth.enums.AuthResponseStatus; import me.zhyd.oauth.exception.AuthExce…

提升测试效率,专业方案揭秘

提升测试效率是软件开发中一个永恒的主题&#xff0c;它不仅关乎项目能否按期完成&#xff0c;更影响着软件产品的质量与用户体验。随着敏捷开发、持续集成等方法论的普及&#xff0c;如何在有限的时间内进行高效、全面的测试成为了开发者和测试人员面临的挑战。 在传统模式中&…

Windows 平台上面管理服务器程式的高级 QoS 策略

在 Windows 平台上面&#xff0c;目前有两个办法来调整应用程式的 QoS 策略设置&#xff0c;一种是通过程式设置&#xff0c;一种是通过 “Windows 组策略控制”。 在阅读本文之前&#xff0c;您需要先查阅本人以下的几篇文献&#xff0c;作为前情提示&#xff1a; VC Windows…

数据质量与策略:解锁生成式AI潜力的关键步骤

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

每日一题(L2-011):玩转二叉树--建树+层序遍历

与L2-006近乎相同&#xff0c;先建树&#xff0c;然后遍历 #include<bits/stdc.h> using namespace std; int in[35]; int pre[35]; typedef struct Tree{int num;Tree* left;Tree* right; }T;T * build(int in1,int in2,int pre1,int pre2){T * tnew T;t->numpre[pr…

战姬物语部署

一.准备环境 #关闭seliunx和防火墙 setenforce 0 systemctl stop firewalld systemctl disable firewalld #配置源&#xff0c;并安装常用工 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo curl -o /etc/yum.repos.d/epel.repo …

Leetcode 86. 分隔链表

题目链接&#xff1a; 86. 分隔链表 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/partition-list/description/ 题目&#xff1a; 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出…

深入探究图像增强(C语言实现)

我们将从基础出发使用C语言进行图像处理与分析&#xff0c;重点讨论图像增强和平滑技术。图像增强技术旨在通过增加对比度、亮度和整体清晰度来改善图像的视觉质量。另一方面&#xff0c;图像平滑方法则用于减少噪声并减少图像中的突变&#xff0c;使图像更加均匀和视觉上吸引人…

利用二维码定位技术实现桌面机器人简易定位方案(上篇)

目录 1、前言2、二维码的定位标签识别原理3、生成定位标签3、基于定位标签的物体识别与定位 1、前言 机械手臂尤其是工业场景下大部分的应用是在一个平面&#xff08;桌面&#xff09;内完成一些抓取工作。一般可以用示教方式完成重复步骤。但是示教方式&#xff0c;对于一些活…

过氧化氢滴定方法可用的PFA器皿有哪些?

滴定液:KMnO4标准溶液 试液:H2O2商品液(3%)&#xff0c;H2SO4 (3.0mol/L ) 指示剂:酚酞指示剂 仪器:分析天平&#xff0c;PFA酸式滴定管50mL&#xff0c;PFA 移液管10mL/25mL、PFA 容量瓶250mL、PFA锥形瓶250mL 1、KMnO4标准溶液浓度的标定(见实验:高锰酸钾标准溶液的配制与…

记一次普通的单表查询sql优化,去掉文件排序

一现象&#xff1a; 有空观察了线上某个sql语句执行计划&#xff0c;发现在500多毫秒左右&#xff0c;打算进行下优化。 二步骤&#xff1a; 对查询列assessment_periodic_id、assessment_user_id、create_time添加了组合索引并指定了倒叙。加入create_time 使查询结果不需要在…