`->` 操作符重载的注意事项
在 C++ 中,-> 操作符可以被重载,用于对象的指针成员访问。
重载后的 -> 操作符主要用于模拟指针访问行为,常见于智能指针的实现等复杂场景。
-> 操作符重载后的调用触发流程:
在对象上使用 -> 操作符时,编译器按照以下步骤处理:
检查对象类型是否有
operator->()重载:- 如果对象是一个用户定义的类型(比如类、结构体),编译器首先会检查该类型是否定义了
operator->()函数。
- 如果对象是一个用户定义的类型(比如类、结构体),编译器首先会检查该类型是否定义了
调用
operator->()并获得返回值:- 如果有
operator->()重载,编译器会调用这个操作符,并获取它的返回值。
这个返回值必须是一个指针或能够再次使用->操作符的对象。
- 如果有
递归调用
->:- 如果
operator->()返回的值是一个对象而不是直接的指针,编译器将对这个返回的对象再次应用->操作符(如果它也有operator->()重载)。
这个过程会递归进行,直到最终返回的是一个指针为止。
- 如果
访问指针成员:
-** 一旦->操作最终返回一个指针,编译器就会访问这个指针指向的成员**。
触发流程示例
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. 调用流程解释:
sp->show()被编译器处理为sp.operator->()->show()。sp.operator->()返回一个Test*类型的指针,即realPtr。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;
}
递归流程解释:
obj->display()被编译器转换为obj.operator->()->display()。C::operator->()返回B*,即&b。编译器接着在
B上调用->,即b->display()。B::operator->()返回A*,即&a。最终调用
a->display(),执行了A::display()。
关键点:
operator->()必须返回一个指针或具有operator->()重载的对象。如果它不返回一个可以继续使用->的对象或指针,编译器会报错。- 重载后的
->可以递归调用,直到最后返回一个实际的指针,才能真正访问对象的成员。
注意事项:
- 通常情况下,重载
operator->()是为了实现类似智能指针的功能,确保可以用类似指针的方式访问内部对象。 - 重载
operator->()的返回值一般是指向对象的指针,因此在重载时要确保返回值是能够继续使用->的类型。
总结:
- 第一步:编译器检查对象是否有
operator->()。 - 第二步:调用
operator->(),获取返回值。 - 第三步:如果返回值仍是对象而非指针,继续递归调用
->,直到返回一个指针。 - 第四步:一旦返回指针,正常使用指针访问成员。
这种机制使得类对象能够模拟指针行为,并通过 -> 直接访问底层对象的成员。
`->` 操作符重载的注意事项的更多相关文章
- 15.C++-操作符重载
首先回忆下以前学的函数重载 函数重载 函数重载的本质为相互独立的不同函数 通过函数名和函数参数来确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的函数重载 ...
- 15.C++-操作符重载、并实现复数类
首先回忆下以前学的函数重载 函数重载 函数重载的本质为相互独立的不同函数 通过函数名和函数参数来确定函数调用 无法直接通过函数名得到重载函数的入口地址 函数重载必然发生在同一个作用域中 类中的函数重载 ...
- C++解析(17):操作符重载
0.目录 1.操作符重载 2.完善的复数类 3.小结 1.操作符重载 下面的复数解决方案是否可行? 示例1--原有的解决方案: #include <stdio.h> class Compl ...
- c++之旅:操作符重载
操作符重载 操作符重载可以为操作符添加更多的含义,操作符重载的作用的对象是类 那些操作符可以重载 除了下面几个操作符不能重载外,其它的操作符都能重载 . :: .* ?: sizeof 操作符重载的本 ...
- C++中的赋值操作符重载和拷贝构造函数
1,关于赋值的疑问: 1,什么时候需要重载赋值操作符? 2,编译器是否提供默认的赋值操作符? 2,关于赋值的疑问: 1,编译器为每个类默认重载了赋值操作符: 1,意味着同类型的类对象可以相互赋值: 2 ...
- C++中采用操作符重载完善复数类
1,复数类应该具有的操作: 1,运算:+,-,*,/: 2,比较:==,!=: 3,赋值:=: 4,求模:modulus: (5),完善的复数类操作符重载必不可少: 2,利用操作符重载: 1,统一复数 ...
- c++ 操作符重载和友元
操作符重载(operator overloading)是C++中的一种多态,C++允许用户自定义函数名称相同但参数列表不同的函数,这被称为函数重载或函数多态.操作符重载函数的格式一般为: operat ...
- paip.操作符重载的缺失 Java 的一个大缺点
paip.操作符重载的缺失 Java 的一个大缺点 #----操作符重载的作用 1.提升用户体验 操作符重载..可以让代码更加自然.... 2.轻松实现代码代码移植 例如 java代码会直接移植到 ...
- C#中如何利用操作符重载和转换操作符
操作符重载 有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成 ...
- 操作符重载.xml
pre{ line-height:1; color:#1e1e1e; background-color:#d2d2d2; font-size:16px;}.sysFunc{color:#627cf6; ...
随机推荐
- 解决cnpm syscall: ‘rename‘
1.删了cnpm npm uninstall -g cnpm 2.指定版本下载cnpm npm install cnpm@7.1.0 -g
- hbuilderx打正式包所需的私钥证书的创建方法
现在使用uniapp作为底层框架来开发app应用已经成为了很多公司的事实标准,而uniapp的开发工具hbuilderx云打包的时候,需要私钥证书和证书profile文件. 而且还需要将打包好的ipa ...
- 【Android】构建Android12项目报错
报错信息: Installed Build Tools revision 31.0.0 is corrupted. Remove and install again using the SDK Man ...
- 【Win10】找不到Telnet命令
百度才发现原来我的Telnet程序就没启动... CMD终端就找不到命令... 但是有一点要注意!不能使用CMD之外的终端访问[GitBash访问无效] 打开控制面板,点卸载程序: 然后点击启动和关闭 ...
- ComfyUI插件:ComfyUI layer style 节点(四)
前言: 学习ComfyUI是一场持久战,而ComfyUI layer style 是一组专为图片设计制作且集成了Photoshop功能的强大节点.该节点几乎将PhotoShop的全部功能迁移到Comf ...
- OneFlow框架0.9.1dev版本,成功安装并运行
安装cuda和cudnn: (此步骤可以忽略,pip安装框架时会自动安装依赖的cuda和cudnn环境) conda install cudatoolkit==11.8.0 python3 -m pi ...
- Inno Setup 出现 the drive or unc share you selected does not exist or is not accessible 解决记录
背景 软件是使用Inno Setup的,且安装后,再次安装是默认安装到历史路径.一次用户电脑维修后,发现再次安装后报错 解决办法 取消自动安装到默认路径就好了~ UsePreviousAppDir=n ...
- Avnet ZUBoard 1CG开发板上手—深度学习新选择
Avnet ZUBoard 1CG 开发板上手-深度学习新选择 摘要 本文主要介绍了 Avnet ZUBoard 1CG 开发板的特性.架构.硬件单元等概念,并对如何使用以太网接口和串口连接开发板进行 ...
- 仅花一天时间,开发者重制 32 年前经典 Mac 应用!
导读:在这个快节奏的技术世界里,重温过去并从中汲取灵感总是一件有趣的事情.今天要介绍的是一款仅用一天时间重制的经典 Macintosh 应用--Stapler.这款应用最初发布于1992年,现在由一位 ...
- 使用 Gradle 构建包含所有依赖的 JAR 包
在 Gradle 中构建一个包含所有依赖的 jar 包(通常被称为"fat jar"或者"uber jar"),你可以使用 shadowJar 插件来包含编译的 ...