类和对象——const修饰的类的对象和函数

const修饰的类的对象和函数

  • const成员函数和const对象
    • 1 const成员函数
    • 2 调用关系
    • 3 const在成员函数中的位置
    • 4 取地址&及const取地址操作符重载

const成员函数和const对象

1 const成员函数

const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改
请添加图片描述
例如:

#include<iostream>
class Date {
public:Date(int year, int month, int day) {_year = year;_month = month;_day = day;}//编译器认为两个Print构成函数重载void Print() {using std::cout;using std::endl;cout << "Print()" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}void Print() const {using std::cout;using std::endl;cout << "Print()const" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}
private:int _year; // 年int _month; // 月int _day; // 日
};
int main() {Date d1(2022, 1, 13);d1.Print();const Date d2(2022, 1, 13);//编译器认为d2.Print(&d2),&d2的类型是const Date*,//会为d2匹配void Print() constd2.Print();return 0;
}

编译器的原则:永远是最匹配的,没有就找最合适的。权限可以缩小,但不可以放大。所以d1调用的是Print(),而d2调用的是Print() const

如果只有Print() const,则d1调用的是Print() const。例如:

#include<iostream>class Date {
public:Date(int year, int month, int day) {_year = year;_month = month;_day = day;}void Print() const {using std::cout;using std::endl;cout << "Print()const" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}
private:int _year; // 年int _month; // 月int _day; // 日
};int main() {Date d1(2022, 1, 13);d1.Print();return 0;
}

2 调用关系

const对象和const成员函数,它们与非const的对象和成员函数之间的关系:

  1. const对象不可以调用非const成员函数。权限放大。

因为非const成员函数可通过this指针间接修改对象,所以const对象不能将自身具有常属性的地址上传给this指针,防止权限放大。

参考样例:

#include<iostream>
class A {
public:void f1() {using std::cout;cout << "void f1()\n";}void f2() const {using std::cout;cout << "void f2()\n";}
};int main() {const A a;//a.f1();//不允许。a.f2();//允许,权限平移return 0;
}
  1. const对象可以调用const成员函数。权限缩小。
#include<iostream>
class A {
public:void f1() {using std::cout;cout << "void f1()\n";}void f2() const {using std::cout;cout << "void f2()\n";}
};int main() {A a;a.f2();//允许return 0;
}
  1. const成员函数内不可以调用其它的非const成员函数。
    因为const成员函数的this具有常属性,将this的值上传给非const成员函数,因为非const的成员函数不具有常属性的this,所以权限放大。
#include<iostream>
class A {
public:void f1() {using std::cout;cout << "void f1()\n";}void f2() const {using std::cout;cout << "void f2()\n";//f1();//不允许,权限放大}
};

在存在大量代码复用的类中需要特别注意。

