类和对象中阶3⃣️-默认成员函数(赋值运算符重载,取地址及 const取地址操作符重载等)

目录

5.赋值运算符重载

5.1 运算符重载

5.2 赋值运算符重载 

5.3 前置++和后置++重载 

5.4 重载流插入与流提取

流插入<<运算符重载

流提取运算符重载

 6.日期类实现

7.const成员

8.取地址 及 const取地址操作符 重载


5.赋值运算符重载

5.1 运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字operator后面接需要重载的运算符符号

函数原型:返回值类型operator操作符(参数列表)

注意:

  1. 不能通过连接其他符号来创建新的操作符:比如operator@
  2. 重载操作符必须有一个类(的)类型参数
  3. 用于内置类型的运算符,其含义不能改变,例如:内置类型+,不能改变其含义
  4. 作为类成员函数重载时,其形参看起来比操作数 数目少1,因为成员函数的第一个参数为隐藏的this

5. .* :: sizeof ?: . 注意以上5个运算符不能重载,这个经常在笔试选择题中出现

 

6. 对于运算符重载,显示调用与转换调用语法实现效果是一样的

 

7.        当将函数重载成全局的时候,就无法访问类内私有成员,解决方案如下:

  1. 提供这些成员get和set(Java爱用)
  2. 友元
  3. 重载为成员函数(一般使用这种)
class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }

    int GetYear()
    {
        return _year;
    }

//    //实现d1 == d2 重载为成员函数
//    bool operator==(const Date& d){
//        return this->_year == d._year && this->_month == d._month &&
//        this->_day == d._day;
//    }

public:
    int _year;
    int _month;
    int _day;
};

// 重载成全局,无法访问私有成员
// 1、提供这些成员get和set
// 2、友元  后面会讲
// 3、重载为成员函数(一般使用这种)

bool operator==(const Date& d1, const Date& d2)
{
    return d1._year == d2._year
        && d1._month == d2._month
        && d1._day == d2._day;
}

//d1-d2
//d1+d2 没有意义
//d1*d2 没有意义
//一个类要重载哪些运算符是看需求,看重载有没有价值和意义

int main()
{
    Date d3(2024, 4, 14);
    Date d4(2024, 4, 15);

    // 显式调用
    operator==(d3, d4);

    // 直接写,装换调用,编译会转换成operator==(d3, d4);
    d3 == d4;

    return 0;
}

5.2 赋值运算符重载 

  1. 赋值运算符重载格式

          a. 参数类型:const T&,传递引用可以提高传参效率
          b. 返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
          c. 检测是否自己给自己赋值
          d. 返回*this:要复合连续赋值的含义

2.赋值运算符重载函数必须作为成员函数,不能作为全局函数。并且函数出了类域,将不在有this指针的特性,此时需要给两个参数 

原因:赋值运算符如果不显示实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数

 

3.用户没有显示实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值

 

注意:如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理必须要实现。比如下面这个例子 

 

5.3 前置++和后置++重载 

class Date{
private:
    int _year;
    int _month;
    int _day;
    
public:
    Date(int year = 2024,int month = 4,int day = 17){
        _year = year;
        _month = month;
        _day = day;
    }
    
    //前置++:返回+1之后的结果
    //注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率
    Date& operator++(){
        _day +=1;
        return *this;
    }
    
    //后置++
    //前置++和后置++都是一元运算符,为了让前置++和后置++能形成正确重载
    // C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器
    //自动传递
    // 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存
    //一份,然后给this+1
    
    Date operator++(int){
        Date tmp = (*this);
        _day += 1;
        return tmp;//注意:tmp是临时对象,因此只能以值的方式返回,不能返回引用
    }
    
};

int main(){
    Date d; //d: 2024 4 17
    Date d1(2000,1,1); //d1: 2000,1,1
    d = d1++;//d : 2000,1,1  d1: 2000,1,2
    d = ++d1;//d ; 2000,1,3  d1: 2000,1,3
    return 0;
}

5.4 重载流插入与流提取

在C++标准库中,cout和cin都是iostream中ostream 和istream 的对象,对于流插入<<运算符,之所以cout输出可以不用指定占位符编译器可以自动匹配的原因是ostream中<<的运算符重载,对于内置类型来说,有下面的函数重载

流插入<<运算符重载

我们来实现流插入重载

在上面代码中,虽然重载了<<,但是形参是ostream流的对象,而隐含的形参是this,而在运算符重载函数形参列表规则中,对于有两个操作数的运算符重载来说,这里第一个参数为左操作数(隐含的this),第二个参数为右操作数,所以上面代码应改为d<<cout;

