【C++】隐式转换与explicit关键字、运算符及其重载、this关键字

news2024/12/23 14:13:05

C++隐式转换与explicit关键字

隐式构造函数

隐含的意思是不会明确告诉你要做什么

隐式转换

C++允许编译器对代码执行一次隐式转换,而不需要使用casr强制转换

例1

#include <iostream>
#include <string>

class Entity
{
private:
 std::string m_Name;
 int m_Age;
public:
 Entity(const std::string& name)
  : m_Name(name), m_Age(-1) {}
 Entity(int age)
  : m_Name("Unknown"), m_Age(age) {}
};
void PrintEntity(const Entity& entity)
{
 // Printing
}
int main()
{
 Entity a("Cherno");
 Entity b(22);

 Entity c = "Cherno";  // 隐式转换
 Entity d = 22;

 PrintEntity(22);
 PrintEntity("Cherno");  // 不能隐式转换,因为"Cherno"不是std::string, 而是一个char数组
 std::cin.get();
}

隐式的将22转换成一个Entity,构造出一个Entity
PrintEntity(22)可以
PrintEntity("Cherno")不可以
因为"Cherno"不是一个std::string, 而是一个char数组,所以要进行两次转换,一次从char数组转换成std::string, 然后再从std::string转换成Entity,然而,只允许做一次隐式转换

PrintEntity(std::string("Cherno"));
先做一个显式的转换

PrintEntity(Entity("Cherno"));
或者包含在Entity,因为可以将其隐式地将字符数组转换成std::string

explicit关键字

  • 禁用隐式implicit这个功能
  • explicit关键字放在构造函数前面,如果有一个explicit构造函数,意味着没有implicit转换。如果要使用整数构造Entity对象,就必须显式调用此构造函数

例2

#include <iostream>
#include <string>

class Entity
{
private:
 std::string m_Name;
 int m_Age;
public:
 Entity(const std::string& name)
  : m_Name(name), m_Age(-1) {}
 explicit Entity(int age)
  : m_Name("Unknown"), m_Age(age) {}
};

void PrintEntity(const Entity& entity)
{
 // Printing
}

int main()
{
 Entity a("Cherno");
 Entity b(22);

 Entity c = "Cherno";  
 Entity d = 22;

 PrintEntity(22);
 PrintEntity("Cherno");  
 PrintEntity(std::string("Cherno"));
  
 std::cin.get();
}

失效:

Entity d = 22;
 PrintEntity(22);

有效:

Entity e = Entity(22);
 Entity f(22);
 Entity g = (Entity)22;

什么时候使用explicit

使用数学库之类的东西,因为不想总是将数字变成向量,确保代码尽量安全

C++运算符及其重载

运算符

一个符号,通常代替一个函数来执行一些事情
dereference运算符->
+=, &, <<
new, delete
, () []

运算符重载

  • 给运算符重载赋予新的含义,添加参数或者创建
  • 允许在程序中定义或更改运算符的行为
  • 运算符重载的使用,应该是非常少

例3

#include <iostream>
#include <string>


struct Vector2
{
 float x, y;
 Vector2(float x, float y)
  : x(x), y(y) {}

 Vector2 Add(const Vector2& other) const
 {
  return Vector2(x + other.x, y + other.y);
 }

 Vector2 Multiply(const Vector2& other) const
 {
  return Vector2(x * other.x, y * other.y);
 }
};
int main()
{
 Vector2 position(4.0f, 4.0f);
 Vector2 speed(0.5f, 1.5f);
 Vector2 powerup(1.1f, 1.1f);
 // 加在一起
 Vector2 result = position.Add(speed.Multiply(powerup));
 std::cin.get();
}

Java只能这样写,因为Java没有操作符重载
可以用this指针:

Vector2 Add(const Vector2& other) const
 {
  return *this + other;
 }
Vector2 Add(const Vector2& other) const
 {
  return operator+(other);
 }

是否可以改成Vector2 result1 = position + speed * powerup;?

例4

#include <iostream>
#include <string>


struct Vector2
{
 float x, y;
 Vector2(float x, float y)
  : x(x), y(y) {}

 Vector2 Add(const Vector2& other) const
 {
  return Vector2(x + other.x, y + other.y);
  // return *this + other;
 }

 Vector2 operator+(const Vector2& other) const
 {
  return Add(other);
 }
 
 Vector2 Multiply(const Vector2& other) const
 {
  return Vector2(x * other.x, y * other.y);
 }

 Vector2 operator*(const Vector2& other) const
 {
  return Multiply(other);
  // return *this + other;
 }
};

int main()
{
 Vector2 position(4.0f, 4.0f);
 Vector2 speed(0.5f, 1.5f);
 Vector2 powerup(1.1f, 1.1f);
 // 加在一起
 Vector2 result = position.Add(speed.Multiply(powerup));

 Vector2 result1 = position + speed * powerup;   // +运算符重载了


 std::cin.get();
}

