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++相对来说较为复杂,我们应该时刻理清自己的思路,耐下心来,一点点积累, 星光不问赶路人,加油吧,感谢阅读,如果对此专栏感兴趣,点赞加关注! 

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

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

相关文章

使用 mongo2neo4j 和 SemSpect 通过各种方式进行图探索

用于可视化和探索每个 MEAN 堆栈背后的数据图的 ETL 您是否正在努力回答有关 MEANS Web 服务数据的紧急问题&#xff1f;哪里有 BI 可以快速回答“上个季度哪些亚洲的artisan.plus 用户触发了订单&#xff1f;”这个问题&#xff0c;而无需编写查询&#xff1f;使用 mongo2neo4…

Linux:进程间通信(一.初识进程间通信、匿名管道与命名管道、共享内存)

上次结束了基础IO&#xff1a;Linux&#xff1a;基础IO&#xff08;三.软硬链接、动态库和静态库、动精态库的制作和加载&#xff09; 文章目录 1.认识进程间通信2.管道2.1匿名管道2.2pipe()函数 —创建匿名管道2.3匿名管道的四种情况2.4管道的特征 3.基于管道的进程池设计4.命…

FineBI在线学习资源-数据处理

FineBI在线学习资源汇总&#xff1a; 学习资源 视频课程 帮助文档 问答 数据处理学习文档&#xff1a; 相关资料&#xff1a; 故事背景概述-https://help.fanruan.com/finebi6.0/doc-view-1789.html 基础表处理-https://help.fanruan.com/finebi6.0/doc-view-1791.html …

软件设计之Java入门视频(11)

软件设计之Java入门视频(11) 视频教程来自B站尚硅谷&#xff1a; 尚硅谷Java入门视频教程&#xff0c;宋红康java基础视频 相关文件资料&#xff08;百度网盘&#xff09; 提取密码&#xff1a;8op3 idea 下载可以关注 软件管家 公众号 学习内容&#xff1a; 该视频共分为1-7…

Ubuntu 24.04 上安装 Kubernetes,超级详细的教程!

Kubernetes 是一个免费的开源容器编排工具&#xff0c;它允许基于容器的应用程序的自动化部署、扩展和管理。 我们将介绍如何使用 Kubeadm 逐步在 Ubuntu 24.04 上安装 Kubernetes 此次演示中&#xff0c;我们将使用以下三个 Ubuntu 24.04 实例 Instance 1 : Master Node (k…

计算机视觉——opencv快速入门(二) 图像的基本操作

前言 上一篇文章中我们介绍了如何配置opencv&#xff0c;而在这篇文章我们主要介绍的是如何使用opencv来是实现一些常见的图像操作。 图像的读取&#xff0c;显示与存储 读取图像文件 在opencv中我们利用imread函数来读取图像文件,函数语法如下&#xff1a; imagecv2.imre…

植物大战僵尸融合版最新版1.0下载及安装教程

《植物大战僵尸融合版》最新版1.0已经发布&#xff0c;为粉丝们带来了全新的游戏体验。这个版本由B站UP主蓝飘飘fly精心打造&#xff0c;引入了创新的植物融合玩法&#xff0c;让玩家可以享受策略和创意的结合。以下是游戏的详细介绍和安装指南&#xff1a; 游戏特色介绍 全新…

TF-IDF计算过程一步步推导详解含代码演示

相关概念 TF-IDF TF-IDF&#xff08;Term Frequency–Inverse Document Frequency&#xff09;是一种用于资讯检索与文本挖掘的常用加权技术。TF-IDF是一种统计方法&#xff0c;用以评估一个字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在…

lua入门(2) - 数据类型

