C++类基础(十二)

news2024/9/22 10:08:41

运算符重载(终)
● 类型转换运算符
– 函数声明为 operator type() const
– 与单参数构造函数一样,都引入了一种类型转换方式

struct Str
{
    Str(int p)
        : val(p)
    {}
    operator int() const //重载类型转换运算符: 没有显示声明返回类型(返回类型在函数名)、函数名后声明为const(不改变对象的内容,兼容常量与变量)
    {
        return val;
    }
private:
    int val;
};
int main()
{
    Str obj(100); //调用构造函数
    int v = obj;
    std::cout << v << std::endl;
    std::cout << static_cast<Str>(100) << std::endl; //OK,由于单参数构造函数和类型转换运算符
    std::cout << static_cast<int>(obj) << std::endl; //OK,由于类型转换运算符
    return 0;
}

在这里插入图片描述

– 注意避免引入歧义性与意料之外的行为

struct Str
{
    Str(int p)
        : val(p)
    {}
    operator int() const
    {
        return val;
    }
    friend auto operator+(Str a, Str b)
    {
        return Str(a.val + b.val);
    }
private:
    int val;
};
int main()
{
    Str obj(100);
    obj + 3; //Error: use of overloaded operator '+' is ambiguous(with operand types 'Str' and 'int')
             //没有完美匹配,即无需任何类型转换就可以调用的重载函数,但是有两种解决办法
             //第一种: 通过单一参数的构造函数将3转换为Str类型的对象,然后执行加法运算
             //第二种: 通过重载类型转换运算符函数将obj转换为int类型,然后执行加法运算
             //单一参数的构造函数和重载类型转换运算符函数的优先级相同,编译器无法确定选取哪一种
    std::cin << 3; //#1Error: Invalid operands to binary expression('std::istream'(aka 'basic_istream<char>') and 'int'
    //C++内部防止了隐式类型转换,比如if(std::cin)中std::cin输入流不能隐式转换为布尔类型
    //如果不防止,#1处的std::cin会隐式转换为bool类型,然后进行类型提升转换为int类型,然后<< 3的含义就是左移3
    return 0;
}

● 通过 explicit 引入显式类型转换

struct Str
{
    explicit Str(int p) //explicit声明符表明不能隐式将int类型转换为Str类型
        : val(p)
    {}
    operator int() const
    {
        return val;
    }
    friend auto operator+(Str a, Str b)
    {
        return Str(a.val + b.val);
    }
private:
    int val;
};
int main()
{
    Str obj(100);
    std::cout << obj + 3 << std::endl; //OK,通过重载类型转换运算符函数将obj转换为int类型,然后执行加法运算
    return 0;
}

在这里插入图片描述

struct Str
{
    Str(int p)
        : val(p)
    {}
    explicit operator int() const //explicit声明符表明不能隐式将Str类型转换为int类型
    {
        return val;
    }
    friend auto operator+(Str a, Str b)
    {
        return Str(a.val + b.val);
    }
private:
    int val;
};
int main()
{
    Str obj(100);
    std::cout << int(obj + 3) << std::endl; //OK,通过单一参数的构造函数将3转换为Str类型的对象,再通过重载类型转换运算符函数将obj转换为int类型,然后执行加法运算
    return 0;
}

在这里插入图片描述

struct Str
{
    explicit Str(int p) //explicit声明符表明不能隐式将int类型转换为Str类型
        : val(p)
    {}
    explicit operator int() const //explicit声明符表明不能隐式将Str类型转换为int类型
    {
        return val;
    }
    friend auto operator+(Str a, Str b)
    {
        return Str(a.val + b.val);
    }
private:
    int val;
};
int main()
{
    Str obj(100);
    std::cout << int(obj + 3) << std::endl; //Error: Invalid operands to binary expression('Str' and 'int')
    obj + static_cast<Str>(3); //OK
    static_cast<int>(obj) + 3; //OK
    return 0;
}

