C++ 重载成员访问运算符 ->, .*
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8777845/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Overloading member access operators ->, .*
提问by Bingo
I understand most operator overloading, with the exception of the member access operators ->
, .*
, ->*
etc.
据我所知大多数运算符重载,与成员访问运营商外->
,.*
,->*
等。
In particular, what is passed to these operator functions, and what should be returned?
特别是,传递给这些操作符函数的是什么,应该返回什么?
How does the operator function (e.g. operator->(...)
) know what member is being refered to? Can it know? Does it even need to know?
运算符函数(例如operator->(...)
)如何知道引用的是哪个成员?它可以知道吗?它甚至需要知道吗?
Finally, are there any const considerations that need to be taken into account? For example, when overloading something like operator[]
, generally you will need both a const and non-const version. Do member access operators require const and non-const versions?
最后,是否有任何需要考虑的常量因素?例如,当重载诸如 之类的东西时operator[]
,通常您将同时需要常量和非常量版本。成员访问运算符是否需要常量和非常量版本?
回答by Potatoswatter
->
->
This is the only really tricky one. It must be a nonstatic member function, and it takes no arguments. The return value is used to perform the member lookup.
这是唯一真正棘手的。它必须是非静态成员函数,并且不带参数。返回值用于执行成员查找。
If the return value is another object of class type, not a pointer, then the subsequent member lookup is also handled by an operator->
function. This is called the "drill-down behavior." The language chains together the operator->
calls until the last one returns a pointer.
如果返回值是另一个类类型的对象,而不是指针,那么后续的成员查找也由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 << x.a << y->a << z->a; // print "333"
}
->*
->*
This one is only tricky in that there is nothing special about it. The non-overloadedversion requires an object of pointer to class type on the left-hand side and an object of pointer to member type on the right. But when you overload it, you can take any arguments you like and return anything you want. It doesn't even have to be a nonstatic member.
这个只是棘手,因为它没有什么特别之处。的非过负荷版本需要指针的一个目的是在左手侧类类型和指针的一个目的是在右侧构件类型。但是当你重载它时,你可以接受任何你喜欢的参数并返回你想要的任何东西。它甚至不必是非静态成员。
In other words, this one is just a normal binary operator like +
, -
, and /
. See also: Are free operator->* overloads evil?
换句话说,这只是一个普通的二元运算符,如+
, -
, 和/
。另请参阅:free operator->* 重载是否邪恶?
.*
and .
.*
和 .
These cannot be overloaded. There is already a built-in meaning when the left-hand side is of class type. Perhaps it would make a little sense to be able to define them for a pointer on the left-hand side, but the language design committee decided that would be more confusing than useful.
这些不能过载。当左侧是类类型时,已经有一个内置的含义。也许能够为左侧的指针定义它们会有点意义,但语言设计委员会认为这会更令人困惑而不是有用。
Overloading ->
, ->*
, .
, and .*
can only fill in cases where an expression would be undefined, it can never change the meaning of an expression that would be valid with no overloading.
重载->
, ->*
, .
, 和.*
只能填充表达式未定义的情况,它永远不会改变没有重载有效的表达式的含义。
回答by Totonga
Operator -> is special.
运算符 -> 是特殊的。
"It has additional, atypical constraints: It must return an object (or reference to an object) that also has a pointer dereference operator, or it must return a pointer that can be used to select what the pointer dereference operator arrow is pointing at." Bruce Eckel: Thinking CPP Vol-one : operator->
“它有额外的非典型约束:它必须返回一个对象(或对对象的引用),该对象也有一个指针解引用运算符,或者它必须返回一个指针,该指针可用于选择指针解引用运算符箭头所指的对象。 ” Bruce Eckel: Thinking CPP Vol-1 : operator->
The extra functionality is provided for convenience, so you do not have to call
提供额外功能是为了方便,因此您不必调用
a->->func();
You can simply do:
你可以简单地做:
a->func();
That makes operator -> different from the other operator overloads.
这使得 operator -> 不同于其他运算符重载。
回答by 6502
You cannot overload member access .
(i.e. the second part of what ->
does). You can however overload the unary dereferencingoperator *
(i.e. the first part of what ->
does).
你不能重载成员访问.
(即什么的第二部分->
)。但是,您可以重载一元解引用运算符*
(即执行内容的第一部分->
)。
The C++ ->
operator is basically the union of two steps and this is clear if you think that x->y
is equivalent to (*x).y
. C++ allows you to customize what to do with the (*x)
part when x
is an instance of your class.
C++->
运算符基本上是两个步骤的并集,如果您认为这x->y
等效于(*x).y
. C++ 允许您自定义(*x)
当x
是您的类的实例时如何处理该部分。
The semantic for ->
overloading is somewhat strange because C++ allows you either to return a regular pointer (that it will be used to find the pointed object) or to return an instance of another class if this class also provides a ->
operator. When in this second case the search for the dereferenced object continues from this new instance.
->
重载的语义有些奇怪,因为 C++ 允许您返回常规指针(它将用于查找指向的对象)或返回另一个类的实例(如果该类也提供->
运算符)。在第二种情况下,从这个新实例继续搜索解引用的对象。
回答by John Chadwick
The ->
operator doesn't know what member is being pointed to, it just provides an object to perform the actual member access on.
该->
运营商不知道正在指向什么成员,它只是提供了一个对象来执行实际的成员访问。
Additionally, I see no reason why you can't provide const and non-const versions.
此外,我认为没有理由不能提供常量和非常量版本。
回答by Asaf
When you overload operator->() (no arguments are passed here), what the compiler actually does is calling -> recursively until it returns an actual pointer to a type. It then uses the correct member/method.
当您重载 operator->() (此处不传递参数)时,编译器实际执行的是递归调用 -> 直到它返回指向类型的实际指针。然后它使用正确的成员/方法。
This is useful, for example, to create a smart pointer class which encapsulates the actual pointer. The overloaded operator-> is called, does whatever it does (e.g. locking for thread safety), returns the internal pointer and then the compiler calls -> for this internal pointer.
例如,这对于创建封装实际指针的智能指针类很有用。重载的 operator-> 被调用,不管它做什么(例如锁定线程安全),返回内部指针,然后编译器为这个内部指针调用 ->。
As for constness - it's been answered in the comments and other answers (you can, and should, provide both).
至于常量性 - 它已在评论和其他答案中得到解答(您可以并且应该同时提供两者)。