运算符+和*都进行了重载

<< 操作符

std::cout << result2 << std::endl; // 

<< 操作符没有被重载,接收两个参数,一个是输出流cout,另一个是Vector2

例5

#include <iostream>
#include <string>


struct Vector2
{
 float x, y;
 Vector2(float x, float y)
  : x(x), y(y) {}

 Vector2 Add(const Vector2& other) const
 {
  return Vector2(x + other.x, y + other.y);
  // return *this + other;
 }

 Vector2 operator+(const Vector2& other) const
 {
  return Add(other);
 }
 
 Vector2 Multiply(const Vector2& other) const
 {
  return Vector2(x * other.x, y * other.y);
 }

 Vector2 operator*(const Vector2& other) const
 {
  return Multiply(other);
  // return *this + other;
 }
 std::ostream& operator<<(std::ostream& stream, const Vector2& other)
{
 stream << other.x << "," << other.y;
 return stream;
}
};
int main()
{
 Vector2 position(4.0f, 4.0f);
 Vector2 speed(0.5f, 1.5f);
 Vector2 powerup(1.1f, 1.1f);
 // 加在一起
 Vector2 result = position.Add(speed.Multiply(powerup));

 Vector2 result1 = position + speed * powerup;   // +, * 运算符重载了
 std::cout << result << std::endl;   // << 操作符重载了

 std::cin.get();
}

==操作符

例6

#include <iostream>
#include <string>


struct Vector2
{
 float x, y;
 Vector2(float x, float y)
  : x(x), y(y) {}

 Vector2 Add(const Vector2& other) const
 {
  return Vector2(x + other.x, y + other.y);
  // return *this + other;
 }

 Vector2 operator+(const Vector2& other) const
 {
  return Add(other);
 }
 
 Vector2 Multiply(const Vector2& other) const
 {
  return Vector2(x * other.x, y * other.y);
 }

 Vector2 operator*(const Vector2& other) const
 {
  return Multiply(other);
  // return *this + other;
 }
 std::ostream& operator<<(std::ostream& stream, const Vector2& other)
{
 stream << other.x << "," << other.y;
 return stream;
}
bool operator==(const Vector2& other) const
 {
  return x == other.x && y == other.y;
 }
};
int main()
{
 Vector2 position(4.0f, 4.0f);
 Vector2 speed(0.5f, 1.5f);
 Vector2 powerup(1.1f, 1.1f);
 // 加在一起
 Vector2 result1 = position.Add(speed.Multiply(powerup));
 Vector2 result12 = position.Add(speed.Multiply(powerup));

 Vector2 result1 = position + speed * powerup;   // +, * 运算符重载了
 std::cout << result2 << std::endl;   // << 操作符重载了
if (result1 == result2)      // == 操作符重载了
 {  
 }
 std::cin.get();
}

!=操作符

例7

#include <iostream>
#include <string>


struct Vector2
{
 float x, y;
 Vector2(float x, float y)
  : x(x), y(y) {}

 Vector2 Add(const Vector2& other) const
 {
  return Vector2(x + other.x, y + other.y);
  // return *this + other;
 }

 Vector2 operator+(const Vector2& other) const
 {
  return Add(other);
 }
 
 Vector2 Multiply(const Vector2& other) const
 {
  return Vector2(x * other.x, y * other.y);
 }

 Vector2 operator*(const Vector2& other) const
 {
  return Multiply(other);
  // return *this + other;
 }
 std::ostream& operator<<(std::ostream& stream, const Vector2& other)
{
 stream << other.x << "," << other.y;
 return stream;
}
bool operator==(const Vector2& other) const
 {
  return x == other.x && y == other.y;
 }
 bool operator!=(const Vector2& other) const
 {
  return !(*this == other);
  // return !operator==(other);
 }
};
int main()
{
 Vector2 position(4.0f, 4.0f);
 Vector2 speed(0.5f, 1.5f);
 Vector2 powerup(1.1f, 1.1f);
 // 加在一起
 Vector2 result1 = position.Add(speed.Multiply(powerup));
 Vector2 result12 = position.Add(speed.Multiply(powerup));

 Vector2 result1 = position + speed * powerup;   // +, * 运算符重载了
 std::cout << result2 << std::endl;   // << 操作符重载了
if (result1 == result2)      // == 操作符重载了
 {  
 }
 if (result1 != result2)      // != 操作符重载了
 {  
 }
 std::cin.get();
}

