C++箭头(->)运算符的重载

箭头操作符(->)的通常用法是,使用一个类对象的指针来调用该指针所指对象的成员。左操作数为对象指针(this),右操作数为该对象的成员名称。定义重载箭头操作符之后看起来就有点特别,可以用类对象的指针来调用,也可以用类对象直接调用。重载箭头操作符必须定义为类成员函数。

箭头操作符与众不同。它可能表现得像二元操作符一样:接受一个对象和一个成员名。对对象解引用以获取成员。不管外表如何,箭头操作符不接受显式形参。这里没有第二个形参,因为 -> 的右操作数不是表达式,相反,是对应着类成员的一个标识符。没有明显可行的途径将一个标识符作为形参传递给函数,相反,由编译器处理获取成员的工作。

8.1 箭头操作符的调用过程

当这样编写时:

     point->action();

由于优先级规则,它实际等价于编写:

     (point->action)();

    换句话说,我们想要调用的是对 point->action 求值的结果。编译器这样对该代码进行求值:

(1).如果 point 是一个指针,指向具有名为 action 的成员的类对象,则编译器将代码编译为调用该对象的 action 成员(默认语义)。

(2).否则,如果 point(注:中文版primer误写为action) 是定义了 operator-> 操作符的类的一个对象,则 point->action 与 point.operator->()->action 相同。即,执行 point 的 operator->(),然后使用该结果重复这三步。(递归调用)

(3).否则,代码出错。

总结:通过箭头(->)操作符的执行过程,我们可以得到结论“重载箭头操作符必须返回指向类类型的指针,或者返回定义了自己的箭头操作符的类类型对象。”返回前者用于执行编译器默认语义终结箭头运算符的调用(如果返回类型是指针,则内置箭头操作符可用于该指针,编译器对该指针解引用并从结果对象获取指定成员),返回后者用于递归调用。(如果返回类型是类类型的其他对象(或是这种对象的引用),则将递归应用该操作符。编译器检查返回对象所属类型是否具有成员箭头,如果有,就应用那个操作符;否则,编译器产生一个错误。这个过程继续下去,直到返回一个指向带有指定成员的的对象的指针,或者返回某些其他值,在后一种情况下,代码出错。)

8.2. 实例分析

根据理解,定义了3个类,C包含B,B包含A。A、B、C都定义了一个action的成员函数。B和C都重载箭头操作符,不同的是B的重载箭头操作符返回的是A类对象的指针,而C的重载箭头操作符返回的是B类对象。

#include <iostream>
using namespace std;  

class A{
public:
    void action(){
        cout << "Action in class A!" << endl;
    }
};  

class B{
    A a;
public:
    A* operator->(){  //返回指针
        return &a;
    }
    void action(){
        cout << "Action in class B!" << endl;
    }
};  

class C{
    B b;
public:
    B operator->(){  //返回对象
        return b;
    }
    void action(){
        cout << "Action in class C!" << endl;
    }
};  

int main(int argc, char *argv[])
{
    C* pc = new C;
    pc->action();  //指针调用(使用默认语义)
    C c;
    c->action();   //对象调用(使用重载语义)
    getchar();
    return 0;
}

 上面代码输出结果是:

Action in class C!
Action in class A!

 

其中的代码

 C* pc = new C;
 pc->action();

输出的结果是

Action in class C!

这个结果比较好理解,pc是类对象指针,此时的箭头操作符使用的是内置含义,对pc解引用然后调用对象的成员函数action。

 

 而下面的代码

 C c;
 c->action();

输出的结果是

Action in class A!

 其实c->action();的含义与c.operator->().operator->()->action();相同。

c是对象,c后面的箭头操作符使用的是重载箭头操作符,即调用类C的operator->()成员函数。此时返回的是类B的对象,所以调用类B的operator->()成员函数,B的operator->()返回的是指针,所以现在可以使用内置箭头操作符了。对B的operator->()返回的指针进行解引用,然后调用解引用后的对象的成员函数action,此时调用的就是类A的action()。这里存在一个递归调用operator->()的过程,最后再使用一次内置含义的箭头操作符。

总结:对箭头(->)运算符的调用,最终都要归结到对指针自身的(->)调用。

时间: 2025-01-30 00:25:13

C++箭头(-&gt;)运算符的重载的相关文章

编程-c++ 运算符的重载 运行时出现 debug 请各位大神帮忙找错

问题描述 c++ 运算符的重载 运行时出现 debug 请各位大神帮忙找错 // Chapter 8 of C++ How to Program// doubleScriptedArray.h#ifndef DARRAY_H#define DARRAY_H #include using std::ostream;using std::istream; class DoubleScriptedArray { friend ostream &operator<<(ostream&