– explicit bool 的特殊性:用于条件表达式时会进行隐式类型转换

struct Str
{
    explicit Str(int p)
        : val(p)
    {}
    operator bool() const //无explicit声明符
    {
        return (val == 0);
    }
private:
    int val;
};
int main()
{
    Str obj(100);
    std::cout << obj << std::endl; //OK
    return 0;
}

在这里插入图片描述

struct Str
{
    explicit Str(int p)
        : val(p)
    {}
    explicit operator bool() const //explicit声明符,不允许隐式类型转换
    {
        return (val == 0);
    }
private:
    int val;
};
int main()
{
    Str obj(100);
    if(obj) //OK,等价于static_cast<bool>(obj)
    {
        std::cout << 1 <<std::endl;
    }
    else
    {
        std::cout << 0 <<std::endl;
    }

    auto var = obj ? 1 : 0; //OK,等价于static_cast<bool>(obj)
    std::cout << var <<std::endl;
    return 0;
}

在这里插入图片描述

● C++ 20 中对 == 与 <=> 的重载
– 通过 == 定义 !=

struct Str
{
    Str(int p)
        : val(p)
    {}
    friend bool operator==(Str obj1, Str obj2)
    {
        return obj1.val == obj2.val;
    }
private:
    int val;
};
int main()
{
    Str obj(100);
    Str obj2(100);
    std::cout << (obj == obj2) << std::endl;
    std::cout << (obj != obj2) << std::endl; //C++20 OK等价于((!operator==(Str(obj), Str(obj2)))),但是C++17 Error: Invalid operands to binary expression ('Str' and 'Str')
    return 0;
}
struct Str
{
    Str(int p)
        : val(p)
    {}
    friend bool operator==(Str obj1, Str obj2)
    {
        return obj1.val == obj2.val;
    }
    friend bool operator!=(Str obj1, Str obj2)
    {
        return obj1.val != obj2.val;
    }
private:
    int val;
};
int main()
{
    Str obj(100);
    Str obj2(100);
    std::cout << (obj == obj2) << std::endl; //OK
    std::cout << (obj != obj2) << std::endl; //OK等价于((operator!=(Str(obj), Str(obj2))))
    return 0;
}

在这里插入图片描述

但是不能通过!=定义==

struct Str
{
    Str(int p)
        : val(p)
    {}
    friend bool operator!=(Str obj1, Str obj2)
    {
        return obj1.val != obj2.val;
    }
private:
    int val;
};
int main()
{
    Str obj(100);
    Str obj2(100);
    std::cout << (obj == obj2) << std::endl; //Error: Invalid operands to binary expression ('Str' and 'Str')
    std::cout << (obj != obj2) << std::endl; //OK等价于((operator!=(Str(obj), Str(obj2))))
    return 0;
}
struct Str
{
    Str(int p)
        : val(p)
    {}
    friend bool operator==(Str obj1, int x) //重载==运算符第一个参数是Str类型
    {
        return obj1.val == x;
    }
private:
    int val;
};
int main()
{
    Str obj(100);
    std::cout << (obj == 100) << std::endl; //OK
    std::cout << (100 == obj) << std::endl; //C++20 OK因为通常等号满足交换律,因此C++20会尝试通过operator(int ,Str)寻找operator(Str, int),但是C++17Error: Invalid operands to binary expression ('int' and 'Str')
    std::cout << (100 != obj) << std::endl; //C++20 OK通过operator==()再求反
    return 0;
}

– 通过 <=> 定义多种比较逻辑

#include<iostream>
#include<compare>
struct Str
{
    Str(int p)
        : val(p)
    {}
    auto operator<=>(int x)
    {
        return val <=> x;
    }
private:
    int val;
};
int main()
{
    Str obj(100);
    std::cout << (100 >= obj) << std::endl; //OK等价于((operator>=(__cmp_cat::__unspec(0), obj.operator<=>(100))))
    std::cout << (obj >= 100) << std::endl; //OK等价于((operator>=(obj.operator<=>(100), __cmp_cat::__unspec(0))))
    return 0;
}

