当前位置: 首页 > article >正文

C++学习笔记----7、使用类与对象获得高性能(一)---- 书写类(3)

2.4、this指针

        每个正常的成员函数调用都会隐含地传递一个指针给到对象,它就是被可能我的天this的隐藏参数。使用该指针访问数据成员或者调用成员函数,也可以将其传递给其他的成员函数或者函数。有时候它对消除有歧义的名字很有用。例如,可以给SpreadsheetCell类定义一个value的数据成员而不是m_value。这种情况下,setValue()可能就会像下面:

void SpreadsheetCell::setValue(double value)
{
	value = value; // Confusing!
}

        这行代码是不是很令人迷惑。你的value到底是指哪个:是作为参数传递的那个还是对象成员的那个?

        有些编译器或者编译器设置,上面令人迷惑的代码行能够正常编译,而不会生成报警或错误,但是不会生成代期待的正确结果。

        为了不让这些名字产生歧义,可以使用this指针:

void SpreadsheetCell::setValue(double value)
{
	this->value = value;
}

        然而,如果你使用了我们以前讨论过的命名规范,你就永远不会碰到这种名字冲突的情况。

        也可以使用this指针来调用一个作为参数的对象的成员函数的指向对象的指针。例如,假设你写了一个printCell()的单独的函数(不是成员函数)如下:

void printCell(const SpreadsheetCell& cell)
{
	println("{}", cell.getString());
}

        如果你想从setValue()成员函数中调用printCell(),一定要传递*this作为参数给到printCell()一个对于SpreadsheetCell的引用,setValue()在其上操作:

void SpreadsheetCell::setValue(double value)
{
	this->value = value;
	printCell(*this);
}

        注意:不要写printCell()函数,写一个我们以前解释过的客户化的格式会比较方便。可以使用下面的代码来打印一个叫做myCell的SpreadsheetCell的对象:

std::println("{}", myCell);

        换一种方式,可以重载<<操作符,这个我们以后讨论,可以写成下面这样:

cout << myCell << endl;

3、显式对象参数(c++23标准)

        从c++23开始,不用再依赖于编译器提供隐式的this参数,可以使用显式对象参数,通常是一个引用类型。下面的代码段用显式对象参数实现了前面的SpreadsheetCell的setValue()成员函数

void SpreadsheetCell::setValue(this SpreadsheetCell& self, double value)
{
	self.m_value = value;
	printCell(self);
}

        setValue()的第一个参数现在就是显式对象参数,通常叫做self,但是你可以使用任何你想使用的名字。self的类型以this关键字开头。该显式对象参数一定要是成员函数的第一个参数。一旦使用了显式对象参数,该函数就不再有隐式定义的this;因此,在setValue()函数体中,必须显式使用self来访问SpreadsheetCell中的任何东东。

        使用显式对象参数调用成员函数与使用隐式this参数并没有什么不同。即使setValue()现在指定了两个参数,self与value,你还是会传递一个单独的参数来调用它,该参数就是你想设置的value:

SpreadsheetCell myCell;
myCell.setValue(6);

        如示例使用显式对象参数并没有什么好处,甚至使代码更难读。然而,在下面这些情况下是非常有用的:

  • 提供更显式的语法来书写引用验证的成员函数,这个我们以后会讨论。
  • 对于成员函数模板,其显式对象参数的类型是一个模板类型的参数。在实现const与non-cost重载成员函数时避免代码重复会非常有用,这个我们以后也会讨论。
  • 书写递归lambda表达式时,这个我们以后再讨论。


http://www.kler.cn/news/307305.html

相关文章:

  • 蓝桥杯-基于STM32G432RBT6的LCD进阶(LCD界面切换以及高亮显示界面)
  • 【AIGC】CFG:基于扩散模型分类器差异引导
  • JavaScript 函数 function
  • 用 nextjs 创建 Node+React Demo
  • WebGL入门(048):OES_draw_buffers_indexed 简介、使用方法、示例代码
  • Python---爬虫
  • Leetcode-轮转数组
  • 复现OpenVLA:开源的视觉-语言-动作模型及原理详解
  • 【Go开发】Go语言结构体,与java类不一样的定义方式
  • 推荐|基于springBoot智能推荐的卫生健康系统设计与实现(源码+论文+数据库)
  • 【附源码】用Python开发一个音乐下载工具,并打包EXE文件,所有音乐都能搜索下载!
  • el-table 的单元格 + 图表 + 排序
  • 动手学深度学习(pytorch土堆)-03常见的Transforms
  • 图论篇--代码随想录算法训练营第五十六天打卡| 108. 冗余连接,109. 冗余连接II
  • 【SQL】百题计划:SQL排序Order by的使用。
  • Flutter Error: Type ‘UnmodifiableUint8ListView‘ not found
  • 刷题DAY36
  • 初中生物--5.单细胞生物
  • VuePress搭建文档网站/个人博客(详细配置)主题配置-导航栏配置
  • 【开源免费】基于SpringBoot+Vue.JS企业客户管理系统(JAVA毕业设计)
  • Linux命令:文本处理工具sed详解
  • django中F()和Q()的用法
  • 保姆级离线+windows环境+大模型前端UI安装(二)
  • 基于Spring Boot的停车场管理系统的设计与实现
  • 【STL】 set 与 multiset:基础、操作与应用
  • Vue路由配置、网络请求访问框架项目、element组件介绍学习
  • 数据库连接池与Druid【后端 16】
  • STM32 HAL freertos零基础(十)软件定时器
  • Renesas R7FA8D1BH (Cortex®-M85)控制ISLS29035
  • Unity-Transform类-父子关系