当前位置: 首页 > news >正文

C++基础(七):类和对象(中-2)

      上一篇博客学的默认成员函数是类和对象的最重要的内容,相信大家已经掌握了吧,这一篇博客接着继续剩下的内容,加油!

目录

一、const成员(理解)

1.0 引入

1.1 概念

1.2  总结

1.2.1 对象调用成员函数

1.2.2 成员函数调用成员函数

二、取地址及const取地址操作符重载(了解)

三、日期类的重新规范书写

3.1 Date.h

3.2 Date.cpp


一、const成员(理解)

1.0 引入

      先看代码:

#include <iostream>
using namespace std;
class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}private:int _year;     // 年int _month;   // 月int _day;     // 日
};void func( Date d)    这里的形参为对象,它会进行调用一次拷贝构造
{d.Print();
}int main()
{Date d1(2024, 7, 20);func(d1);             这里直接传递的是对象return 0;
}

程序运行结果:、

 

再看代码: 

#include <iostream>
using namespace std;
class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}private:int _year;     // 年int _month;   // 月int _day;     // 日
};void func( const Date& d)  这里的形参为对象的引用/别名,它就是d1的别名,同一个实体,不会进行拷贝构造                     加const代表我引用这个对象,但是我不会通过引用从而修改这个对象!
{d.Print();
}int main()
{Date d1(2024, 7, 20);func(d1);             这里直接传递的是对象return 0;
}

程序运行结果:

为什么会是上面的结果???

其实,这就是我们在入门阶段学习的指针的相互赋值,指针的能力不能出现扩张,这样编译器会报错!那又该如何解决呢?  这便引入了要学习的const成员。

  void Print()   const    //  void Print(const Date* this )   {cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}

1.1 概念

       将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数 隐含的this指针,表明在该成员函数中不能对类的任何成员变量进行修改。(const修饰的指针)比如:_year= 2026; (编译器底层:this->_year=2026;) 这是不允许的!

复习:

  1. const  Date* p1 :  const修饰的是指针指向的对象,也就是说不可以通过这个指针来修改对象的数据!
  2. Date  const * p2 : 和上面的一样,const修饰的是指针指向的对象,也就是说不可以通过这个指针来修改对象的数据!
  3. Date   * const p3 : const修饰的是指针p3本身,也就是说,不可以修改指针的指向!
  4. const  Date* const  p4: const既修饰指针指向的对象,也就是说不可以通过这个指针来修改对象的数据!也修饰了指针p3本身,也就是说,不可以修改指针的指向!(双重限定)

1.2  总结

1.2.1 对象调用成员函数

1. const对象可以调用非const成员函数吗?

      不可以。const对象只能调用const成员函数,因为const对象不能被修改,而非const成员函数可能会修改对象的状态。

