【C++】类和对象(中下)

news2025/1/10 22:44:46

  前言:

        上一篇文章,我们了解了类的默认成员函数——构造函数、析构函数、拷贝构造函数,这篇我们让我们接着了解。

一、赋值运算符重载:

1.运算符重载:

        C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也就是说它跟普通的函数一样具有返回值类型,安徽念书名字以及参数列表。

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

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

ps:

①.只能在原有的运算符基础上重载,不能通过连接其他符号来创建新的操作符,比如:operator@、operator#等等都不行;

②.重载操作符必须有一个类类型参数;

③用于内置类型的运算符,其含义不能改变,例如:内置的整形+,不能改变其含义;

④作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this指针。

*::sizeof?: , . 这五个操作符不能重载。

class Date
{
public:
    Date(int year=2023,int month=9,int day=15)
    {
        _year=year;
        _month=month;
        _day=day;
    }    
public:
//这里因为运算符重载成全局的需要成员函数是公有的,后期可以用友元解决,或者重载成成员函数;
    int _year;
    int _month;
    int _day;
};
bool opprator==(const Date& d1,const Date& d2)
{
    return d1._year=d2._year&&d1._month==d2._month&&d1._day==d2._day;
}

void Test()
{
    Date d1(2002,09,21);
    Date d2;
    cout<<(d1==d2)<<endl;
}

在类里面实现:

class Date
{
public:
    Date(int year=2023,int month=9,int day=15)
    {
        _year=year;
        _month=month;
        _day=day;
    }    
    bool opprator==(const Date& d2)
    {
    return _year=d2._year&&_month==d2._month&&_day==d2._day;
    }

private:
    int _year;
    int _month;
    int _day;
};

void Test()
{
    Date d1(2002,09,21);
    Date d2;
    cout<<(d1==d2)<<endl;
}

2.赋值运算符重载:

Ⅰ.赋值运算符重载格式:

参数类型:const T&,传递引用可以提高传参效率;

返回值类型:T&,返回引用可以提高返回效率,有返回值目的是为了支持连续赋值;

检测是否给自己赋值;

返回*this。

class Date
{
public:
    Date(int year=2023,int month=9,int day=15)
    {
        _year=year;
        _month=month;
        _day=day;
    }    
    bool oprator==(const Date& d2)
    {
    return _year=d2._year&&_month==d2._month&&_day==d2._day;
    }
    Date& oprator=(const Date& d)
    {
        if(this!=&d)
        {
            _year=d._year;
            _month=d.month;
            _day=d._day;
        }
        return *this;
    }

private:
    int _year;
    int _month;
    int _day;
};

Ⅱ赋值运算符只能重载成类的成员函数不能重载成全局函数:

class Date
{
public:
    Date(int year=2023,int month=9,int day=15)
    {
        _year=year;
        _month=month;
        _day=day;
    }    
    bool oprator==(const Date& d2)
    {
    return _year=d2._year&&_month==d2._month&&_day==d2._day;
    }

private:
    int _year;
    int _month;
    int _day;
};
Date& oprator=(const Date& d1,const Date& d2)
    {
        if(&d2=&d1)
        {
            d1._year=d2._year;
            d1._month=d2.month;
            d1._day=d2._day;
        }
        return d1;
    }
void Test()
{
    Date d1(2002,09,21);
    Date d2;
    cout<<(d1==d2)<<endl;
}

        上面这段代码会编译失败:error C2801:“operator=”必须是非静态成员。

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

编译器生成的默认赋值运算符重载是以值的方式逐字节拷贝

Ⅲ.默认赋值运算符重载

        上面我们讲到认编译器生成的默认赋值运算符重载是以值的方式逐字节拷贝。对于日期类来说,逐字节拷贝可以完成相应功能,但是有些情况逐字节拷贝无法完成,所以就需要深拷贝,现在我们来看看深拷贝的情况。

class Stack
{
public:
    Stack(size_t capacity = 10)
    {
        _array = (int*)malloc(capacity * sizeof(int));
            if (nullptr == _array)
            {
                perror("llmalloc申请空间失败");
                return;
            }
        _size = 0;
        _capacity = capacity;
    }
    void Push(const int& data)
    {
        //检查需要扩容,但这只是演示一下深拷贝情况,所以就不写了
        _array[_size] = data;
        _size++;
    }
    ~Stack()
    {
        if (_array)
        {
            free(_array);
            _array = nullptr;
            _capacity = 0;
            _size = 0;
        }
    }
private:
    int* _array;
    size_t _size;
    size_t _capacity;
};

