在 C++ 中,-> 操作符可以被重载,用于对象的指针成员访问。

重载后的 -> 操作符主要用于模拟指针访问行为,常见于智能指针的实现等复杂场景。

-> 操作符重载后的调用触发流程:

在对象上使用 -> 操作符时,编译器按照以下步骤处理:

  1. 检查对象类型是否有 operator->() 重载

    • 如果对象是一个用户定义的类型(比如类、结构体),编译器首先会检查该类型是否定义了 operator->() 函数。
  2. 调用 operator->() 并获得返回值

    • 如果有 operator->() 重载,编译器会调用这个操作符,并获取它的返回值

      这个返回值必须是一个指针或能够再次使用 -> 操作符的对象
  3. 递归调用 ->

    • 如果 operator->() 返回的值是一个对象而不是直接的指针,编译器将对这个返回的对象再次应用 -> 操作符(如果它也有 operator->() 重载)。

      这个过程会递归进行,直到最终返回的是一个指针为止。
  4. 访问指针成员

    -** 一旦 -> 操作最终返回一个指针,编译器就会访问这个指针指向的成员**。

触发流程示例

1. 操作符重载示例:

假设我们定义了一个智能指针类,并重载了 operator->()

#include <iostream>

class Test {
public:
void show() { std::cout << "Test::show() called\n"; }
}; class SmartPointer {
private:
Test* ptr; // 原始指针
public:
SmartPointer(Test* p = nullptr) : ptr(p) {} // 重载 -> 操作符
Test* operator->() {
return ptr;
}
}; int main() {
Test* realPtr = new Test();
SmartPointer sp(realPtr); sp->show(); // 实际上调用了 sp.operator->()->show(); delete realPtr;
return 0;
}

2. 调用流程解释:

  1. sp->show() 被编译器处理为 sp.operator->()->show()

  2. sp.operator->() 返回一个 Test* 类型的指针,即 realPtr

  3. realPtr->show() 然后被调用,输出 "Test::show() called"

递归调用示例

operator->() 可以递归调用。比如返回的不是指针,而是另一个对象,该对象也重载了 operator->()

#include <iostream>

class A {
public:
void display() { std::cout << "A::display() called\n"; }
}; class B {
private:
A a;
public:
A* operator->() {
return &a;
}
}; class C {
private:
B b;
public:
B* operator->() {
return &b;
}
}; int main() {
C obj;
obj->display(); // 实际上是 obj.operator->()->operator->()->display();
return 0;
}

递归流程解释:

  1. obj->display() 被编译器转换为 obj.operator->()->display()

  2. C::operator->() 返回 B*,即 &b

  3. 编译器接着在 B 上调用 ->,即 b->display()

  4. B::operator->() 返回 A*,即 &a

  5. 最终调用 a->display(),执行了 A::display()

关键点:

  • operator->() 必须返回一个指针或具有 operator->() 重载的对象。如果它不返回一个可以继续使用 -> 的对象或指针,编译器会报错。
  • 重载后的 -> 可以递归调用,直到最后返回一个实际的指针,才能真正访问对象的成员。

注意事项:

  • 通常情况下,重载 operator->() 是为了实现类似智能指针的功能,确保可以用类似指针的方式访问内部对象。
  • 重载 operator->() 的返回值一般是指向对象的指针,因此在重载时要确保返回值是能够继续使用 -> 的类型。

总结:

  • 第一步:编译器检查对象是否有 operator->()
  • 第二步:调用 operator->(),获取返回值。
  • 第三步:如果返回值仍是对象而非指针,继续递归调用 ->,直到返回一个指针。
  • 第四步:一旦返回指针,正常使用指针访问成员。

这种机制使得类对象能够模拟指针行为,并通过 -> 直接访问底层对象的成员。