class MyClass 
{public:void nonConstFunc() {// 修改对象状态的代码}void constFunc() const {// 不修改对象状态的代码}
};int main(){const MyClass obj;obj.constFunc();     // 可以调用obj.nonConstFunc();  // 编译错误return 0;}

2. 非const对象可以调用const成员函数吗?

       可以。const对象可以调用const成员函数,因为const成员函数保证不会修改对象的状态。

class MyClass 
{
public:void nonConstFunc() {// 修改对象状态的代码}void constFunc() const {// 不修改对象状态的代码}
};int main() 
{MyClass obj;obj.constFunc();     // 可以调用obj.nonConstFunc();  // 也可以调用return 0;
}

1.2.2 成员函数调用成员函数

1. const成员函数内可以调用其它的非const成员函数吗?

       不可以。const成员函数不能调用非const成员函数,因为这会违反const成员函数不修改对象状态的承诺。

class MyClass
{
public:void nonConstFunc() {// 修改对象状态的代码}void constFunc() const {nonConstFunc();  // 编译错误}
};int main() 
{MyClass obj;obj.constFunc();return 0;
}

2. 非const成员函数内可以调用其它的const成员函数吗?

      可以。const成员函数可以调用const成员函数,因为const成员函数不会修改对象的状态。

class MyClass 
{
public:void nonConstFunc() {constFunc();  // 可以调用// 修改对象状态的代码}void constFunc() const{// 不修改对象状态的代码}
};int main() 
{MyClass obj;obj.nonConstFunc();return 0;
}

理解记忆,明确一个原则:只要调用成员函数都涉及this指针,我们就要分析指针类型的变化。

 

结论:什么时候会给成员函数加const?

         只要成员函数中不需要修改成员变量最好都加上const,但是,如果你需要改变成员变量,你就不能加const!因为这个时候const对象可以调用这个const修饰的成员函数,非const对象(普通对象)也可以调用这个const修饰的成员函数。

二、取地址及const取地址操作符重载(了解)

这两个默认成员函数一般不用重新定义 ,编译器默认会生成。

#include <iostream>
using namespace std;
class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print()  const{cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}/*自己实现的取地址运算符重载函数以及const取地址操作符重载函数,构成函数重载Date* operator&(){return this;//return nullptr;}const Date* operator&() const{cout<< "operator&()"<<endl;return this;//return nullptr;}*/private:int _year;     // 年int _month;   // 月int _day;     // 日
};void func( const Date& d)
{d.Print();
}int main()
{Date d1(2024, 7, 20);Date d2(2024, 7, 21);const Date d3(2024, 7, 22);cout << &d1 << endl; //调用的是取地址运算符重载函数,不实现的话,编译器默认会生成cout << &d2 << endl; //调用的是取地址运算符重载函数,不实现的话,编译器默认会生成cout << &d3 << endl;  //调用的是const取地址操作符重载函数,不实现的话,编译器默认会生成return 0;
}

         这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如不想让别人获取到指定的内容!

三、日期类的重新规范书写

3.1 Date.h

#pragma once
#include <iostream>
using namespace std;class Date
{
public:int GetMonthDay(int year, int month)  const;Date(int year = 0, int month = 1, int day = 1);Date(const Date& d);~Date();void  Print() const;/*运算符重载*/bool  operator<(const Date& d)   const;bool  operator==(const Date& d)  const;bool  operator<=(const Date& d)  const;bool  operator>(const Date& d)   const;bool  operator>=(const Date& d)  const;bool  operator!=(const Date& d)  const;Date& operator=(const Date& d);Date  operator+(int day)         const;Date& operator+=(int day);       //不能加Date  operator-(int day)         const;Date& operator-=(int day);       //不能加Date& operator++();             //不能加Date  operator++(int);Date& operator--();Date  operator--(int);int   operator-(const Date& d) const;private:int _year;int _month;int _day;
};

3.2 Date.cpp

#define _CRT_SECURE_NO_WARNINGS 1#include "Date.h"int Date::GetMonthDay(int year, int month)    const  
{static int days[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };int day = days[month];if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))  {day += 1;}return day;
}Date::Date(int year , int month , int day )   //缺省参数只在声明中给
{if (year >= 0 && month >= 1 && month <= 12 && day >= 1 && day <= GetMonthDay(year, month)){_year = year;_month = month;_day = day;}else{cout << "非法日期" << endl;}
}Date::Date(const Date& d)
{_year = d._day;_month = d._month;_day = d._day;
}Date::~Date()
{cout << "~Date()" << endl;
}void Date::Print()  const
{cout << _year << "-" << _month << "-" << _day << endl;
}bool Date::operator<(const Date& d)    const
{if (_year < d._year){return true;}else if (_year == d._year && _month < d._month){return true;}else if (_year == d._year && _month == d._month && _day < d._day){return true;}return false;
}bool   Date::operator==(const Date& d)  const
{if (_year == d._year && _month == d._month && _day == d._day){return true;}return false;}bool   Date::operator<=(const Date& d)  const
{return *this < d || *this == d;           }bool   Date::operator>(const Date& d)  const
{return !(*this <= d);            }bool  Date::operator>=(const Date& d)   const
{return !(*this < d);           }bool   Date::operator!=(const Date& d)   const
{return !(*this == d);          }Date& Date::operator=(const Date& d)         
{if (this != &d)         {_year = d._day;_month = d._month;_day = d._day;}return *this;
}Date Date::operator+(int day)  const
{Date ret(*this);     ret._day += day;while (ret._day > GetMonthDay(ret._year, ret._month)){ret._day -= GetMonthDay(ret._year, ret._month);ret._month++;if (ret._month == 13)   {ret._year++;ret._month = 1;     }}return ret;
}Date& Date::operator+=(int day)
{if (day < 0){return *this -= -day;}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);++_month;if (_month == 13)   {++_year;_month = 1;     }}return *this;        
}Date Date::operator-(int day) const
{Date ret(*this);     ret._day -= day;while (ret._day <= 0)   {--ret._month;if (ret._month == 0){--ret._year;    ret._month = 12;   }ret._day += GetMonthDay(ret._year, ret._month);}return ret;}Date& Date::operator-=(int day)
{if (day < 0){return *this += -day;  }_day -= day;while (_day <= 0)   {--_month;if (_month == 0){--_year;    _month = 12;   }_day += GetMonthDay(_year, _month);}return *this;
}Date& Date::operator++()
{*this += 1;return *this;     
}Date Date::operator++(int)
{Date tmp(*this);  *this += 1;return tmp;  
}Date& Date::operator--()
{*this -= 1;return *this;     
}Date Date::operator--(int)
{Date tmp(*this);  *this -= 1;return tmp;   
}int Date::operator-(const Date& d) const
{int flag = 1;Date max = *this;       Date min = d;if (*this < d)       {max = d;min = *this;flag = -1;}int n = 0;while (min != max){++min;++n;}return n * flag;
}

        至此,C++面向对象-中全部内容就学习完毕,这一节内容比较重要,建议多看几遍,认真复习消化,熟练使用,C++相对来说较为复杂,我们应该时刻理清自己的思路,耐下心来,一点点积累, 星光不问赶路人,加油吧,感谢阅读,如果对此专栏感兴趣,点赞加关注! 