第九周-任务1-Complex类中运算符的重载

[题目]接第8周任务1,定义Complex类中的<<和>>运算符的重载,实现输入和输出,改造原程序中对运算结果显示方式,使程序读起来更自然. [参考解答] #include <iostream> using namespace std; class Complex { public: Complex(){real=0;imag=0;} Complex(double r,double i){real=r;imag=i;} Complex operator-(); //实现

详解C++中的函数调用和下标以及成员访问运算符的重载_C 语言

函数调用使用括号调用的函数调用运算符是二元运算符. 语法 primary-expression ( expression-list ) 备注 在此上下文中,primary-expression 为第一个操作数,并且 expression-list(可能为参数的空列表)为第二个操作数.函数调用运算符用于需要大量参数的操作.这之所以有效,是因为 expression-list 是列表而非单一操作数.函数调用运算符必须是非静态成员函数. 函数调用运算符在重载时不会修改函数的调用方式:相反,它会在运算符

C++程序设计-第9周 运算符的重载(之二)

课程首页地址:http://blog.csdn.net/sxhelijian/article/details/7910565 本周目标是:1. 学会定义类中>>和<<运算符的重载函数:2. 理解通过运算符的重载解决实际问题的方法 [上机项目]项目1-3直接复制第8周的代码,加入要求的运算符重载定义后,作为第9周的项目另外发博文.[项目1-Complex类]接第8周项目1,定义Complex类中的<<和>>运算符的重载,实现输入和输出,改造原程序中对运算结果显

python 运算符 供重载参考_python

二元运算符 特殊方法 + __add__,__radd__ - __sub__,__rsub__ * __mul__,__rmul__ / __div__,__rdiv__,__truediv__,__rtruediv__ // __floordiv__,__rfloordiv__ % __mod__,__rmod__ ** __pow__,__rpow__ << __lshift__,__rlshift__ >> __rshift__,__rrshift__ & __an

C++学习摘要之七:运算符重载

C++语言中预定义的运算符的操作对象只能是基本数据类型,但是,在实际应用中,对于很多用户自定 义数据类型(如类)也需要类似的功能,这就需要对已有的运算符赋予多种含义,使同一个运算符具有作 用于不同类性的数据导致不同类型的行为,这就是运算符重载.因此,运算符重载的目的是设置C++语言 中的某一运算符,让它们之间并不冲突,C++语言会根据运算符的位置辨别应使用哪一种功能进行运算. 可见,运算符重载的优点是允许改变使用于系统内部的运算符的操作方式,以适应用户新定义类型的类似 运算. 运算符重载的实质是

C++运算符重载赋值运算符

自定义类的赋值运算符重载函数的作用与内置赋值运算符的作用类似,但是要要注意的是,它与拷贝构造函数与析构函数一样,要注意深拷贝浅拷贝的问题,在没有深拷贝浅拷贝的情况下,如果没有指定默认的赋值运算符重载函数,那么系统将会自动提供一个赋值运算符重载函数. 赋值运算符重载函数的定义与其它运算符重载函数的定义是差不多的. 下面我们以实例说明如何使用它,代码如下: //程序作者:管宁//站点:www.cndev-lab.com//所有稿件均有版权,如要转载,请务必著名出处和作者#include <iostr

C++运算符重载转换运算符

为什么需要转换运算符? 大家知道对于内置类型的数据我们可以通过强制转换符的使用来转换数据,例如(int)2.1f;自定义类也是类型,那么自定义类的对象在很多情况下也需要支持此操作,C++提供了转换运算符重载函数,它使得自定义类对象的强转换成为可能. 转换运算符的生命方式比较特别,方法如下: operator 类名(); 转换运算符的重载函数是没有返回类型的,它和类的构造函数,析构函数一样是不遵循函数有返回类型的规定的,他们都没有返回值. 下面我看一个例子,看看它是如何工作的: //例1 //程序

C++运算符重载函数基础及其值返回状态

运算符重载是C++的重要组成部分,它可以让程序更加的简单易懂,简单的运算符使用可以使复杂函数的理解更直观. 对于普通对象来说我们很自然的会频繁使用算数运算符让他们参与计算,但是对于自定义类的对象来说,我们是无论如何也不能阻止写出像下面的代码一样的程序来的. 例子如下: class Test{ //过程省略}int main(){ Test a,c; c=a+a;} 当然这样的代码是不能够通过编译的,c++对自定类的算术运算部分保留给了程序员,这也是符合c++灵活特性的. 在c++中要想实现这样的