int main()
{
    Stack s;
    s.Push(1);
    s.Push(2);
    s.Push(3);

    Stack s1;
    s1 = s;
    return 0;
}

上述代码会造成两个问题:

①指向同一块空间,但s改变的时候s1也会跟着改变。

②当程序结束的时候会调用两次析构函数,同一块空间析构两次,这也是导致程序奔溃的主要原因。

3.前置++和后置++重载:

        同样我们用日期类来看看前置++和后置++:

class Date
{
public:
    Date(int year=2023,int month=9,int day=15)
    {
        _year=year;
        _month=month;
        _day=day;
    }    
    Date(const Date& d)
    {
        _year=d._year;
        _month=d._month;
        _day=d._day;
    
    }
    //前置++
    Date& operator++()
    {
        _day++;
        return *this;
    }
    //前置++
    //C++规定:后置++重载时多增加一个整形参数,但调用函数时该参数不用传递,编译器自动传递
    Date operator++(int)
    {
        因为前置++返回的是没有改变前的值,所以要备份一个tmp
        且因为出了作用域后tmp会摧毁,所以返回值不能使用引用
        Date tmp(*this);
        _day++;
        return tmp;
    }
private:
    int _year;
    int _month;
    int _day;
};

4.const成员:

将const修饰的成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针。

5.取地址及const取地址操作符重载:

        这两个默认成员函数一般不用重新定义,编译器默认会生成,只有特殊情况才需要重载,比如想让别人读取到指定内容。

总结:

        文章到这,我们关于类的六个默认成员函数已经介绍完了,也是构造函数,析构函数,拷贝构造函数,赋值运算符重载,const成员函数,取地址及const取地址操作符重载。

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

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

相关文章

数据科学的文本技术 Text Technology(IR信息检索、搜索引擎)

一、文章摘要 1. 内容 * Introduction to IR and text processing, system components * Zipf, Heaps, and other text laws * Pre-processing: tokenization, normalisation, stemming, stopping. * Indexing: inverted index, boolean and proximity search * Evaluation m…

测试进阶知识之零日攻击的发现和防御

零日攻击是指针对软件或系统中未公开&#xff08;或未被开发者知晓&#xff09;的漏洞进行的攻击。这些漏洞被称为零日漏洞&#xff0c;因为在被公开之前&#xff0c;它们对开发者或安全研究人员来说是未知的&#xff0c;所以没有足够的时间进行防御或修复。 发现零日漏洞 发…

数据集成:数据挖掘的准备工作之一

⭐️⭐️⭐️⭐️⭐️欢迎来到我的博客⭐️⭐️⭐️⭐️⭐️ &#x1f434;作者&#xff1a;秋无之地 &#x1f434;简介&#xff1a;CSDN爬虫、后端、大数据领域创作者。目前从事python爬虫、后端和大数据等相关工作&#xff0c;主要擅长领域有&#xff1a;爬虫、后端、大数据…

清华大学 邓俊辉数据结构 关于哈希表的章节

本来以为没有 但是搜索hash 发现被叫做散列表 所以在9.3节就可以找到了

Keepalived+LVS高可用集群

目录 一、keepalived介绍&#xff1a; 二、keepalived工具介绍&#xff1a; &#xff08;1&#xff09;管理 LVS 负载均衡软件&#xff1a; &#xff08;2&#xff09;支持故障自动切换&#xff1a; &#xff08;3&#xff09;实现 LVS 负载调度器、节点服务器的高可用性&…

HTML5教程之移动端Web页面布局

一、什么是移动端项目 顾名思义&#xff0c;运行在移动端的项目就称为移动端项目。那什么是移动端呢&#xff0c;主要是指我们的一些手持设备&#xff0c;最具有代表性的就是我们日常使用的手机和平板&#xff0c;当然还包括一些其他便携设备&#xff0c;如智能手表&#xff0c…

LVS keepalived实现高可用负载群集

目录 1 Keepalived及其工作原理 1.1 Keepalived体系主要模块及其作用&#xff1a; 2 LVSKeepalived 高可用群集部署 2.1 配置负载调度器&#xff08;主、备相同&#xff09; 2.1.1 配置keeplived&#xff08;主、备DR 服务器上都要设置&#xff09; 2.1.2 启动 ipvsadm 服…

重新认识交叉编译

1. 我以前对交叉编译的认知 引用正点原子的话来讲就是: 说得对&#xff0c;但是不全面&#xff0c;直到最近项目中遇到了一个例子我才重新认识什么是交叉编译。 2. build/host/target的概念 参考: Cross-Compilation (automake) 参考: Specifying Target Triplets (Autocon…

javaee之黑马乐优商城3