相关文章:

C++基础(七):类和对象(中-2)

上一篇博客学的默认成员函数是类和对象的最重要的内容&#xff0c;相信大家已经掌握了吧&#xff0c;这一篇博客接着继续剩下的内容&#xff0c;加油&#xff01; 目录 一、const成员&#xff08;理解&#xff09; 1.0 引入 1.1 概念 1.2 总结 1.2.1 对象调用成员函数 …...

对秒杀的思考

一、秒杀的目的 特价商品&#xff0c;数量有限&#xff0c;先到先得&#xff0c;售完为止 二、优惠券的秒杀 和特价商品的秒杀是一样的&#xff0c;只不过秒杀的商品是优惠券 三、秒杀的需求 秒杀前&#xff1a;提前将秒杀商品&#xff0c;存放到Redis秒杀中&#xff1a;使…...

数据结构预科

在堆区申请两个长度为32的空间&#xff0c;实现两个字符串的比较【非库函数实现】 要求&#xff1a; 1> 定义函数&#xff0c;在对区申请空间&#xff0c;两个申请&#xff0c;主函数需要调用2次 2> 定义函数&#xff0c;实现字符串的输入&#xff0c;void input(char …...

想做亚马逊测评技术需要解决哪些问题,有哪些收益?

现在真正有亚马逊测评技术的人赚的盆满钵满&#xff0c;有些人看到别人赚取就自己盲目去做&#xff0c;买完了账号和设备就感觉自己懂了&#xff0c;却不知里面的水深着&#xff0c;花了钱却没有掌握真正的技术&#xff0c;号莫名其妙就封完了&#xff0c;而每一次大风控注定要…...

1117 数字之王

solution 判断现有数字是否全为个位数 全为个位数&#xff0c;找出出现次数最多的数字&#xff0c;并首行输出最多出现次数&#xff0c;第二行输出所有出现该次数的数值不全为个位数 若当前位数值为0&#xff0c;无需处理若当前位数值非0&#xff0c;则每位立方相乘&#xff0…...

关于ORACLE单例数据库中的logfile的切换、删除以及添加

一、有关logfile的状态解释 UNUSED&#xff1a; 尚未记录change的空白group&#xff08;一般会出现在loggroup刚刚被添加&#xff0c;或者刚刚使用了reset logs打开数据库&#xff0c;或者使用clear logfile后&#xff09; CURRENT: 当前正在被LGWR使用的gro…...

Linux高并发服务器开发(十三)Web服务器开发

文章目录 1 使用的知识点2 http请求get 和 post的区别 3 整体功能介绍4 基于epoll的web服务器开发流程5 服务器代码6 libevent版本的本地web服务器 1 使用的知识点 2 http请求 get 和 post的区别 http协议请求报文格式: 1 请求行 GET /test.txt HTTP/1.1 2 请求行 健值对 3 空…...