C++的this关键字

  • 通过它,可以访问成员函数,即属于某个类的函数
  • this是一个指向当前对象实例的指针,该方法属于这个对象实例
  • 可以写一个方法,非静态方法,为了调用这个方法,首先需要实例化一个对象,然后调用这个方法;这个方法必须用一个有效的对象来调用,关键字this是指向该对象的指针

例8

#include <iostream>
#include <string>

class Entity
{
public:
 int x, y;

 Entity(int x, int y)
 {
  this->x = x;
  this->y = y;
 }

 int GetX() const
 {
  const Entity* e = this;  // this必须是const的
 }
};
int main()
{
 std::cin.get();
}

this是const Entity const 类型
在这里插入图片描述

在类外调用函数,可以使用this

例9

#include <iostream>
#include <string>

void PrintEntity(Entity* e);

class Entity
{
public:
 int x, y;

 Entity(int x, int y)
 {
  this->x = x;
  this->y = y;

  PrintEntity(this);
 }

 int GetX() const
 {
  const Entity* e = this;  // this必须是const的
 }
};


void PrintEntity(Entity* e)
{
 // Printing
}

int main()
{
 std::cin.get();
}
void PrintEntity(const Entity& e);
Entity& e = *this;
  PrintEntity(this);
void PrintEntity(const Entity& e)
{
 // Printing
}
int GetX() const
 {
  const Entity& e = *this;  // this必须是const的
 }

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

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

相关文章

13 SQL——数值函数

1 ceil() 数值向上取整&#xff08;前提是小数位不是0&#xff09; select ceil(1.2);2 floor() 数值向下取整&#xff08;前提是小数位不是0&#xff09;select floor(1.8);3 mod() 取&#xff08;x%y&#xff09;的模运算&#xff08;求余数运算&#xff09; select …

10. hr 综合面试题汇总

10. hr 综合面试题汇总 C++软件与嵌入式软件面经解析大全(蒋豆芽的秋招打怪之旅) 本章讲解知识点 1.1 HR心理复盘1.2 HR常问问题——学校的表现怎么样啊?1.3 HR常问问题——了解我们公司吗?1.4 HR常问问题——个人情况1.5 HR常问问题——业余生活1.6 HR常问问题——薪资待…

【源码角度】为什么AQS这样设计

AQS&#xff08;AbstractQueuedSynchronizer&#xff0c;抽象同步队列器&#xff09;是 一个基于 FIFO的双端队列。它分为独占模式和共享模式&#xff0c;本文主要围绕独占模式进行讲解&#xff0c;共享模式的原理和独占模式相似&#xff0c;最后会提一嘴。 场景代入 其实AQS模…

云计算基础(持续更新)

文章目录 云计算云计算的定义第1关&#xff1a;云计算定义第2关&#xff1a;云计算的基本原理 云计算出现的背景第1关&#xff1a;云计算出现的背景第2关&#xff1a;云计算的特征第3关&#xff1a;云计算的优势与劣势 虚拟化的类型第1关&#xff1a;虚拟化的定义第2关&#xf…

第六章结构型模式—代理模式

文章目录 代理模式解决的问题概念结构 静态代理动态代理织入的概念JDK 动态代理JDK 动态代理分析 CGLIB 动态代理 三种代理的对比JDK 和 CGLIB 的区别动态代理和静态代理的对比代理模式的优缺点使用场景 结构型模式描述如何将类或对象按某种布局组成更大的结构&#xff0c;有以…

浅谈springboot启动过程

1. 知识回顾 为了后文方便&#xff0c;我们先来回顾一下spring的一些核心概念。 spring最核心的功能无非是ioc容器&#xff0c;这个容器里管理着各种bean。ioc容器反映在java类上就是spring的核心类ApplicationContext。ApplicationContext有众多的子接口和子类&#xff0c;不…

SAP重复制造入门到放弃系列之基本配置

目录 前言 主要配置清单&#xff1a; REM参数文件&#xff1a; 计划订单计划参数文件 维护输入项参数 维护行选择 确认和物流信息系统全局设置 定义确认处理 操作方法表 其他 前言 重复制造中的配置步骤包括创建重复制造配置文件、为运行计划数量&#xff08;计划订单&a…

Excel技能之打印,19+技巧超省纸

颜色太多&#xff0c;重新打印。 没有边框&#xff0c;重新打印。 少了几列&#xff0c;重新打印。 整个工作表打印出来&#xff0c;拿剪刀把自己需要的数据剪下来&#xff0c;用胶水贴到另一张新的A4纸。 你上班打印资料&#xff0c;浪费了多少纸&#xff0c;认真算一下&…

PyCharm with Remote Interpreters

文章目录 一: 利用 Docker 镜像搭建1.编写 Dockerfile2.构建并配置 Remote Interpreters3.结论0.FAQ 二: 利用 SSH Docker 镜像搭建1.编写 Dockerfile2.构建并运行3.构建镜像4.运行容器5.验证并配置0.FAQ 起因是需要在 M2 芯片的 Mac 上调试基于 Python3.6.1 构建的程序. 而 M…