为了能够实现和流插入一样的效果,我们就要进行修改,但this所在的形参是更改不了的,因此我们将<<重载放到全局中(全局中失去了this的特性),此时可以决定两个操作数的顺序。

由于我们将重载放在了全局中,那么全局无法访问类中私有成员,这里我们使用友元的方法,解除私有问题。

流提取运算符重载

class Date
{
friend ostream& operator<<(ostream &cout,Date& d);
    friend istream& operator>>(istream &cin ,Date& d);
private:
    int _day;
    int _month;
    int _year;
public:
    Date(int year = 2024, int month = 4, int day = 18)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    
    //运算符重载中,参数顺序和操作顺序是一致的
//    void operator<<(ostream &cout){
//        cout << _year << "-" << _month << "-" << _day <<endl;
//    }
    
};

//使用返回值类型 可以进行连续插入
ostream& operator<<(ostream &cout,Date& d){
    cout << d._year << "-" << d._month << "-" << d._day <<endl;
    return cout;
}
 
istream& operator>>(istream &cin ,Date& d){
    cin >> d._year >> d._month >> d._day;
    return cin;
}
int main()
{
    Date d(1999,8,1);
    Date d1;
    cin >> d >> d1;
    return 0;
}

 6.日期类实现

//
//  Date.hpp
//  类和对象2⃣️
//
//  Created by 南毅 on 2024/4/19.
//

#pragma once
#include<iostream>
using namespace std;

#include<assert.h>

class Date
{
    // 友元函数声明

public:
    Date(int year = 1900, int month = 1, int day = 1);
    void Print() const;

    // 直接定义类里面,他默认是inline
    // 频繁调用
    int GetMonthDay(int year, int month)
    {
        assert(month > 0 && month < 13);
        
        static int monthDayArray[13] = { -1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

        // 365天 5h +
        if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
        {
            return 29;
        }
        else
        {
            return monthDayArray[month];
        }
    }

    bool CheckDate();

    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;

    // d1 += 100
    Date& operator+=(int day);
    Date operator+(int day) const;

    // d1 -= 100
    Date& operator-=(int day);

    // d1 - 100;
    Date operator-(int day) const;

    // d1 - d2
    int operator-(const Date& d) const;

    // ++d1 -> d1.operator++()
    Date& operator++();

    // d1++ -> d1.operator++(1)
    // 为了区分,构成重载,给后置++,强行增加了一个int形参
    // 这里不需要写形参名,因为接收值是多少不重要,也不需要用
    // 这个参数仅仅是为了跟前置++构成重载区分
    Date operator++(int);
    // 15:55

    Date& operator--();
    Date operator--(int);


private:
    int _year;
    int _month;
    int _day;
};
 
//
//  Date.cpp
//  类和对象2⃣️
//
//  Created by 南毅 on 2024/4/19.
//

#include "Date.hpp"

Date::Date(int year, int month, int day){//缺省值在.h文件显示
    _year = year;
    _month = month;
    _day = day;
    
    if(!CheckDate()){
        perror("日期非法\n");
    }
}


void Date::Print() const{

    cout<< _year << "-" << _month << "-" << _day <<endl;
}

bool Date::CheckDate(){
    if(_month > 12 || _month < 1 || _day > GetMonthDay(_year, _month)||_day<1){
        return false;
    }else{
        return true;
    }
}

//d1 < d2
bool Date::operator<(const Date& d) const{
    if(_year < d._year){
        return true;
    }else if (_year == d._year){
        if(_month < d._month){
            return true;
        }else if (_month == d._month){
            return _day < d._day;
        }
    }
    return false;
}

//d1 == d2
bool Date::operator==(const Date& d) const{
    return _year == d._year && _month == d._month && _day == d._day;
}

//d1 <= d2
bool Date::operator<=(const Date& d) const{
    return (*this < d) || (*this == d);
}

//d1 > d2
bool Date::operator>(const Date& d) const{
    return !(*this <= d);
}


//d1 >= d2
bool Date::operator>=(const Date& d) const{
    return !(*this < d);
}

//d1 != d2
bool Date::operator!=(const Date& d) const{
    return !(*this == d);
}
//d1 += 50
Date& Date::operator+=(int day){
    _day += day;
    while(_day > GetMonthDay(_year, _month)){
        _day -= GetMonthDay(_year, _month);
        _month++;
        while (_month > 12) {
            _year += 1;
            _month =1 ;
        }
    }

    return *this;
}

Date Date::operator+(int day) const{
    Date tmp = *this;
    tmp += day;
    return tmp;
}

// d1 -= 50;
Date& Date::operator-=(int day){
    while (_day - day < 0) {
        _month--;
        while (_month < 1) {
            _year--;
            _month = 12;
        }
        _day += GetMonthDay(_year, _month);

    }
    _day -= day;
    return *this;
}

//d1 - 100
Date Date::operator-(int day) const
{
    Date tmp = *this;
     tmp -= day;
    return tmp;
}

//++d1
Date& Date::operator++()
{
    *this += 1;

    return *this;
}

// d1++
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;
}
// d1 - d2
int Date::operator-(const Date& d) const{
    Date max = *this;
    Date min = d;
    int flag = 1;
    int n = 0;
    if((*this) < d){
        max = d;
        min = *this;
        flag = -1;
    }
    
    while (max != min) {
        max--;
        n++;
    }
    return n * flag;
}