  1. const成员函数内可以调用其它的const成员函数。权限缩小。
#include<iostream>
class A {
public:void f1() {using std::cout;cout << "void f1()\n";f2();//可以,权限缩小。}void f2() const {using std::cout;cout << "void f2()\n";}
};

3 const在成员函数中的位置

这是一个数组类:

#include<iostream>
#include<cstdlib>
class SeqList {
public:~SeqList() {free(a);}int& operator[](int i) const {//a向堆区申请内存,出了这里的作用域数据还在,可以传引用返回return a[i];}
private://c++11允许给内置类型成员初始值,甚至是调用公共库函数//但如果函数执行出错无法反馈int* a = (int*)malloc(sizeof(int) * 10);size_t size = 0;size_t capacity = 10;
};void print(const SeqList& a) {using std::cout;for (int i = 0; i < 10; i++) {cout << a[i] << ' ';a[i]++;//const只限制a本身的内容不可改变,}cout << "\n";
}int main() {SeqList a;using std::cout;for (int i = 0; i < 10; i++)a[i] = i;//修改堆区的数据print(a);print(a);return 0;
}

函数int& operator[](int i) const{}虽然对this指针本身用const修饰,但是函数返回值是堆区某个位置的引用,所以[]并没有对堆区的数据进行限制。

数组类需要通过[]进行修改和访问数据,因此在部分场合我们想通过[]修改数据,在另一场合又希望这个数据无法被修改。

所以需要提供两个[]的重载,一个只读,一个可读可写,此时编译器会匹配最合适的[]。只读的[]重载一般需要用两个const进行限制。

#include<iostream>
#include<cstdlib>
class SeqList {
public:~SeqList() {free(a);}int& operator[](int i) {//对象可读可写return a[i];}const int& operator[](int i) const{//对象只读return a[i];}
private:int* a = (int*)malloc(sizeof(int) * 10);size_t size = 0;size_t capacity = 10;
};void print(const SeqList& a) {using std::cout;for (int i = 0; i < 10; i++) {cout << a[i] << ' ';//a[i]++;//编译器为const SeqList匹配形参为const SeqList的operator[],所以不可修改}cout << "\n";
}int main() {SeqList a;using std::cout;for (int i = 0; i < 10; i++)a[i] = i;//修改堆区的数据print(a);return 0;
}

还是需求问题,程序员想要用户不修改什么数据,就加const对类的成员函数进行限制。

4 取地址&及const取地址操作符重载

默认成员函数的取地址&重载一般不用重新定义 ,编译器默认会生成。其中用到了const修饰this时构成的重载。

class Date {
public:Date* operator&() {return this;}const Date* operator&() const {//参考上文的数组类return this;}
private:int _year; // 年int _month; // 月int _day; // 日
};

这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如不想被别人取到对象的有效地址,于是给个假地址返回。

#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS 1
#endif#include<iostream>
using std::cout;
class Date {
public:Date(int year=1900,int month=0,int day=0){_year = year;_month = month;_day = day;}Date* operator&() {return nullptr;}const Date* operator&() const {return nullptr;}
private:int _year; // 年int _month; // 月int _day; // 日
};int main() {Date a;const Date b;cout << (&a) << '\n' << (&b);return 0;
}

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

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

相关文章

【DeepSeek-R1背后的技术】系列十三:归一化方式介绍(BatchNorm, LayerNorm, Instance Norm 和 GroupNorm)

【DeepSeek-R1背后的技术】系列博文&#xff1a; 第1篇&#xff1a;混合专家模型&#xff08;MoE&#xff09; 第2篇&#xff1a;大模型知识蒸馏&#xff08;Knowledge Distillation&#xff09; 第3篇&#xff1a;强化学习&#xff08;Reinforcement Learning, RL&#xff09;…

高压风机专用32位单片机MM32SPIN080G

专为高压风机量身打造的32位高性能单片机&#xff0c;拥有卓越的处理性能和丰富的接口资源&#xff0c;能够应对工业级应用的严苛要求。 RAMSUN高性能单电机控制SOC单片机——32位MM32SPIN080G&#xff0c;基于Cortex-M0内核构建&#xff0c;集成了200V三相N沟道栅极驱动器。它…

计算机毕设-基于springboot的融合多源高校画像数据与协同过滤算法的高考择校推荐系统的设计与实现(附源码+lw+ppt+开题报告)

博主介绍&#xff1a;✌多个项目实战经验、多个大型网购商城开发经验、在某机构指导学员上千名、专注于本行业领域✌ 技术范围&#xff1a;Java实战项目、Python实战项目、微信小程序/安卓实战项目、爬虫大数据实战项目、Nodejs实战项目、PHP实战项目、.NET实战项目、Golang实战…

nodejs将pdf转换成图片并提取图片内容

pdf2pic 安装方法 安装文档地址&#xff1a;https://github.com/yakovmeister/pdf2image/blob/HEAD/docs/gm-installation.md Windows下载下面两个文件&#xff0c;安装时没有自动设置环境变量&#xff0c;要分别设置到环境变量 Download Ghostscript Windows: https://gith…

机器学习--(随机森林,线性回归)

一、集成学习方法之随机森林 集成学习的基本思想就是将多个分类器组合&#xff0c;从而实现一个预测效果更好的集成分类器。集成算法可以说从一方面验证了中国的一句老话&#xff1a;三个臭皮匠&#xff0c;赛过诸葛亮。集成算法大致可以分为&#xff1a;Bagging&#xff0c;B…

RabbitMQ 的工作模式

目录 工作模式 Simple&#xff08;简单模式&#xff09; Work Queue&#xff08;工作队列&#xff09; Publish/Subscribe&#xff08;发布/订阅&#xff09; Exchange&#xff08;交换机&#xff09;? Routing&#xff08;路由模式&#xff09; Topics&#xff08;通配…

24.[前端开发-JavaScript基础]Day01-插件配置-变量-数据

一、邂逅JavaScript 1 认识编程语言 前端的三大核心 计算机语言 编程语言 常见的编程语言 2 编程语言发展历史 编程语言的发展历史 – 机器语言 编程语言的发展历史 – 汇编语言 编程语言的发展历史 – 高级语言 机器语言和高级语言 3 JavaScript的历史 认识JavaScript J…

uni-app集成sqlite

Sqlite SQLite 是一种轻量级的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;广泛应用于各种应用程序中&#xff0c;特别是那些需要嵌入式数据库解决方案的场景。它不需要单独的服务器进程或系统配置&#xff0c;所有数据都存储在一个单一的普通磁盘文件中&am…

為什麼使用不限量動態住宅IP採集數據?

在瞭解“不限量動態住宅IP數據採集”之前&#xff0c;我們需要先搞清楚什麼是“動態住宅IP”。簡單來說&#xff0c;動態IP是一種會定期變化的IP地址&#xff0c;通常由互聯網服務提供商&#xff08;ISP&#xff09;分配給家庭用戶。與固定IP&#xff08;靜態IP&#xff09;不同…

多模态人物视频驱动技术回顾与业务应用

一种新的商品表现形态&#xff0c;内容几乎存在于手淘用户动线全流程&#xff0c;例如信息流种草内容、搜索消费决策内容、详情页种草内容等。通过低成本、高时效的AIGC内容生成能力&#xff0c;能够从供给端缓解内容生产成本高的问题&#xff0c;通过源源不断的低成本供给倒推…

navicat161_premium_cs_x64 安装与使用

navicat161_premium_cs_x64 安装与使用https://mp.weixin.qq.com/s/eE90x59hDVdk-shXSvICbA

自学c++之类、对象、封装

class 类名{int a;//属性 public://权限操作&#xff1b; } 1、权限 public(公共权限&#xff09;类内可以访问&#xff0c;类外可以访问protected&#xff08;保护权限&#xff09;类内可以访问&#xff0c;类外不可以访问&#xff08;儿子可以访问父亲中的保护内容&#xf…

mmdetection框架下使用yolov3训练Seaships数据集

之前复现的yolov3算法采用的是传统的coco数据集&#xff0c;这里我需要在新的数据集上跑&#xff0c;也就是船舶检测方向的SeaShips数据集&#xff0c;这里给出教程。 Seaships论文链接&#xff1a;https://ieeexplore.ieee.org/stamp/stamp.jsp?tp&arnumber8438999 一、…

基于 Python 的网络监控系统开发全解

基于 Python 的网络监控系统开发全解 本文详细阐述如何使用 Python 开发一个网络监控系统。通过介绍系统的功能需求&#xff0c;如网络设备状态监测、流量统计、故障告警等&#xff0c;展示利用 Python 丰富的库实现这些功能的过程&#xff0c;包括scapy进行网络数据包捕获、p…

【多模态处理篇三】【DeepSeek语音合成:TTS音色克隆技术揭秘】

最近帮某明星工作室做AI语音助手时遇到魔幻需求——要求用5秒的咳嗽声克隆出完整音色!传统TTS系统直接翻车,生成的语音像得了重感冒的电音怪物。直到祭出DeepSeek的TTS音色克隆黑科技,才让AI语音从"机器朗读"进化到"声临其境"。今天我们就来扒开这个声音…

基于YOLO11深度学习的苹果叶片病害检测识别系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

一篇docker从入门到精通

Docker Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现虚拟化。容器是完全使用沙盒机制&#xff0c;相互之间不会有任何接口&#xff08;类似 iP…

w803|联盛德|WM IoT SDK2.X测试|window11|TOML 文件|外设|TFT_LCD|测试任务|(5):TFT_LCD_LVGL示例

TFT_LCD_LVGL 功能概述 此应用程序是使用 WM IoT SDK 进行 LVGL 功能的示例。它演示了如何初始化 TFT LCD 设备&#xff0c;并创建 LVGL DEMO Task 进行 LVGL 模块的初始化&#xff0c;并展示 LVGL 原生的不同 Demo 场景, 例如&#xff1a; Widgets, Music Player, Benchmark…

openlayers结合turf geojson面获取面积和中心点

在 OpenLayers 中绘制 GeoJSON 面要素并计算面积和中心点&#xff0c;可以结合 OpenLayers 的 ol/format/GeoJSON 模块将 GeoJSON 数据转换为 OpenLayers 的 Feature&#xff0c;然后使用 Turf.js 进行计算。示例代码如下 import Map from ol/Map; import View from ol/View; …

nginx 搭建 IPv6 -> IPv4 反向代理服务器

背景 在实际生产过程中&#xff0c;由于各种原因&#xff0c;我们的在线服务搭建在火山云服务器上&#xff0c;使用火山云包括 ECS、CLB、PLB 等组件进行网络通信&#xff0c;并且通过专线接受来自某公司内部流量。但是在大概 22~23 年&#xff0c;某公司要把所有网络流量变为…