– 隐式交换操作数
– 注意 <=> 可返回的类型: strong_ordering, week_ordering, partial_ordering

参考
深蓝学院: C++基础与深度解析
cppinsights

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

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

相关文章

百趣代谢组学分享,补充α-酮酸的低蛋白饮食对肾脏具有保护作用

文章标题&#xff1a;Reno-Protective Effect of Low Protein Diet Supplemented With α-Ketoacid Through Gut Microbiota and Fecal Metabolism in 5/6 Nephrectomized Mice 发表期刊&#xff1a;Frontiers in Nutrition 影响因子&#xff1a;6.59 作者单位&#xff1a;…

opencv调取摄像头录制

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…

月薪11k!从财务专员到软件测试工程师,成都校区小哥哥用三个月实现转行换岗

好久没和大家分享学员的转行经历了&#xff0c;或许在一些人看来他们的故事与自己无关&#xff0c;但同样也能引起一些人的共鸣&#xff0c;可以帮助到那些陷于就业焦虑的同学找到目标和方向。相仿的年龄、相同的职业、相似的压力…在转行软件测试追求更好生活的路上&#xff0…

Python - 文件基础操作

目录 文件的读取 open()打开函数 read类型 read()方法 readlines()方法 readline()方法 for循环读取文件行 close() 关闭文件对象 with open 语法 文件的写入 文件的追加 文件的读取 操作 功能 文件对象 open(file, mode, encoding) 打开文件获得文件对象 文件…

C语言学习笔记(六): 探索函数与变量

函数的定义 形参和实参 在定义函数时函数名后面括号中的变量名称为“形式参数”&#xff08;简称“形参”&#xff09;或“虚拟参数”。 在主调函数中调用一个函数时&#xff0c;函数名后面括号中的参数称为“实际参数”&#xff08;简称“实参”&#xff09;。 当函数被调用…

独自开:提供创业机会、享受平台分红、推出新颖赚钱副业

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 前言 独自开&#xff1a;一款聚焦软件定制开发&#xff0c;独立、自主、开放平台 独创分层标准化平台架构,满足系统不断生长的个性化需求多端一键部署前端业务交互与展…

KMP算法详解

注意&#xff1a;PC阅读效果更佳&#xff0c;建议阅读的同时完成代码实践加深理解一、问题描述指定文本串&#xff1a;aabaabaaf和模式串&#xff1a;aabaaf使用KMP算法判断模式串是否在文本串中出现过&#xff1f;假定模式串的长度小于文本串二、思路解析BF算法的问题是&#…

【pytorch安装】conda安装pytorch无法安装cpu版本(完整解决过程)

问题描述 在安装pytorch过程中&#xff0c;发现最后验证torch时总是返回结果为False&#xff0c;结果翻上去发现自己安装的是cpu版本的。 然后又通过conda去更换不同版本尝试&#xff0c;发现都是cpu版本的。 问题分析 通过conda安装pytorch是从源中搜索匹配指令中的文件&am…

@Validated注解不生效问题汇总

Validated注解不生效问题汇总 文章目录Validated注解不生效问题汇总背景&#xff1a;一&#xff1a;可能原因原因1&#xff1a;原因2&#xff1a;原因3&#xff1a;原因4&#xff1a;二&#xff1a;补充全局异常对validation的处理背景&#xff1a; 项目框架应用的是validatio…

捕鱼大作战协议解密

捕鱼大作战协议解密协/议/流/量/解/密分析捕鱼大作战这款游戏流量的加密方式及解密方法。序捕鱼大作战是tuyoo公司在很多年前上线的一款休闲游戏&#xff0c;对&#xff0c;就是那个之前本号批斗过的途游&#xff0c;这款游戏以海洋深处作为背景&#xff0c;玩家通过在海底施展…