7.const成员

将const修饰的“成员函数“称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改

8.取地址 及 const取地址操作符 重载

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

class A
{
public:
    // 我们不实现,编译器会自己实现,我们实现了编译器就不会自己实现了
    // 一般不需要我们自己实现
    // 除非不想让别人取到这个类型对象的真实地址
    A* operator&()
    {
        cout << "A* operator&()" << endl;

        return nullptr;
    }

    const A* operator&() const
    {
        cout << "const A* operator&() const" << endl;

        return (const A*)0xffffffff;
    }
private:
    int _a1 = 1;
    int _a2 = 2;
    int _a3 = 3;
};

int main()
{
    A aa1;
    const A aa2;

    cout << &aa1 << endl;
    cout << &aa2 << endl;

    return 0;
}

 

 

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

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

相关文章

数仓建模—数据仓库初识

数仓建模—数据仓库初识 数据仓库之父Bill Inmon在1991年出版的"Building the Data Warehouse"一书中所提出的定义被广泛接受 数据仓库&#xff08;Data Warehouse&#xff09;是一个面向主题的&#xff08;Subject Oriented&#xff09;、集成的&#xff08;Integ…

Mysql索引专题

文章目录 1. 数据库索引结构1.1 Hash结构1.2 树结构1.3 Mysql索引怎么提升效率? 2. 执行计划 explainidselect_typetabletypepossible_keyskeykey_lenrefrowsfiteredextra 1. 数据库索引结构 我们都知道mysql数据库的常用存储结构是B树&#xff0c;为什么是B树&#xff1f;试…

邮件代发API发送邮件如何使用?操作指南?

邮件代发邮箱API发送邮件的步骤&#xff1f;代发有哪些注意事项&#xff1f; 在自动化办公、批量营销等场景中&#xff0c;手动发送邮件往往显得效率低下&#xff0c;这时候&#xff0c;邮件代发API就显得尤为重要。那么&#xff0c;邮件代发API发送邮件究竟如何使用呢&#x…

买婴儿洗衣机怎么选择?四大绝佳好用婴儿洗衣机分享

幼龄时期的宝宝的衣物&#xff0c;是比较需要注意的时候。可能一不注意宝宝穿在身上就会有不适宜症状发生。所以宝妈们真的要随时观察&#xff0c;然后在宝宝洗衣服的这上面多下点功夫&#xff0c;不要让宝宝受到这种无谓的伤害。小婴儿的抵抗力比我们差很多。有些细菌、病毒可…

Hadoop大数据处理技术-Linux相关命令

​7.Linux常用命令 1&#xff09;Windows中的dir&#xff1a;列出当前目录下所有的文件和目录 2&#xff09;cd&#xff1a;改变当前目录 cd命令并不能直接实现这种跳跃转换目录的功能 它只能让你在当前目录和其子目录之间来回切换 就像在一张平面地图上移动一样 如果想跨目录…

如何挑选护眼灯?分享护眼灯排行榜前十名

许多家长肯定都有这样的烦恼&#xff0c;家中的孩子自从上学后&#xff0c;每天回家后的学习作写阅读时总会在不知不觉间越来越贴近书本&#xff0c;后来还会时不时眯着眼睛看东西&#xff0c;但其实这种用眼习惯的最大原因是孩子没有足够光线和舒适的环境光线导致的&#xff0…

硬件设备杂记——12G SDI及 AES67/EBU

常见的 SDI线缆规格&#xff0c;HD-SDI又被称为1.5G-SDI&#xff0c;具体参数以秋叶原的参数为例 AES67/EBU 目前音频网络标准主要集中在OSI网络体系的第二层和第三层。 第二层音频标准的弊端在于构建音频网络时需要专用的交换机&#xff0c;无法利用现有的以太网络&#xff0c…

