C++中重载箭头运算符详解

首先看一个例子

#include <iostream>
using namespace std;
class A
{
	void fun()
	{
		cout << "amazing" << endl;
	}
};
int main()
{
	A a;
	a->fun();//错误。“A”类型没有重载成员“operator ->”
	system("pause");
	return 0;
}
一般来说,类对象不能使用箭头运算符访问成员函数,而应该使用点运算符。但是,如果该类重载了箭头运算符,则情况发生改变。

看下面这个例子

#include <iostream>
using namespace std;
class A {
public:
	A() { i = 1; }
	void fun() {
		cout << "fun in class A!" << endl;
	}
public:
	int i;
};

class B {
	A a;
public:
	B() { i = 2; }
	A* operator->() {           //重载箭头运算符的函数居然返回的是指针,也就是对象的地址
		return &a;
	}
	void fun() {
		cout << "fun in class B!" << endl;
	}
private:
	int i;
};
class C {
	B b;
public:
	C() { i = 3; }
	B operator->() {             //重载箭头运算符的函数返回的是对象
		return b;
	}
	void fun() {
		cout << "fun in class C!" << endl;
	}
private:
	int i;
};

int main()
{
	C* p = new C();     //p是类C的一个指针
	p->fun();
	C c;               //c是类C的对象
	c->fun();
	int i = c->i;
	cout << i << endl;
	system("pause");
	return 0;
}


看见了吗?c是类C的一个对象,却可以使用箭头运算符。更神奇的是,你看一下运算结果,c->fun()居然结果是“fun in class A”,c->i的结果居然是1。

在C++ Primer中关于重载箭头运算符有这样一段总结:

(说明一)

对于形如point->mem的表达式来说,point必须是指向类对象的指针或者是重载了operator->的类的对象。根据point类型的不同,point->mem分别等价于

<1> (*point).mem                           //point是一个指针

<2>point.operator()->mem                //point是类的一个对象

而且,更为重要的是,按照我们一般的理解,重载箭头运算符返回的不应该是一个指针。那么你再看一下下面这段话:

(说明二)

重载箭头操作符必须返回指向类类型的指针,或者返回定义了自己的箭头操作符的类类型对象。

<1>如果返回类型是指针,则内置箭头操作符可用于该指针,编译器对该指针解引用并从结果对象获取指定成员。如果被指向的类型没有定义那个成员,则编译器产生一个错误。

<2>如果返回类型是类类型的其他对象(或是这种对象的引用),则将递归应用该操作符。编译器检查返回对象所属类型是否具有成员箭头,如果有,就应用那个操作符;否则,编译器产生一个错误。这个过程继续下去,直到返回一个指向带有指定成员的的对象的指针,或者返回某些其他值,在后一种情况下,代码出错。

那么现在给你解释一下程序的运行结果(非常重要)

<1>p是指针,按照上述说明一,应该调用的是(*p).fun(),这样结果就是“fun in class C!”

<2>c是定义了operator的类的一个对象,按照上述说明一,应该调用c.operator()->fun,接着类C的重载箭头运算符的成员函数返回值类型是类类型的其它对象,那么按照说明二,应该递归应用该操作符,那么现在来到了类B的重载箭头运算符的成员函数,此成员函数的返回值类型为指针,所以按照说明二,编译器对该指针解引用并从结果对象获取指定成员函数fun(),由于在类B的重载箭头运算符函数中返回的是类A的指针,所以调用类A的成员函数fun(),结果就是“fun in class A!”

     至于c->i,则是同理,自行感受。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值