C++ 常量对象及常量成员函数

#include <stdexcept>
#include <iostream>struct Vector2
{float x;float y;// 通过[0]或[1]访问x或y分量float& operator[](int index){switch (index){case 0: return x;case 1: return y;default:throw std::out_of_range("Invalid Vector2 index!");}}const float& operator[](int index) const{switch (index){case 0: return x;case 1: return y;default:throw std::out_of_range("Invalid Vector2 index!");}}// 减法操作符Vector2 operator-(const Vector2 &other) const{return {x - other.x, y - other.y};}
};

在这个示例中,通过重载 operator[] 函数来实现索引器的功能。这个函数接受一个整数参数 index ,并根据其值返回相应的成员( xy )的引用。如果index的值无效(不是0或1),它将抛出一个 std::out_of_range 异常。operator- 被声明为一个 const 成员函数,这样就可以在常量对象上调用它。

使用示例:

int main()
{Vector2 vec;vec[0] = 1.0f;vec[1] = 2.0f;std::cout << "x: " << vec[0] << ", y: " << vec[1] << std::endl;const Vector2 zero = {0.0f, 0.0f};Vector vec2 = zero - vec;std::cout << "x: " << vec2[0] << ", y: " << vec2[1] << std::endl;return 0;
}

在上面的示例中,首先创建了一个 Vector2 类型的对象 vec ,使用索引器将值赋给了x和y分量。然后,使用索引器获取了x和y分量的值并进行打印。接着,创建了一个名为 zero 的常量 Vector2 对象,它的 xy 分量都是 0。使用减法操作符 Vector2 operator-(const Vector2 &other) constzero 减去 vec,得到一个新的向量 vec2,然后打印了 vec2xy 分量的值。

float& operator[](int index)const float& operator[](int index) const 是C++中的两个不同的函数签名,它们的区别在于是否允许在调用该函数时修改对象的成员。

const float& operator[](int index) constVector2 operator-(const Vector2 &other) const 是为了提供对常量对象的支持,它可以在常量对象上被调用,但只能读取成员,不能修改它们。

如果代码中不会出现对常量对象的索引操作,可以只保留非常量版本的 float& operator[](int index),这样会简化代码并提供更直接的方式来访问和修改成员。

然而,如果代码可能会涉及到常量对象,那么保留两个版本会提供更大的灵活性,并且符合良好的编程实践,因为它允许你在不同的情况下以一致的方式使用索引器。

在C++中,"涉及到常量对象"指的是在代码中使用了一个被声明为 const 的对象,或者在一个 const 成员函数中操作对象。
例如,考虑以下情况:

struct Vector2
{float x;float y;const float& operator[](int index) const{switch (index){case 0: return x;case 1: return y;default:throw std::out_of_range("Invalid Vector2 index!");}}
};int main()
{const Vector2 vec = {1.0f, 2.0f};float value = vec[0]; // 这里涉及到了一个常量对象vecreturn 0;
}

在上面的例子中,vec 是一个 const Vector2 类型的对象,因此它被视为一个常量对象。当你在一个常量对象上调用 operator[] 时,编译器会使用 const 版本的operator[],并且它只返回一个对成员的常量引用,不允许修改。

因此,在这个例子中,float value = vec[0]; 是合法的,因为它只是读取了 vecx 分量,但是任何尝试修改 vec[0] 的行为将会导致编译错误。

在C++中,将一个成员函数声明为 const 的作用是告诉编译器,这个成员函数不会修改对象的状态。也就是说,在一个 const 成员函数内部,你不能修改对象的成员变量。

在括号 () 后面的 const 称为成员函数的常量修饰符。这是为了在对象的常量实例上调用该函数时,确保该函数不会修改对象的状态。

