【C++】const与类(const修饰函数的三种位置)

目录

const基本介绍

正文

前:

中:

后:

拷贝构造使用const


目录

const基本介绍

正文

前:

中:

后:

拷贝构造使用const


const基本介绍

const 是 C++ 中的修饰符,用于声明常量或表示不可修改的对象、函数或成员函数。

我们已经了解了const基本用法,我们先进行简单的回顾:

  1. 声明常量变量:使用 const 关键字来声明常量,一旦声明为常量,其值就不能被修改。例如:

     const int MAX_VALUE = 100;
  2. const修饰指针:

    a).const 修饰指针所指向的值不可被修改:

 int x = 5;const int* ptr = &x;*ptr = 10; // 错误:试图修改 const 指针所指向的值​int y = 10;ptr = &y; // 正确:const 指针本身可以被修改,指向不同的地址

b).const 修饰指针本身不可被修改:

 int x = 5;int* const ptr = &x;ptr = nullptr; // 错误:试图修改 const 指针本身的值​int y = 10;*ptr = y; // 正确:可以通过 const 指针修改指向的值

const修饰指针具体讲解:C语言:const函数修饰指针_const函数指针-CSDN博客

3.声明常量引用:使用 const 关键字修饰引用,表示引用的值不能被修改。例如:

 const int& ref = someVariable;

错误例子如下:

 int x = 5;const int& ref = x;ref = 10; // 错误:试图修改 const 引用的值

