首页 > 其他分享 >`->` 操作符重载的注意事项

`->` 操作符重载的注意事项

时间:2024-09-29 14:46:32浏览次数:7  
标签:调用 operator 编译器 操作符 注意事项 重载 指针

在 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->(),获取返回值。
  • 第三步:如果返回值仍是对象而非指针,继续递归调用 ->,直到返回一个指针。
  • 第四步:一旦返回指针,正常使用指针访问成员。

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

标签:调用,operator,编译器,操作符,注意事项,重载,指针
From: https://www.cnblogs.com/niumachen/p/18439780

相关文章

  • 操作符-单目操作符
    !   反操作符-    减+   加&   取地址操作符~   --++*布尔类型(表示真假类型)一、操作符用法反操作符(!)#include<stdio.h>intmain(){ while(!0) { printf("哈哈\n"); } return0;}这是个死循环,会一直打印“哈哈”,因为!0表示真,0表......
  • 友元运算符重载函数
    目录1.定义友元运算符重载函数的语法形式2.双目运算符重载3.单目运算符重载1.定义友元运算符重载函数的语法形式        (1)在类的内部,定义友元运算符重载函数的格式如下:friend函数类型operator运算符(形参表){函数体}        (2)在类中,声明友......
  • C++友元和运算符重载
    目录一.友元friend1.1概念1.2友元函数1.3友元类1.4友元成员函数二.运算符重载2.1概念2.2成员函数运算符重载2.3成员函数运算符重载2.4特殊运算符重载2.4.1赋值运算符重载2.4.2类型转换运算符重载2.5注意事项三、std::string字符串类(熟悉)一.友元......
  • Day4 C++(运算符重载,模板与容器)(友元函数,运算符重载,赋值运算符,string字符串类,模板)
    1.友元friend1.1概念(掌握)定义:类实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,仅能通过类的成员函数才能读写。如果数据成员定义为公共的,则又破坏了封装性。但是某些情况下,需要频繁读写类的成员,特别是在对某些成员函数多次调用时,由于参数传递、类型检查和安全......
  • C++ Practical-2 day2 运算符重载之时钟类++运算符
    系列文章目录点击直达——文章总目录文章目录系列文章目录C++Practical-2day2运算符重载之时钟类++运算符Overview1.时间类重载后缀`++`运算符来递增时间1.1.解释1.2.注意事项2.如何确保时间递增操作在多线程环境中是线程安全的?关于作者C++Practical-2day......
  • 算法备案如何办理和注意事项
    一、“算法备案”概述“算法备案”,全称为互联网信息服务算法推荐活动备案,是中国政府为了规范互联网信息服务算法推荐活动而设立的一种管理制度。该制度旨在确保算法应用的公平公正、透明可释,同时保护用户的合法权益,促进互联网行业的健康发展。互联网信息服务算法备案是由国家......
  • C++ -函数重载-详解
    博客主页:【夜泉_ly】本文专栏:【C++】欢迎点赞......
  • XILINX FIR IP核系数重载功能的学习以及测试
    XILINXFIRIP核系数重载功能的学习以及测试最近在学习宽带数字接收机的一些东西,其中多相滤波是属于其中比较关键的一环,笔者在matlab上成功仿真了多相滤波这一环节后,便想着在FPGA上实现多相滤波,多相滤波器的一个重要环节便是滤波器组的设计,简单来讲,滤波器组是由原型低......
  • Windows环境下安装pytorch及注意事项
    前言:最近学习pytorch,在安装配置环境时花了很大功夫,实际上整件事情并不难,但是由于有很多细节比如版本匹配问题,可能会踩很多坑,从而浪费大量时间,故我在成功安装配置完pytorch后,写下一点总结,为后来者提供一些参考,使能够将更多的时间真正专注于科研上,而不必在安装配置上徒添烦恼。......
  • C++考试题-9道编程题运算符重载带部分答案
    【1】写出下列程序的运行结果。#include<iostream>   usingnamespacestd;classA{public:   A(inti):x(i)   { }   A(){x=0;}   friendAoperator++(Aa);   friendAoperator--(A&a);   voidprint();private:   i......