Overloading member access operators ->, .* (C++)
我了解大多数运算符重载,除了成员访问运算符
尤其是,传递给这些运算符函数的是什么,应该返回什么?
操作员如何工作(如
最后,是否需要考虑任何常量因素?例如,当重载诸如
这是唯一一个非常棘手的问题。它必须是非静态成员函数,并且不接受参数。返回值用于执行成员查找。
如果返回值是类类型的另一个对象,而不是指针,那么随后的成员查找也由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | struct client { int a; }; struct proxy { client *target; client *operator->() const { return target; } }; struct proxy2 { proxy *target; proxy &operator->() const { return * target; } }; void f() { client x = { 3 }; proxy y = { & x }; proxy2 z = { & y }; std::cout << x.a << y->a << z->a; // print"333" } |
这件事很棘手,因为它没有什么特别之处。非重载版本需要左侧的指向类类型的指针对象和右侧的指向成员类型的指针对象。但是,当您超载它时,您可以接受任何您喜欢的参数,并返回任何您想要的。它甚至不必是非静态成员。
换句话说,这只是一个普通的二元运算符,如
这些不能超载。当左侧是类类型时,已经有了内置的含义。也许能够为左侧的指针定义它们是有点道理的,但是语言设计委员会认为这会比有用更令人困惑。
重载
operator->是特殊的。
它有附加的、非典型的约束:它必须返回一个对象(或对对象的引用),该对象还具有指针取消引用运算符,或者它必须返回一个指针,该指针可用于选择指针取消引用运算符箭头指向的对象。布鲁斯·埃克尔:思考CPP第一卷:操作员->
额外的功能是为方便起见而提供的,因此您不必打电话
1 | a->->func(); |
您只需执行以下操作:
1 | a->func(); |
这使得operator->不同于其他运算符重载。
您不能重载成员访问
C++ EDCOX1的0×操作符基本上是两个步骤的结合,如果你认为EDCOX1〔6〕相当于EDCOX1〔7〕,这是很清楚的。当EDCOX1(9)是你的类的一个实例时,C++允许你自定义如何处理EDCOX1的8个部分。
EDOCX1·0超载的语义有些奇怪,因为C++允许您返回一个正则指针(它将被用来找到指向的对象),或者返回另一个类的实例,如果该类还提供了EDCOX1×0的操作符。在第二种情况下,从这个新实例继续搜索未引用的对象。
另外,我看不出为什么不能提供const和non-const版本。
当您重载操作符->()(此处不传递任何参数)时,编译器实际执行的操作是递归地调用->直到它返回指向某个类型的实际指针。然后使用正确的成员/方法。
例如,这对于创建封装实际指针的智能指针类很有用。调用重载的operator->执行它的任何操作(例如,为线程安全而锁定),返回内部指针,然后编译器调用->来获取此内部指针。
至于Constness——它已经在评论和其他答案中得到了回答(你可以,也应该,两者都提供)。