D31 Vue2 + Vue3 K104-K123

D31.Vue F17.打包 图片懒加载&#xff08;K104-K106&#xff09; 1.打包 1&#xff09;vue.config.js module.exports {//打包时不生成map文件(用来进行错误提示的文件&#xff0c;很占用空间)productionSourceMap: false,// 关闭ESLINT校验工具lintOnSave: false, }pnp…

学完Scrapy-Splash秒变爬虫大佬

在做爬虫的时候&#xff0c;大多数的网页中会存在数据动态加载的部分&#xff0c;而且多数都是后期渲染上的。正常情况下爬虫程序仅能爬取被渲染过的数据。因此我们看到的数据也许并非是爬虫直接获取来的。 而scrapy-splash担任了一个中间人的角色&#xff0c;程序通过splash服…

吴思进——复杂美创始人首席执行官

杭州复杂美科技有限公司创始人兼CEO, 本科毕业于浙江大学机械专业&#xff0c;辅修过多门管理课程&#xff1b;1997年获经济学硕士学位&#xff0c;有关对冲基金的毕业论文被评为优秀&#xff1b;2008年创办杭州复杂美科技有限公司。 吴思进 中国电子学会区块链委员会专家&…

计算机网络-基本概念

目录 计算机网络-基本概念 互联网 Java的跨平台原理 ​编辑 C\C的跨平台原理 解释性语言的跨平台原理(python,js等) 客户端 vs 服务器 什么是协议&#xff1f; 网络互连模型 请求过程 计算机之间的通信基础 计算机之间的连接方式-网线直连(需要用交叉线&#xff0c;而…

GIS数据经纬度投影坐标转换总结(涵盖几乎全行业的坐标转换方法)

在处理GIS数据的过程中,避免不了要与坐标和坐标系打交道。这篇文章对能够进行地理坐标转换的所有软件框架做一个一次性总结。 软件类: 1.arcgis arcgis能够进行很全面的很方便的坐标处理,无论是经纬度坐标转投影坐标还是投影坐标转经纬度坐标都非常的简单。arcgis能够对导…

Qt编写视频监控系统70-0SD标签和图形信息(支持写入到文件)

一、前言 作为一个完整的视频监控系统&#xff0c;用户还需要自定义一些OSD标签信息显示在对应通道上面&#xff0c;而且不止一个OSD标签信息&#xff0c;位置可以在四个角或者指定坐标显示。最开始本系统设计的时候&#xff0c;由于本人擅长的是painter绘制&#xff0c;所以直…

MySQL视图特性

文章目录MySQL视图特性基本使用准备测试表创建视图修改视图影响基表修改基表影响视图删除视图视图规则和限制MySQL视图特性 视图的概念 视图是一个虚拟表&#xff0c;其内容由查询定义&#xff0c;同真实的表一样&#xff0c;视图包含一系列带有名称的列和行数据。视图中的数据…

opencv读取摄像头和视频数据

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…

TensorRT和DLA(Deep Learning Accelerator)

TensorRT和DLA(Deep Learning Accelerator) 点击此处加入NVIDIA开发者计划 文章目录TensorRT和DLA(Deep Learning Accelerator)12.1. Running On DLA During TensorRT Inference注意&#xff1a;对于任何张量&#xff0c;索引维度的总体积加上请求的批量大小不得超过此函数返回…

Docker 面试知识点

Docker 是什么&#xff1f; 是实现容器技术的一种工具是一个开源的应用容器引擎使用 C/S 架构模式&#xff0c;通过远程API 来管理 (我们本机是 C&#xff0c;docker 引擎是 S,实际的构建过程是在 docker 引擎下完成的)可以打包一个应用及依赖包到一个轻量级、可移植的容器中 …