正文

 const char &getCharRef(const SomeClass &param) const{// 返回一个 const char& 类型的常量引用return someChar;}声明一个名为 constCharRef 的函数,该函数接收一个 const 类型的参数,并返回一个 const char& 类型的常量引用。同时,这个函数本身也是一个 const 成员函数示例中 MyClass 是一个类名,SomeClass 是作为参数传递给函数的某个类型,someChar 是一个 const 类型的字符变量、字符串字面值或者对象中的成员变量

看以上代码,在三个位置(文中称做前中后)都用const进行了修饰,那这三个点具体意义是什么呢?

前:

该const是修饰返回值类型

 const int getVal() {// 在这里实现函数的逻辑someVal = 10; // 修改对象中的成员变量return someVal;}

const 关键字用于修饰函数返回值前面的类型,表示函数返回的是一个常量值。这意味着,一旦 getVal() 函数返回一个常量值之后,返回的值就不能被修改,否则编译器会报错。

此处的 const 关键字并没有修饰函数本身。因此,即使在函数内部修改了对象中的成员变量,函数返回的仍然是一个常量值,不能被修改

中:

 void Add(const int val, const int constant){int result = val + constant;cout << "Result: " << result << endl;}

声明常量参数,该const则是为了保护数据,防止val和constant的值被修改

后:

声明常量成员函数:在类中声明成员函数时,使用 const 关键字修饰函数,表示该函数不会修改类的成员变量。该函数不会修改被隐式访问的对象,只能访问类的常量成员变量或调用其他常量成员函数

 class MyClass{public:int getValue() const;​private:int value;};​int MyClass::getValue() const{return value; // 只能读取成员变量的值}const char& operator[](size_t pos) const {assert(pos < _size);return _str[pos];}

函数声明中的 const 关键字修饰的是 this 指针,即表示该成员函数对应的实例对象在函数内部是只读的,不能修改对象的成员变量。因此,即使在函数内部尝试修改 _str 字符串,编译器也不会报错,但这样的操作违反了 const 限定的约定,也会导致代码运行时出现不可预期的问题。

  1. 在函数中断言 _size 大于 pos,确保访问 _str 数组元素时不会越界。

  2. 约束函数不能修改对象的成员变量,避免对对象状态造成破坏或影响调用者对对象状态的判断。

错误例子:

 class MyString{public:MyString(const char *str){_str = new char[std::strlen(str) + 1];std::strcpy(_str, str);}​// 错误的 const 成员函数char &operator[](size_t pos) const{return _str[pos]; // 修改了成员变量值}​private:char *_str;};​int main(){const MyString str("Hello");​str[0] = 'h'; // 错误:试图修改常量对象的值​return 0;}

拷贝构造使用const

使用拷贝构造时,最用const进行修饰,以防权限的放大

正确写法:

 Date(const Date &d){_year = d.year;_month = d.month;_year = d.year;}

不用const修饰:

 class Date{public:Date(int year, int month, int day) : _year(year), _month(month), _day(day) {}​// 错误的拷贝构造函数,没有使用 const 修饰符Date(Date &d){_year = d._year + 1;_month = d._month;_day = d._day;}​void PrintDate(){std::cout << "Year: " << _year << ", Month: " << _month << ", Day: " << _day << std::endl;}​private:int _year;int _month;int _day;};​int main(){Date d1(2023, 11, 21);d1.PrintDate(); // 输出:Year: 2023, Month: 11, Day: 21​Date d2 = d1;   // 调用拷贝构造函数d2.PrintDate(); // 输出:Year: 2024, Month: 11, Day: 21​return 0;}

出现的错误:

  1. 逻辑错误:拷贝构造函数中可能会修改成员变量的值,从而导致对象的状态发生改变。如果这不是我们的预期行为,那么就会导致程序逻辑错误。

  2. 破坏不变式:如果被拷贝对象的成员变量有一些不变式,那么拷贝构造函数的修改可能会破坏这些不变式,从而导致程序出错。

    假设有一个 Rectangle 类表示矩形,其中成员变量 widthheight 分别表示矩形的宽度和高度。该类定义了一个不变式,即 widthheight 都必须大于 0。

     class Rectangle {public:Rectangle(int width, int height) : _width(width), _height(height) {}​// 错误的拷贝构造函数,破坏了不变式Rectangle(Rectangle& other) {_width = other._width + 1;  // 修改宽度值_height = other._height;}​private:int _width;int _height;};

    在这个例子中,我们定义了一个错误的拷贝构造函数,其中修改了被拷贝对象的宽度值。这将导致破坏 Rectangle 类的不变式,即宽度必须大于 0。如果我们使用该拷贝构造函数创建一个新的矩形对象,它将具有无效的宽度值,从而导致程序出错

  3. 不可预知的行为:如果被拷贝对象是一个常量对象,那么在拷贝构造函数中修改其成员变量的值是未定义的行为,可能会导致不可预知的结果。

    假设有一个 Person 类表示人员信息,其中成员变量 name 表示人的姓名,而该类对象被声明为常量对象。

     class Person 
    {public:Person(const std::string& name) : _name(name) {}​// 错误的拷贝构造函数,常量对象被修改Person(Person& other) {_name = "Copy of " + other._name;  // 修改姓名}​private:std::string _name;};

    在这个例子中,我们定义了一个错误的拷贝构造函数,其中修改了被拷贝对象的姓名。如果我们使用该拷贝构造函数创建一个常量对象的副本,这将是未定义的行为,可能会导致不可预知的结果。由于常量对象的成员变量应该是不可修改的,所以在拷贝构造函数中修改成员变量将导致不可预知的状态和行为。

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

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

相关文章

【 OpenGauss源码学习 —— (hash_search)】

列存储&#xff08;hash_search&#xff09; 概述hash_search 函数hash_search_with_hash_value 函数calc_bucket 函数get_hash_entry 函数 补充知识 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和学术成果&#xff0c;力…

层层剥开Android14升级后异常弹框的神秘面纱

本篇文章将会通过研究源码的方式给您讲述Android系统升级到Android14后出现的两个异常弹框并给出消除它们的方案。闲话少叙&#xff0c;我们开始。 问题描述 在Android 14升级后&#xff0c;出现两个弹窗的异常情况。这里是异常的截图&#xff1a; 接下来&#xff0c;我们对这…

第一个Maven项目

&#xff08;一&#xff09;准备工作 1、从官网下载压缩包&#xff1a;apache-maven-3.5.4-bin&#xff0c;然后解压到D盘没有中文的目录。 2、配置环境变量: 在左下角win打开“设置”&#xff0c;搜索“高级系统设置”&#xff0c;点击“高级”&#xff0c;点击“环境变量”&…

酷开科技OS——Coolita,让智能大屏走向国际

10月23日&#xff0c;2023中国—东盟视听传播论坛在南宁举行。作为第五届中国—东盟视听周重要活动之一&#xff0c;本次论坛以“共享新成果、共创新视听、共建新家园”为主题。来自中国和东盟的300余名专家学者、业界代表通过主旨演讲、主题发言、圆桌对话等方式进行深入探讨&…

自学成为android framework高手需要准备哪些装备-千里马车载车机系统开发学习

背景 hi&#xff0c;粉丝朋友们&#xff1a; 大家好&#xff01;经常有很多学员买课同学都会问到需要准备哪些装备&#xff0c;我也回答了很多学员了&#xff0c;今天就搞一篇文章来统一说明一下&#xff0c;告诉一下大家如果你想从一个framework新手变成一个framework开发的高…

计算机网络实用工具之fping

简介 fping是一个类似ping的程序&#xff0c;它使用互联网控制消息协议&#xff08;ICMP&#xff09;回显请求来确定目标主机是否正在响应。fping与ping的不同之处在于&#xff0c;您可以在命令行上指定任意数量的目标&#xff0c;或者指定一个包含要ping的目标列表的文件。fp…

振弦传感器土压力计的安装及埋设方法

振弦传感器土压力计的安装及埋设方法 土压力计是一种测量土体内侧压力的仪器&#xff0c;常用于土体工程的安全监测和评估。以下是土压力计的安装及埋设方法&#xff1a; 1. 选择合适的位置&#xff1a;土压力计的安装位置应该在土体内的高应力区域&#xff0c;以便能够准确测…

Shell变量作用范围

目录 1、函数内的变量 2、shell脚本内的变量 3、进程内的变量 4、进程间的变量 5、终端间的变量 6、用户间的变量 总结 本文内容同微信公众号【凡登】&#xff0c;关注不迷路&#xff0c;学习上高速&#xff0c;欢迎关注共同学习。 什么是变量的作用范围&#xff1f; 变…

在Linux服务器中查找mysql的配置文件并修改其内容并保存,清空mysql8.0以上默认开启SSL的配置,防止odbc无法连接的问题

------每个命令输完记得按【enter】回车键------- 1、查找mysql的配置文件命令-mysql的配置文件默认名是my.cnf&#xff1a; find / -name my.cnf 2、查看显示的配置文件内容&#xff1a; cat /etc/my.cnf 3、修改配置文件的内容&#xff1a; 使用vi 或vim 命令 vi /etc…

推荐系统概述(PPT)

参考资料&#xff1a; 推荐系统系列之推荐系统概览&#xff08;上&#xff09; | 亚马逊AWS官方博客推荐系统系列之推荐系统概览&#xff08;下&#xff09; | 亚马逊AWS官方博客 目录如下&#xff1a; 推荐系统简介 推荐系统中常见概念 推荐系统中常用的评价指标 首页推荐…

请求的接口响应状态为已取消的原因

有趣的iframe问题 今天遇到一个问题&#xff0c;当点击了按钮----跳转页面时----F12键点击网络中的状态报了已取消&#xff0c;类型是 document说明是前端页面的问题&#xff0c;如果是xhr那可能是接口的问题。 原本是写了3个iframe,页面刷新的时候请求了第一个iframe,然后就…

随机微分方程的MATLAB数值求解

dt0.01; tout200; %总时间为2 xzeros(1,tout); x(1)0.5; %初始位置 mu0.2; sigma1; Wtsqrt(dt)*randn(1,tout); %产生随机序列Wt for t1:tout-1x(t1)x(t)mu*x(t)*dtsigma*x(t)*Wt(t); end t11:10:tout; %对原时间序列进行抽样 xtzeros(1,length(t1)); i1; for tt1xt(i)0.5*exp(…

招投标系统软件源码,招投标全流程在线化管理

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

【git-分布式版本控制工具】

Git git介绍 分布式版本控制系统工具 vs 集中式版本控制工具git安装 基于官网发布的最新版本2.31.1 安装讲解git命令 基于开发案例 详细讲解了git的常用命令git分支 分支特性 分支创建 分支转换 分支合并 代码合并冲突解决IDea 集成 git Github 创建远程库代码推送 PUSH代码…

HUAWEI华为MateBook X Pro 2022 12代酷睿版(MRGF-16)笔记本电脑原装出厂Windows11系统工厂模式含F10还原

链接&#xff1a;https://pan.baidu.com/s/1ZI5mR6SOgFzMljbMym7u3A?pwdl2cu 提取码&#xff1a;l2cu 华为原厂Windows11系统工厂包&#xff0c;带F10一键智能还原恢复功能。 自带指纹、面部识别、声卡、网卡、显卡、蓝牙等所有驱动、出厂主题壁纸、Office办公软件、华为…

深信服AC跨三层取mac,绑定ip/mac

拓扑图 目录 拓扑图 1.交换机配置团体名和版本号 2.配置跨三层取mac 3.配置策略 验证&#xff1a; “您的每一次阅读、点赞和分享&#xff0c;都是对我最大的鼓舞和动力。” 如果对亲爱您有所帮助&#xff0c;可以尝试支持一下博主&#xff0c;让博主更有动力 1.交换机配置…

Docker上部署mysql(超简单!!!)

拉取mysql镜像 运行如下命令 docker pull mysql:5.7 拉取成功 查看镜像 运行容器 此处部署最新版本的mysql docker run -d --name mysql -p 3307:3306 -e TZAsia/Shanghai -e MYSQL_ROOT_PASSWORD111 mysql --name mysql&#xff1a;给容器起个名字&#xff08;唯一&#xff…

可靠性工程师的发展之路

都是经验之谈&#xff0c;不懂产品&#xff0c;只靠理论 &#xff0c;注定行不通。可靠性工程师的成长&#xff0c;是一个专业与产品共同前进的道路。 1、轻易不要想着建可靠性体系。 如果可靠性还处在一穷二白的程度&#xff0c;建可靠性体系只会害了公司&#xff0c;不仅浪…

js中数组去重(数组中元素是对象)

一、使用 Set 对象&#xff1a; const arr [{ id: 1, name: A },{ id: 2, name: B },{ id: 1, name: A },{ id: 3, name: C } ];const result Array.from(new Set(arr.map(item > JSON.stringify(item)))).map(item > JSON.parse(item)); console.log(result); 二、…

bclinux aarch64 openeuler 20.03 LTS SP1 部署 fastCFS

基于已配置好的4个节点部署ceph-0 ceph-1 ceph-2 ceph-3&#xff08;早期ceph测试环境&#xff0c;名称就不修改了&#xff09; 获取fcfs.sh mkdir /etc/fcfs cd /etc/fcfs wget http://fastcfs.net/fastcfs/ops/fcfs.sh 配置/etc/fcfs/fcfs.settings # 要安装的集群版本号…