class MyClass {
public:void someFunction() const{// 在这里,可以读取成员变量,但不能修改它们}void someOtherFunction(){// 在这里,可以读取并修改成员变量}
};

如果在一个常量对象上调用了一个非常量成员函数,编译器将会报错。

const MyClass obj;
obj.someFunction(); // 合法,因为 someFunction 被声明为 constobj.someOtherFunction(); // 编译错误,因为 someOtherFunction 没有被声明为 const

所以,const 在成员函数声明中的位置非常重要,它指定了这个函数是否可以在一个常量对象上被调用。

要注意,如果一个成员函数不会修改对象的状态,最好将其声明为 const,以便在需要时可以在常量对象上调用它。反之,如果一个成员函数会修改对象的状态,就不应该被声明为 const

在C++中,常量成员函数被设计成可以在常量对象上调用,也可以在非常量对象上调用。这是因为常量成员函数不会修改对象的状态,所以它们可以安全地在常量对象上执行。

例如:

class MyClass {
public:int getValue() const{return value;}private:int value;
};int main() {MyClass obj;obj.getValue(); // 在非常量对象上调用常量成员函数,是合法的const MyClass constObj;constObj.getValue(); // 在常量对象上调用常量成员函数,也是合法的return 0;
}

在上述示例中,getValue() 是一个常量成员函数,它可以在常量对象 constObj 上调用,也可以在非常量对象 obj 上调用。

所以,常量成员函数可以提供一种在对象的不同状态下执行相同操作的方法,而不必担心意外修改对象的状态。

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

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

相关文章

springboot和vue:十、vue2和vue3的差异+组件间的传值

首先用vue-cli创建一个vue2的项目。 vue2和vue3的差异 main.js的语法有所差别。 vue2是 import Vue from vue import App from ./App.vuenew Vue({render: h > h(App), }).$mount(#app)vue3是 import { createApp } from vue import App from ./App.vuecreateApp(App).…

Flask 进行 Web 开发时,常见的错误

ImportError: No module named ‘flask’ 错误描述&#xff1a; 这个错误表示 Python 找不到 Flask 模块。解决方法&#xff1a; 确保已经正确安装了 Flask 模块。你可以使用以下命令来安装 Flask&#xff1a;pip install flaskAttributeError: ‘module’ object has no attri…

Java虚拟机内存模型

JVM虚拟机将内存数据分为&#xff1a; 程序计数器、虚拟机栈、本地方法栈、Java堆、方法区等部分。 程序计数器用于存放下一条运行的指令&#xff1b; 虚拟机栈和本地方法栈用于存放函数调用堆栈信息&#xff1b; Java堆用于存放Java程序运行时所需的对象等数据&#xff1b…

学习笔记|串口通信的基础知识|同步/异步|RS232|常见的串口软件的参数|STC32G单片机视频开发教程(冲哥)|第二十集:串口通信基础

目录 1.串口通信的基础知识串口通信(Serial Communication)同步/异步&#xff1f;全双工&#xff1f;常见的串口软件的参数 2.STC32的串口通信实现原理引脚选择&#xff1a;实现分时复用模式选择串口1模式1&#xff0c;模式1波特率计算公式 3.串口通信代码实现编写串口1通信程序…

前端 | AjaxAxios模块

文章目录 1. Ajax1.1 Ajax介绍1.2 Ajax作用1.3 同步异步1.4 原生Ajax 2. Axios2.1 Axios下载2.2 Axios基本使用2.3 Axios方法 1. Ajax 1.1 Ajax介绍 Ajax: 全称&#xff08;Asynchronous JavaScript And XML&#xff09;&#xff0c;异步的JavaScript和XML。 1.2 Ajax作用 …

用pandas处理数据时,使变量能够在不同的Notebook会话页面进行传递,魔法命令%store

【需求来源】 在使用pandas时&#xff0c;有的时候我想将.ipynb文件分开写 其中一个写清洗数据代码另外一个写数据可视化代码 【解决方案】 但是会涉及到变量转移问题&#xff0c;这个时候我通常使用的方法是&#xff1a; 1、在清洗完数据后导出到本地 2、在文件后面增加当…

vue3+elementPlus:el-tree复制粘贴数据功能,并且有弹窗组件

在tree控件里添加contextmenu属性表示右键点击事件。 因右键自定义菜单事件需要获取当前点击的位置&#xff0c;所以此处绑定动态样式来控制菜单实时跟踪鼠标右键点击位置。 //html <div class"box-list"><el-tree ref"treeRef" node-key"id…

android 不同进程之间数据传递

1.handler android.os.Message是定义一个Messge包含必要的描述和属性数据&#xff0c;并且此对象可以被发送给android.os.Handler处理。属性字段&#xff1a;arg1、arg2、what、obj、replyTo等&#xff1b;其中arg1和arg2是用来存放整型数据的&#xff1b;what是用来保存消息标…

python+selenium实现UI自动化(入门篇)

一、基础准备。 python环境安装&#xff0c;参考&#xff1a;CSDN pycharm安装&#xff0c;参考&#xff1a;CSDN 谷歌浏览器驱动配置&#xff0c;参考&#xff1a;CSDN二、新建pycharm项目 截图中&#xff0c;上面是项目地址&#xff08;可以提前在指定位置创建文件夹&#xf…

20 个超级有用的 JavaScript 技巧,让你的工作更轻松

今天这篇文章&#xff0c;我将跟大家分享20个我自己收藏使用的JavaScript技巧&#xff0c;希望今天这篇文章里的内容能够帮助到你&#xff0c;让你的工作更高效&#xff01;更轻松&#xff01;我们现在开始吧。 1. 多条件 if 语句 将多个值放入一个数组中&#xff0c;然后调用…

Redis 主从复制及哨兵模式

目录 1 Redis 主从复制 1.1 主从复制的作用 1.2 主从复制流程 2 搭建Redis 主从复制 2.1 安装 Redis 2.2 修改 Redis 配置文件&#xff08;Master节点操作&#xff09; 2.3 修改 Redis 配置文件&#xff08;Slave节点操作&#xff09; 2.4 验证主从效果 3 Redis 哨兵模…

数据结构——排序算法(C语言)

本篇将详细讲一下以下排序算法&#xff1a; 直接插入排序希尔排序选择排序快速排序归并排序计数排序 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某写关键字的大小&#xff0c;按照递增或递减0排列起来的操作。 稳定性的概念…

horizontal image flip(Neon优化)

1、原始代码 这个代码非常简单,就是将同一行的像素进行反转,我们需要注意,这里的像素是RGBA,因此一个像素共32位 uint32_t line; // 1. For an image of width w and height h, for all lines in the image, do the following. for (line = 0; line < h; line++) {uin…

JAVA开发中常用RDMS

一、前言 JAVA的开发离不开数据库的支持&#xff0c;常见的有关系型数据库和非关系型数据库。java除了处理不依赖与数据库的通信技术。很多的java项目或者应用程序都需要建立在数据库的基础上。所以java开发早已经不是单纯的java开发&#xff0c;更多的是基于对数据的处理&…

一文教你如何快速备考云计算HCIE 3.0 !

大家好&#xff0c;在誉天实验辅导老师的耐心帮助下&#xff0c;本人在9月21日的云计算HCIE 3.0考试已顺利通过&#xff0c;很高兴有这个机会给大家分享备考的经历&#xff0c;希望对还在备考的同学能有一定的帮助。 备考准备 在云计算HCIE3.0的课程学习结束之后&#xff0c;就…

ASPICE标准快速掌握「总目录」

欢迎大家来到雪云飞星的《ASPICE标准快速掌握》,开始前博主先列出本专栏学习的大纲,同时这也可以作为大家学习ASPICE协议知识点的参考。本专栏可以帮助大家快速掌握如何在项目中使用ASPICE,ASPICE的学习通常仅需要半天时间左右,掌握方法后完全就可以结合快查表来指导具体项…

一款构建Python命令行应用的开源库

1 简介 当我们编写 Python 程序时&#xff0c;我们经常需要与用户进行交互&#xff0c;接收输入并输出结果。Python 提供了许多方法来实现这一点&#xff0c;其中一个非常方便的方法是使用 typer 库。typer 是一个用于构建命令行应用程序的 Python 库&#xff0c;它使得创建命令…

使用MATLAB进行傅里叶变换

1、定义 T1;% 周期0-1 N20;% 最大谐波 k-N:N;% -20:20——-20表示a_(20)e^(j*20*w0*t) N1length(k);%N141 % ceil(N1/2)21%即21是N1的中位数tlinspace(0,T,100); Ntlength(t); ttlinspace(-4*T,4*T,1024); Nttlength(tt);2、原函数 w02*pi/T; % 0-T xt(t>T/4).* 1.0; fig…

嵌入式学习笔记(49)由I2C学通信时序

10.2.1什么是时序&#xff1f; 字面意思&#xff0c;时序就是时间顺序&#xff0c;实际上在通信中时序就是通信线上按照时间顺序发生的电平变化&#xff0c;以及这些变化对通信的意义就叫时序。 10.2.2 I2C总线空闲状态、起始位、结束位 (1)I2C总线上有1个主设备&#xff0c…

二叉树的顺序存储——堆——初识堆排序

前面我们学过可以把完全二叉树存入到顺序表中&#xff0c;然后利用完全二叉树的情缘关系&#xff0c;就可以通过数组下标来联系。 但是并不是把二叉树存入到数组中就是堆了&#xff0c;要看原原来的二叉树是否满足&#xff1a;所有的父都小于等于子&#xff0c;或者所有的父都…