每天一道算法练习题--Day18 第一章 --算法专题 --- ----------前缀树

前缀树 字典树也叫前缀树、Trie。它本身就是一个树型结构&#xff0c;也就是一颗多叉树&#xff0c;学过树的朋友应该非常容易理解&#xff0c;它的核心操作是插入&#xff0c;查找。删除很少使用&#xff0c;因此这个讲义不包含删除操作。 截止目前&#xff08;2020-02-04&a…

bootloader编写——MCU固件升级系列2(STM32)

本系列将从升级流程、boot代码编写、APP代码编写以及固件打包来介绍&#xff0c;硬件选用STM32F407ZGT6&#xff08;手里只有&#xff09;&#xff0c;来完成这系列教程。 前言 开发STM32固件升级并编写Bootloader时&#xff0c;需要注意以下几个关键点&#xff1a; 熟悉硬件和…

数据结构篇四:栈

文章目录 前言1.栈1.1 栈的概念及结构1.2 栈的实现 2.栈功能的解析及实现2.1 栈的创建2.2 初始化2.3 入栈2.4 出栈2.5 检查栈是否为空2.6 获取栈顶元素2.7 栈中的有效元素个数2.8 销毁 3.代码实现3.1 Stack.h3.2 Stack.c3.3 test.c 4.总结 前言 前面学习的一些结构都比较普通&a…

13 | visual studio与Qt的结合

1 前提 Qt 5.15.2 visual studio 2019 vsaddin 2.8 2 具体操作 2.1 visual studio tool 2.1.1 下载 https://visualstudio.microsoft.com/zh-hans/downloads/2.1.2 安装 开发

推荐算法实战项目:WideDeep原理以及案例实战(附完整 Python 代码)

本文要介绍的是Google于2016年提出的Wide&Deep模型&#xff0c;此模型的提出对业界产生了非常大的影响&#xff0c;不仅其本身成功地应用在多家一线互联网公司&#xff0c;而且其后续的改进工作也一直延续至今。 Wide&Deep模型正如其名&#xff0c;分别包含了Wide部分…

golang - 函数的使用

核心化编程 为什么需要函数&#xff1f; 代码冗余问题不利于代码维护函数可以解决这个问题 函数 函数&#xff1a;为完成某一功能的程序指令&#xff08;语句&#xff09;的集合&#xff0c;称为函数 在 Go 中&#xff0c;函数分为&#xff1a;自定义函数&#xff08;自己写…

Apache Solr Velocity模板注入RCE

Apache Solr Velocity模板注入RCE 一、Apache Solr介绍 Solr是一个独立的企业级搜索应用服务器,它对外提供类似于web-service的API接口,用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引,也可以通过http get操作提出查找请求,并得到XML格式的返回结果。…

【openFrameworks】跨平台的 C++ 开源框架 | oF 文件结构 | 图形基础介绍

&#x1f4ad; 写在前面&#xff1a;本章我们将介绍一个非常好用的跨平台的 C 开源框架 —— openFrameworks。它是一个开源的跨平台的 C工具包&#xff0c;方便开发者创建出一个更简单和直观的框架&#xff0c;擅长开发图像和动画。 &#x1f4dc; 本章目录&#xff1a; 0x0…

SpringBoot集成SpringSecurity从0到1搭建权限管理详细过程(认证+授权)

前言 最近工作需要给一个老系统搭建一套权限管理&#xff0c;选用的安全框架是SpringSecurity&#xff0c;基本上是结合业务从0到1搭建了一套权限管理&#xff0c;然后想着可以将一些核心逻辑抽取出来写一个权限通用Demo&#xff0c;特此记录下。 文章目录 前言1、SpringSecuri…

CSS中4个定位设计与实现

1.相对定位 说明&#xff1a;相对原来元素的定位。开启定位后&#xff0c;元素层级高&#xff0c;会置于最上层 作用&#xff1a;用于元素的微调&#xff0c;不会脱离文档流 1.1代码实现 <!DOCTYPE html> <html lang"zh"> <head><meta charset…

外卖项目优化-01-redis缓存短信验证码、菜品数据、Spring Cache(注解开发缓存)、(注解开发)缓存套餐数据

文章目录 外卖项目优化-01课程内容前言1. 环境搭建1.1 版本控制解决branch和tag命名冲突 1.2 环境准备 2. 缓存短信验证码2.1 思路分析2.2 代码改造2.3 功能测试 3. 缓存菜品信息3.1 实现思路3.2 代码改造3.2.1 查询菜品缓存3.2.2 清理菜品缓存 3.3 功能测试3.4 提交并推送代码…