`->` 操作符重载的注意事项的更多相关文章

  1. 15.C++-操作符重载

    首先回忆下以前学的函数重载 函数重载 函数重载的本质为相互独立的不同函数 通过函数名和函数参数来确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的函数重载 ...

  2. 15.C++-操作符重载、并实现复数类

    首先回忆下以前学的函数重载 函数重载 函数重载的本质为相互独立的不同函数 通过函数名和函数参数来确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的函数重载 ...

  3. C++解析(17):操作符重载

    0.目录 1.操作符重载 2.完善的复数类 3.小结 1.操作符重载 下面的复数解决方案是否可行? 示例1--原有的解决方案: #include <stdio.h> class Compl ...

  4. c++之旅:操作符重载

    操作符重载 操作符重载可以为操作符添加更多的含义,操作符重载的作用的对象是类 那些操作符可以重载 除了下面几个操作符不能重载外,其它的操作符都能重载 . :: .* ?: sizeof 操作符重载的本 ...

  5. C++中的赋值操作符重载和拷贝构造函数

    1,关于赋值的疑问: 1,什么时候需要重载赋值操作符? 2,编译器是否提供默认的赋值操作符? 2,关于赋值的疑问: 1,编译器为每个类默认重载了赋值操作符: 1,意味着同类型的类对象可以相互赋值: 2 ...

  6. C++中采用操作符重载完善复数类

    1,复数类应该具有的操作: 1,运算:+,-,*,/: 2,比较:==,!=: 3,赋值:=: 4,求模:modulus: (5),完善的复数类操作符重载必不可少: 2,利用操作符重载: 1,统一复数 ...

  7. c++ 操作符重载和友元

    操作符重载(operator overloading)是C++中的一种多态,C++允许用户自定义函数名称相同但参数列表不同的函数,这被称为函数重载或函数多态.操作符重载函数的格式一般为: operat ...

  8. paip.操作符重载的缺失 Java 的一个大缺点

    paip.操作符重载的缺失 Java 的一个大缺点 #----操作符重载的作用 1.提升用户体验 操作符重载..可以让代码更加自然.... 2.轻松实现代码代码移植 例如   java代码会直接移植到 ...

  9. C#中如何利用操作符重载和转换操作符

    操作符重载 有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成 ...

  10. 操作符重载.xml

    pre{ line-height:1; color:#1e1e1e; background-color:#d2d2d2; font-size:16px;}.sysFunc{color:#627cf6; ...

随机推荐

  1. 一步一步分析HTTPS加密机制

    一步一步分析HTTPS加密机制 HTTPS(SSL/TLS)的加密机制虽然是大家都应了解的基本知识, 但是更多的时候我们只是在背诵一些概念, 比如: "对称加密", "非 ...

  2. Python 在PDF中添加、替换、或删除图片

    PDF文件中的图片可以丰富文档内容,提升用户的阅读体验.除了在PDF中添加图片外,有时也需要替换或删除其中的图片,以改进视觉效果或更新信息.本文将提供以下三个示例,介绍如何使用Python 操作PDF ...

  3. 结合拦截器描述mybatis启动流程

    简介 mybatis的启动入口一般有两个,在结合spring框架后由spring整合包下的SqlSessionFactoryBean启动 如果没有整合spring,则有XMLConfigBuilder ...

  4. TinyVue v3.17.0 正式发布,推出了一款基于 Quill 2.0 的富文本编辑器,功能强大、开箱即用!

    你好,我是 Kagol. 我们非常高兴地宣布,2024年6月26日,TinyVue 发布了 v3.17.0 . TinyVue 每次大版本发布,都会给大家带来一些实用的新特性,上一个版本我们重构了 c ...

  5. 2018年视频,路径规划:层次化路径规划系统——hierarchical pathfinding system —— Hierarchical Dynamic Pathfinding for Large Voxel Worlds (续)

    前文: 2018年视频,路径规划:层次化路径规划系统--hierarchical pathfinding system -- Hierarchical Dynamic Pathfinding for ...

  6. 【转载】 拒绝遗忘:高效的动态规划算法 —— “到底什么是动态规划”—— An intro to Algorithms: Dynamic Programming

    原文地址(英文): https://medium.freecodecamp.org/an-intro-to-algorithms-dynamic-programming-dd00873362bb   ...

  7. Jax报错:Windows系统环境下WSL中运行Jax会导致nvidia-smi报错退出,无法使用nvidia-smi和gpustat

    环境: Window11下的WSL: 运行jax,导致nvidia-smi无法使用,不过经过测试发现虽然nvidia-smi报错无法使用,但是GPU已经可以正常使用,调用jax的GPU运行也保持正常, ...

  8. Game of CS 题解

    前言 题目链接:洛谷:UVA. 题意简述 Jolly 和 Emily 在玩一个游戏.游戏在一棵编号为 \([0, n-1]\) 的有根树上进行,根节点是 \(0\),每条边都有一个长度,初始所有边都没 ...

  9. BMC Genomics | 综合代谢组学和转录组学分析揭示了菊花黄酮和咖啡酰奎宁酸的生物合成机制

    杭白菊是一种流行的药用和食用植物,主要通过黄酮类和咖啡酰奎宁酸(CQAs)的存在发挥其生物活性.然而,菊花头状花序中黄酮和CQA生物合成的调控机制尚不清楚. 本研究采用高效液相色谱法测定了菊花头状花序 ...

  10. CF1992场题解

    Only Pluses 算法:数学. 题意简述:有三个数,每次选择一个数 \(x\),使得 \(x\) 增加一,至多操作 \(5\) 次,最后求出这三个数的乘积最大值. 简单题,一眼秒了.考虑把这 \ ...