重载成员访问操作符 – >,。*(C ++)

我理解大多数运算符重载,除了成员访问运算符->.*->*

特别是传递给这些运算符函数的是什么,应该返回什么?

操作符是如何工作的(如operator->(...) )是否知道被引用的成员? 可以知道吗? 它甚至需要知道吗?

最后,是否有需要考虑的常量因素? 例如,当重载类似operator[]东西时,通常你需要一个const和非const的版本。 成员访问操作符是否需要const和非const版本?

->

这是唯一一个非常棘手的问题。 它必须是一个非静态成员函数,并且不需要任何参数。 返回值用于执行成员查找。

如果返回值是类types的另一个对象,而不是指针,则后续成员查找也由operator->函数处理。 这被称为“下钻行为”。 语言把operator->调用链接在一起,直到最后一个返回一个指针。

 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 << xa << y->a << z->a; // print "333" } 

->*

这一个只是棘手的,没有什么特别的。 非重载版本需要一个指向左侧类types指针的对象和右侧成员types指针对象。 但是,当你超载时,你可以采取任何你喜欢的参数,并返回任何你想要的。 它甚至不必是一个非静态成员。

换句话说,这个只是一个普通的二元运算符,像+-/ 。 另见: 免费的运营商 – > *重载邪恶?

.*.

这些不能被重载。 当左边是types时,已经有了一个内置的意思。 也许能够将它们定义为左侧的指针是有道理的,但是语言devise委员会认为这会比有用的更困惑。

重载->->* ,。 , .*只能填充expression式未定义的情况下,它永远不能改变一个expression式的含义,不会超载。

您不能超载成员访问. (即什么->的第二部分)。 但是,你可以重载一元解引用操作符* (即第一部分是什么-> )。

C ++ ->运算符基本上是两个步骤的联合,如果您认为x->y等同于(*x).y ,则这很清楚。 当x是你的类的一个实例时,C ++允许你自定义如何处理(*x)部分。

->重载的语义有点奇怪,因为C ++允许你返回一个常规的指针(它将被用来查找指向的对象),或者如果这个类还提供了一个->操作符,它将返回另一个类的实例。 在第二种情况下,从这个新实例继续search解除引用的对象。

运算符 – >是特殊的。

“它有另外的非典型约束:它必须返回一个对象(或者一个对象的引用),它也有一个指针解引用操作符,或者它必须返回一个指针,可以用来select指针解除引用操作符箭头指向的内容。 “ 布鲁斯·艾克尔(Bruce Eckel):思考CPP Vol-one:运营商 – >

提供额外的function是为了方便,所以你不必打电话

 a->->func(); 

你可以简单地做:

 a->func(); 

这使得运算符 – >与其他运算符重载不同。

->运算符不知道正在指向什么成员,它只是提供一个对象来执行实际的成员访问。

另外,我看不出为什么你不能提供const和非const版本。

当你重载operator – >()(这里没有parameter passing)时,编译器实际上做的是recursion调用 – >直到它返回一个实际的指针types。 然后使用正确的成员/方法。

例如,创build封装实际指针的智能指针类很有用。 重载的operator->被调用,执行任何操作(例如locking线程安全),返回内部指针,然后编译器调用 – >来获取这个内部指针。

至于常量 – 已经在评论和其他答案(你可以,应该提供两者)中得到回答。