人工智能系列-NumPy(二)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 链接数组 anp.array([[1,2],[3,4]]) print(第一个数组&#xff1a;) print(a) print(\n) bnp.array([[5,6],[7,8]]) print(第二个数组&#xff1a;) print(b) print(\n) print…...

[单master节点k8s部署]19.监控系统构建(四)kube-state-metrics

kube-state-metrics 是一个Kubernetes的附加组件&#xff0c;它通过监听 Kubernetes API 服务器来收集和生成关于 Kubernetes 对象&#xff08;如部署、节点和Pod等&#xff09;的状态的指标。这些指标可供 Prometheus 进行抓取和存储&#xff0c;从而使你能够监控和分析Kubern…...

字符串函数5-9题(30 天 Pandas 挑战)

字符串函数 1. 相关知识点1.5 字符串的长度条件判断1.6 apply映射操作1.7 python大小写转换1.8 正则表达式匹配2.9 包含字符串查询 2. 题目2.5 无效的推文2.6 计算特殊奖金2.7 修复表中的名字2.8 查找拥有有效邮箱的用户2.9 患某种疾病的患者 1. 相关知识点 1.5 字符串的长度条…...

【C语言题目】34.猜凶手

文章目录 作业标题作业内容2.解题思路3.具体代码 作业标题 猜凶手 作业内容 日本某地发生了一件谋杀案&#xff0c;警察通过排查确定杀人凶手必为4个嫌疑犯的一个。 以下为4个嫌疑犯的供词: A说&#xff1a;不是我。 B说&#xff1a;是C。 C说&#xff1a;是D。 D说&#xff…...

C++ 多进程多线程间通信

目录 一、进程间通信 1、管道&#xff08;Pipe&#xff09; 2、消息队列&#xff08;Message Queue&#xff09; 3、共享内存&#xff08;Shared Memory&#xff09; 4、信号量&#xff08;Semaphore&#xff09; 5、套接字&#xff08;Socket&#xff09; 6、信号&…...

怎么做防御系统IPS

入侵防御系统&#xff08;IPS&#xff09;是入侵检测系统&#xff08;IDS&#xff09;的增强版本&#xff0c;它不仅检测网络流量中的恶意活动&#xff0c;还能自动采取措施阻止这些活动。实现IPS的主要工具包括Snort和Suricata。以下是使用Snort和Suricata来实现IPS的详细步骤…...

达梦数据库的系统视图v$auditrecords

达梦数据库的系统视图v$auditrecords 在达梦数据库&#xff08;DM Database&#xff09;中&#xff0c;V$AUDITRECORDS 是专门用来存储和查询数据库审计记录的重要系统视图。这个视图提供了对所有审计事件的访问权限&#xff0c;包括操作类型、操作用户、时间戳、目标对象等信…...

Spring Boot与MyBatis-Plus:代码逆向生成指南

在Spring Boot项目中使用MyBatis-Plus进行代码逆向生成&#xff0c;可以通过MyBatis-Plus提供的代码生成器来快速生成实体类、Mapper接口、Service接口及其实现类等。以下是一个简单的示例步骤&#xff1a; 代码逆向生成 1.添加依赖&#xff1a; 在pom.xml文件中添加MyBati…...

【MySQL】mysql访问

mysql访问 1.引入MySQL 客户端库2.C/C 进行增删改3.查询的处理细节4.图形化界面访问数据库4.1下载MYSQL Workbench4.2MYSQL Workbench远程连接数据库 点赞&#x1f44d;&#x1f44d;收藏&#x1f31f;&#x1f31f;关注&#x1f496;&#x1f496; 你的支持是对我最大的鼓励&a…...

(1)Jupyter Notebook 下载及安装

目录 1. Jupyter Notebook是什么&#xff1f;2. Jupyter Notebook特征3. 组成部分3.1 网页应用3.2 文档 4. 适用场景5. 利用Google Colab安装Jupyter Notebook3.1 什么是 Colab&#xff1f;3.2 访问 Google Colab3.3 新建笔记本 1. Jupyter Notebook是什么&#xff1f; 百度百科…...

监控平台zabbix对接grafana

本次博客基于监控平台zabbix介绍与部署-CSDN博客的环境下进行的 1、安装grafana并启动 添加一台虚拟机20.0.0.30 &#xff08;1&#xff09;系统初始化 [rootzx3 ~]# systemctl stop firewalld [rootzx3 ~]# setenforce 0 [rootzx3 ~]#&#xff08;2&#xff09;安装并启动…...

14-11 2024 年的 13 个 AI 趋势

2024 年的 13 个 AI 趋势 人工智能对环境的影响和平人工智能人工智能支持的问题解决和决策针对人工智能公司的诉讼2024 年美国总统大选与人工智能威胁人工智能、网络犯罪和社会工程威胁人工智能治疗孤独与对人工智能的情感依赖人工智能影响者中国争夺人工智能霸主地位人工智能…...

计算机大方向的选择

选专业要了解自己的兴趣所在。 即想要学习什么样的专业&#xff0c;如果有明确的专业意向&#xff0c;就可以有针对性地选择那些专业实力较强的院校。 2.如果没有明确的专业意向&#xff0c;可以优先考虑一下院校。 确定一下自己想要选择综合性院校还是理工类院校或是像财经或者…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...