SpringBoot基于redis zset实现滑动窗口限流

通过Redis zset实现滑动窗口限流算法 在开发高并发系统时有三把利器用来保护系统&#xff1a;缓存、降级和限流。限流可以认为服务降级的一种&#xff0c;限流通过限制请求的流量以达到保护系统的目的。 一般来说&#xff0c;系统的吞吐量是可以计算出一个阈值的&#xff0c;…

【leetcode面试经典150题】59. 合并两个有序链表(C++)

【leetcode面试经典150题】专栏系列将为准备暑期实习生以及秋招的同学们提高在面试时的经典面试算法题的思路和想法。本专栏将以一题多解和精简算法思路为主&#xff0c;题解使用C语言。&#xff08;若有使用其他语言的同学也可了解题解思路&#xff0c;本质上语法内容一致&…

【Java框架】Spring框架(四)——Spring中的Bean的创建与生命周期

目录 SpringBean的创建步骤后置处理器(PostProcessor)BeanFactoryPostProcessorBeanPostProcessorInstantiationAwareBeanPostProcessorpostProcessBeforeInstantiationpostProcessAfterInstantiationpostProcessProperties SmartInstantiationAwareBeanPostProcessordetermine…

空心电抗器的matlab建模与性能仿真分析

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 空心电抗器是一种无铁芯的电感元件&#xff0c;主要由一圈或多圈导线绕制在非磁性材料制成的空心圆筒或其他形状的骨架上构成。其工作原理基于法拉第电磁感应定律&#xff0c;…

Maui 开始笔记

1&#xff0c;仿真器硬件加速&#xff0c;需要安装 2&#xff0c;刚创建的maui 不添加的话&#xff0c;启动可能时会自动退出&#xff0c;不退出&#xff0c;可以不加次配置 MauiApp1.csproj 文件中配置 在 PropertyGroup 元素下添加 <WindowsAppSdkDeploymentManagerIniti…

【Qt】常用控件(LCD Number/进度条/日历)

需要云服务器等云产品来学习Linux可以移步/-->腾讯云<--/官网&#xff0c;轻量型云服务器低至112元/年&#xff0c;新用户首次下单享超低折扣。 目录 一、LCD Number(LCD显示器) 一个倒计时程序 二、ProgressBar(进度条) 1、创建一个进度条&#xff0c;100ms进度增加…

hv第一坑:定时器

错误代码 重试策略&#xff1a;一次延迟1s,最长30s直至事件成功。 int try_count 0;//do something if(not success)m_loop->setTimerInLoop((try_count > 30 ? 30: try_count) *1000 , cb, INFINITE, 0x100);表现现象 cpu 爆了内存爆了 总结原因 hv内部代码bug&…

C语言—常用字符串函数剖析

字符串函数 cplusplus.com/reference/cstring/ 更多没有总结到的函数大家可以自行查阅 这篇文章只是把最需要知道的函数做一个总结 strlen size_t strlen ( const char * str );字符串已经 ‘\0’ 作为结束标志&#xff0c;strlen函数返回的是在字符串中 ‘\0’ 前面出现的…

力扣面试150 文本左右对齐 贪心 字符串 满注释版

Problem: 68. 文本左右对齐 思路 &#x1f469;‍&#x1f3eb; 三叶题解 &#x1f496; Code class Solution { public List<String> fullJustify(String[] words, int maxWidth){List<String> ans new ArrayList<>();// 结果List<String> list …

【网络安全技术】——网络安全设备(学习笔记)

&#x1f4d6; 前言&#xff1a;网络防火墙&#xff08;简称为“防火墙”&#xff09;是计算机网络安全管理中应用最早和技术发展最快的安全产品之一。随着互联应用的迅猛发展&#xff0c;各种安全问题和安全隐患日渐突出。防火墙及相关安全技术能够最大可能地解决各类安全问题…

SpringBoot整合零一万物模型API进行多轮对话

前期准备工作 零一万物官网&#xff1a;https://www.01.ai/cn 零一万物大模型开放平台&#xff1a;https://platform.lingyiwanwu.com/ 选择理由 性价比高很高&#xff0c;模型整体不错&#xff0c;新用户送60元&#xff0c;非常适合研究学习。 开发 只提供了http接口和p…

测试JAVA 测开

测试、java测开 1、测试用例要素&#xff08;4个重要要素&#xff09;2、测试用例的好处3、测试用例的设计方法3.1 基于需求设计测试用例3.2 等价类3.3 边界值3.4 判定表 1、测试用例要素&#xff08;4个重要要素&#xff09; 测试环境操作步骤测试数据预期结果 2、测试用例的…