【转】C++对成员访问运算符->的重载

 运算符->的重载比较特别,它只能是非静态的成员函数形式,而且没有参数。

1、如果返回值是一个原始指针,那么就将运算符的右操作数当作这个原始指针所指向类型的成员进行访问;

2、如果返回值是另一个类型的实例,那么就继续调用这个返回类型的operator->(),直到有一个调用返回一个原始指针为止,然后按第一种情况处理。

如果上述条件不满足(如:右操作数不是返回的原始指针指向的类型中的成员,或者,返回的非指针类型(另一个类型的实例)没有重载operator->()),那么编译将报错。

以下是用于验证的程序片段:

/*******************************************************
* File Name:main.cpp
* Description:演示成员访问操作符->的重载 
* Version:V1.0 
* Author:Mengjia 
* Date:2018-05-20 
* Copyright (C)2018, Mengjia
* Others:
******************************************************************************
运算符->的重载比较特别,它只能是非静态的成员函数形式(即不能在类外重载),
而且没有参数。
1、如果返回值是一个原始指针,那么就将运算符的右操作数当作这个原始
指针所指向类型的成员进行访问;
2、如果返回值是另一个类型的实例,那么就继续调用这个返回类型的operator->(),直到
有一个调用返回一个原始指针为止,然后就按第一种情况处理。

如果上述条件不满足(如:右操作数不是返回的原始指针指向的类型的成员,或者,
返回的另一个类型的实例中没有重载operator->()),那么编译将报错。
******************************************************************************
*******************************************************/
#include <iostream>
using namespace std;

//原始类
struct Origin
{
    int a;
};
//包装器类1,包装Origin类
struct Wrapper
{
    Origin* orig;
    Origin* operator->() const
    {
        return orig;    //返回原始指针
    }
};
//包装器类2,包装Wrapper类
struct Wrapper2
{
    Wrapper* wrap;
    Wrapper& operator->() const
    {
        return *wrap;    //返回类对象
    }
};
int main()
{
    Origin o;
    o.a = 7;
    Wrapper w;
    w.orig = &o;
    Wrapper2 w2;
    w2.wrap = &w;

    cout << "w->a" << "\t\t\t\t" << w->a << endl;
    cout << "w.operator->()" << "\t\t\t" << w.operator->() << endl;
    cout << "w.operator->()->a" << "\t\t" << w.operator->()->a << endl;

    cout << "w2->a" << "\t\t\t\t" << w2->a << endl;
    cout << "&w2.operator->()" << "\t\t" << &w2.operator->() << endl;
    cout << "w2.operator->()->a" << "\t\t" << w2.operator->()->a << endl;
    cout << "w2.operator->().operator->()" << "\t" << w2.operator->().operator->() << endl;
    cout << "w2.operator->().operator->()->a" << "\t" << w2.operator->().operator->()->a << endl;

    system("pause");
    return 0;

}

/*
*输出结果:
w->a                            7
w.operator->()                  00AFF7E4
w.operator->()->a               7
w2->a                           7
&w2.operator->()                00AFF7D8
w2.operator->()->a              7
w2.operator->().operator->()    00AFF7E4
w2.operator->().operator->()->a 7
**/

其中,最为诡异的就是w2->a输出的是7。

按照上面总结的结论,这个调用其实会被编译器转换成w2.operator->().operator->()->a的形式,所以输出的是7。

转自《C++对成员访问操作符->的重载》

原文地址:https://www.cnblogs.com/codingmengmeng/p/9064702.html

时间: 2024-10-10 23:01:08

【转】C++对成员访问运算符->的重载的相关文章

C++ Primer笔记12_运算符重载_递增递减运算符_成员访问运算符

1.递增递减运算符 C++语言并不要求递增递减运算符必须是类的成员.但是因为他们改变的正好是所操作对象的状态,所以建议设定为成员函数. 对于递增与递减运算符来说,有前置与后置两个版本,因此,我们应该为类定义两个版本的递增与递减运算符. 问题来了,程序是如何区分前置和后置呢?因为都是++和-- 为了解决这个问题,后置版本的递增递减运算符接受一个额外的(不被使用)int类型的形参.当我们使用后置运算符时,编译器为这个形参提供一个值为0的实参.这个形参唯一的作用就是区分前置和后置运算符函数. 因为不会

重载运算与类型转换——基本概念,输入和输出运算符,算术和关系运算符,赋值运算符,下标运算符,递增和递减运算符,成员访问运算符