前言 本文参考自: Lua 数据类型 | 菜鸟教程 (runoob.com) 希望详细了解的小伙伴还请查看上方链接: 八个基本类型 type - 函数查看数据类型: 测试程序: print(type("Hello world")) --> string print(type(10.4*3)) --> number print(t…

pdf可以删除其中一页吗?6个软件教你快速进行pdf编辑

pdf可以删除其中一页吗&#xff1f;6个软件教你快速进行pdf编辑 编辑PDF文件并删除特定页面是处理文档时常见的需求&#xff0c;特别是在需要定制或精简文件内容时。以下是几款广受欢迎的PDF编辑软件&#xff0c;它们提供了强大的页面删除功能&#xff0c;帮助用户轻松管理和修…

Vue3学习笔记(n.0)

vue指令之v-for 首先创建自定义组件&#xff08;practice5.vue&#xff09;&#xff1a; <!--* Author: RealRoad1083425287qq.com* Date: 2024-07-05 21:28:45* LastEditors: Mei* LastEditTime: 2024-07-05 21:35:40* FilePath: \Fighting\new_project_0705\my-vue-app\…

安卓开发定时截屏

此处有两种方式&#xff1a;&#xff08;都是定时截屏&#xff0c;不需要定时功能可以剔除service&#xff09; 1.app内截屏 https://download.csdn.net/download/hdhhd/89517797 2.截取当前任意手机显示屏幕 https://download.csdn.net/download/hdhhd/89517800 第一种…

hitcontraining_uaf

BUUCTF[PWN][堆] 题目&#xff1a;BUUCTF在线评测 (buuoj.cn) 程序del是没有将申请的指针清零&#xff0c;导致可以再次调用输出print。 查看add_note函数&#xff1a;根据当前 notelist 是否为空&#xff0c;来申请了一个8字节的空间将地址(指针)放在notelist[i]中&#xff…

海尔智家:科技优秀是一种习惯

海尔智家&#xff1a;科技优秀是一种习惯 2024-06-28 15:19代锡海 6月24日&#xff0c;2023年度国家科学技术奖正式揭晓。海尔智家“温湿氧磁多维精准控制家用保鲜电器技术创新与产业化”项目荣获国家科学技术进步奖&#xff0c;成为家电行业唯一牵头获奖企业。 很多人说&…

RK3568平台(USB篇)TYPE-C接口与PD协议

一.TYPE-C接口简介 type-c 插座&#xff1a; type-c 插头&#xff1a; type-c 线缆&#xff1a; type-c 接口定义之插座&#xff1a; type-c 硬件原理图&#xff1a; VBUS&#xff1a;供电引脚&#xff0c;用于传输电源电压&#xff0c;一般为5V或12V。 GND&#xff1a;地引…

使用ChatGPT写论文,只需四步突破论文写作瓶颈!

欢迎关注&#xff0c;为大家带来最酷最有效的智能AI学术科研写作攻略。关于使用ChatGPT等AI学术科研的相关问题可以和作者七哥&#xff08;yida985&#xff09;交流 地表最强大的高级学术AI专业版已经开放&#xff0c;拥有全球领先的GPT学术科研应用&#xff0c;有兴趣的朋友可…

一键式创建GTest测试平台

适用于C GTest测试平台搭建。直接上python脚本。 #!/usr/bin/env python3 # -*- coding: utf-8 -*-import argparse import os import platform import subprocess from xml.etree import ElementTree as ETdefault_root_path "d:\\test\\UTtest"class DeveloperTe…

文件扫描pdf怎么弄?5个简易高效的文件扫描方法

在繁忙的工作中&#xff0c;我们常常需要将纸质文件快速转换为电子文档&#xff0c;以便于编辑、存储或分享。 无论是合同、报告还是笔记&#xff0c;将这些纸质文件转换为Word格式&#xff0c;不仅能提高工作效率&#xff0c;还能确保信息的安全备份。然而&#xff0c;面对市…

Web3 ETF的主要功能

Web3 ETF的主要功能可以概括为以下几点&#xff0c;Web3 ETF仍是一项新兴投资产品&#xff0c;其长期表现仍存在不确定性。投资者在投资Web3 ETF之前应仔细研究相关风险&#xff0c;并做好充分的风险评估。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xf…

如何爱上阅读及阅读的意义有哪些?

第一个是“情绪决定”&#xff0c;比如看到人家健身&#xff0c;摄影&#xff0c;画画时&#xff0c;自己的肾上腺素开始飙升&#xff0c;马上表示自己也想做&#xff1b; 第二个是“理智决定”&#xff0c;理智决定同样表示想要一样东西&#xff0c;但表示人必定已经想好了为…