异步查询工具axios(儿所以时) vue官方推荐的ajax请求框架 新增品牌页面 如何找到上面这个页面 下面这个页面里面的新增商品弹窗 上面就是请求路径与请求方式 那么请求参数是什么&#xff1f; brand对象&#xff0c;外加商品分类的id数组cids &#xff08;这里其实不止就是添加…

腾讯mini项目-【指标监控服务重构】2023-07-31

今日已办 trace_id传播 关于如何使用 trace_id 创建 span 的思路 【暂未实现 & 测试】 调研 SpanProcessor 阅读源码的test 明日待办 根据 trace_id 创建 span&#xff0c;应该需要 parent span_id 才能有 trace 的树状 span 的关系

腾讯mini项目-【指标监控服务重构】2023-08-06

今日已办 feature/client_traces_profile 修改 consumer 4个阶段的 spankind将 profile 的 span 作为 root span&#xff0c;保持与 venus 的 follows from 的 link feature/profile-otelclient-metric 将 metric 部分使用新分支 push go.opentelemetry.io/otel/propagatio…

定时器类的编写与解析 —— TinyWebServer

定时器类的编写与解析 —— TinyWebServer 一、前言 定时器非常好写。就是链表加定时函数。搞懂他的作用就成。 定时器的作用是什么&#xff1f;什么是回调函数&#xff1f;用到的函数是什么&#xff1f; 二、问题回答 Ⅰ、定时器的作用是什么&#xff1f; 处理非活跃的连…

坦克大战设计与实现

摘 要 J2SE是近年来随着各种不同技术的发展&#xff0c;尤其是编程语言飞速发展而诞生的一项新的开发语言。随着信息技术的飞速发展&#xff0c;计算机的使用也日渐普及&#xff0c;本文从实际应用出发&#xff0c;向大家介绍坦克大战游戏的设计与实现。Eclipse平台模拟器开发调…

华为数通方向HCIP-DataCom H12-831题库(单选题:21-40)

第21题 R3与R1的IS-IS邻居没有建立,根据本图的信息,可能的原因是? A、R3与R1的IIH认证失败 B、R3与R1的System ID重复 C、R3与R1的IS-Level不匹配 D、R3与R1的互连接口circuit-type不匹配 答案: A 解析: 从图中的Bad Authentiaction 信息可以看出R3与R1的IIH认证失败失败…

一生一芯16——安装pandoc使jupyter notebook转pdf

目的 希望导出jupyter notebook文档翻译 从这里导出pdf&#xff0c;但显示我没有安装pandoc&#xff0c;故安装pandoc 安装Pandoc 下载对应安装包 https://github.com/jgm/pandoc/releases 下载完成后&#xff0c;在目录中运行程序如下&#xff1a; 你需要解压下载的文件。…

windows10使用wheel安装tensorflow2.13.0/2.10.0(GPU版本) (保姆级教程)

安装过程 安装虚拟环境安装virtualenv安装满足要求的python版本使用virtualenv创建指定python版本的虚拟环境 安装tensorflow安装tensorflow-docs直接下载使用wheel下载 在VSCode编辑器中使用虚拟环境下的python解释器&#xff0c;并使用tensorflow常见错误 注意&#xff1a; t…

Python stomp 发送消息无法显示文本

我们向消息服务器通过 stomp 发送的是文本消息。 当消息服务器发送成功后&#xff0c;消息服务器上的文本没有显示&#xff0c;显示的是 2 进制的数据。 如上图&#xff0c;消息没有作为文本来显示。 问题和解决 消息服务器是如何判断发送的小时是文本还是二进制的。 根据官…

API接口文档管理系统平台搭建(更新,附系统源码及教程)

简介 这是一款简洁大方的API接口文档管理系统&#xff0c;附系统源码及教程方法。可以轻松管理和使用API接口。 安装步骤 打开config/database.php配置数据库信息导入数据库data.sql设置运行目录为/public伪静态设置think PHP后台地址/admin/login.html 账号&#xff1a;adm…

【算法与数据结构】669、LeetCode修剪二叉搜索树

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;450、LeetCode删除二叉搜索树中的节点两道题的思路几乎是一样的&#xff0c;只不过终止条件和单层递归…

#循循渐进学51单片机#定时器与数码管#not.4

1、熟练掌握单片机定时器的原理和应用方法。 1&#xff09;时钟周期&#xff1a;单片机时序中的最小单位&#xff0c;具体计算的方法就是时钟源分之一。 2&#xff09;机器周期&#xff1a;我们的单片机完成一个操作的最短时间。 3)定时器&#xff1a;打开定时器“储存寄存器…