一.基本概念 重载的运算符时具有特殊名字的函数:它们的名字由关键字operator和其后要定义的运算符号共同组成.和其他函数一样,重载的运算符也包含返回类型.参数列表以及函数体. 重载运算符函数的参数数量与该运算符作用的运算对象数量一样多.一元运算符有一个参数,二元运算符有两个.对于二元运算符来说,左侧运算对象传递给第一个参数,而右侧运算对象传递给第二个参数.除了重载的函数调用运算符operator()之外,其他重载运算符不能含有默认实参. 当一个重载的运算符时成员函数时,this绑定到左侧运算

C++学习笔记(十一):成员访问运算符(点运算和箭头运算)

成员访问运算符 点运算符"."和箭头运算符"->",都可以用于访问成员,其中点运算获取类对象的一个成员,箭头运算获取指针指向对象的成员.表达式ptr->men等价于(*ptr).mem: string s = "hello",  *p = &s; auto n = s.size();                        //获取string对象的成员 n = (*p).size();                

【共读Primer】26.&lt;4.6&gt;成员访问运算符 Page133

成员访问运算符: . 点运算符 -> 箭头运算符 string s1="a string", *p = &s1; auto n = s1.size(); // 运行string对象s1的size成员 n = (*p).size(); // 运行p所知对象的size成员 n = p->size(); // 等价于(*p).size() 因为皆因用运算符的优先级低于点运算符,所以执行解引用运算的子表达式两端必须加括号. 如果不加括号则含义会不同 // 含义是:运行p的s

C# 主要运算符中的成员访问

在开发过程中,我遇到了一种null 条件成员访问的写法,开始不太理解,之后专门查了微软的官方文档,下面是具体内容:   三种成员访问的三种形式 (1)x.y:成员访问. (2)x?.y:null 条件成员访问. 如果左操作数计算结果为 null,则返回 null. (3)x?[y]:null 条件数组元素或类型索引器访问. 如果左操作数计算结果为 null,则返回 null. 其中,我主要介绍一下第二和第三种,x?.y以及x?[y]的语法:Null 条件运算符在 C# 6 及更高版本中可用,仅当

C++——运算符的重载---以成员函数方式重载---以友元函数方式重载

一.运算符的重载 1.运算符的重载 允许把标准运算符(如+ - * /等运算符)应用于自定义数据类型的对象,可以提高程序的可读性,运算符的重载本质上还是函数重载.运算符仅仅是语法上的方便,它是另一种函数调用的方式,只有在设计涉及的代码更容易写,尤其是更容易读的时候才有必要重载. 2.实现运算符重载的方式 类的成员函数 友元函数(即类外的普通函数) 3.运算符重载的原则: 不能重载的运算符有5个:  .  .*  ?: ::  sizeof 运算符重载不允许发明新的运算符 不能改变运算符操作对象的

运算符的重载(复数的相关运算)

运算符的重载实际是一种特殊的函数重载,必须定义一个函数,并告诉C++编译器,当遇到该重载的运算符时调用此函数.这个函数叫做运算符重载函数,通常为类的成员函数.    定义运算符重载函数的一般格式: 返回值类型 类名::operator重载的运算符(参数表) {--} operator是关键字,它与重载的运算符一起构成函数名.因函数名的特殊性,C++编译器可以将这类函数识别出来. 具体的加减乘除等代码运算如下: #include<iostream> #include<string>

输出流运算符的重载疑点

今天看到流运算符重载的时候有几个疑问,一是为何在只需声明一次friend即可,而不是在两个类之间都使用friend,二是为何不能重载为成员函数. 第一个问题:都使用friend,函数需要访问两个类的私有成员 第二个问题:重载为了成员函数,但应用上出现了问题,详情见代码. using std::ostream; class a { public:     ostream& operator<< (ostream & out)     {         out << 

C++ 运算符的重载(转载自http://blog.csdn.net/insistgogo/article/details/6626952)

(转载自http://blog.csdn.net/insistgogo/article/details/6626952) 什么是运算符的重载? 运算符与类结合,产生新的含义. 为什么要引入运算符重载? 作用:为了实现类的多态性(多态是指一个函数名有多种含义) 怎么实现运算符的重载? 方式:类的成员函数 或 友元函数(类外的普通函数) 规则:不能重载的运算符有 .  和 .* 和 ?: 和 ::  和 sizeof 友元函数和成员函数的使用场合:一般情况下,建议一元运算符使用成员函数,二元运算符使