C++ 中的成员指针运算符 ->* 和 .* 是什么?
是的,我看过这个问题和此常见问题解答,但我仍然不明白什么->*
和.*
在 C++ 中表示。
这些页面提供了有关运算符的信息(例如重载),但似乎没有很好地解释它们是什么。
C++ 中的 ->*
和 .*
是什么,与 ->
和 相比,什么时候需要使用它们>.
?
Yes, I've seen this question and this FAQ, but I still don't understand what ->*
and .*
mean in C++.
Those pages provide information about the operators (such as overloading), but don't seem to explain well what they are.
What are ->*
and .*
in C++, and when do you need to use them as compared to ->
and .
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我希望这个例子能让你明白一些事情
现在,你不能使用
x.somePointer()
或px->somePointer()
因为没有这样的成员在类 X 中。为此,使用了特殊的成员函数指针调用语法...只需自己尝试几个示例,您就会习惯它I hope this example will clear things for you
Now, you can't use
x.somePointer()
, orpx->somePointer()
because there is no such member in class X. For that the special member function pointer call syntax is used... just try a few examples yourself ,you'll get used to it编辑:顺便说一下,虚拟成员函数指针变得很奇怪。
对于成员变量:
成员函数几乎相同。
EDIT: By the way, it gets weird for virtual member functions pointers.
For member variables:
Member functions are almost the same.
简而言之:如果您知道要访问哪个成员,则可以使用
->
和.
。如果您不知道要访问哪个成员,则可以使用->*
和.*
。带有简单侵入式列表的示例
In a nutshell: You use
->
and.
if you know what member you want to access. And you use->*
and.*
if you don't know what member you want to access.Example with a simple intrusive list
当您有一个普通指针(指向对象或基本类型)时,您可以使用
*
来取消引用它:从概念上讲,我们对成员函数指针做同样的事情:
我希望有所帮助解释一下这个概念。我们实际上取消了对成员函数的指针的引用。它比这更复杂一点——它不是指向内存中函数的绝对指针,而只是一个偏移量,应用于上面的
foo
或p
。但从概念上讲,我们正在取消引用它,就像我们取消引用普通对象指针一样。When you have a normal pointer (to an object or a basic type), you would use
*
to dereference it:Conceptually, we're doing the same thing with a member function pointer:
I hope that helps explain the concept. We're effectively dereferencing our pointer to the member function. It's a little more complicated than that -- it's not an absolute pointer to a function in memory, but just an offset, which is applied to
foo
orp
above. But conceptually, we're dereferencing it, much like we would dereference a normal object pointer.C++ 中所谓的成员“指针”在内部更像是偏移量。您需要这样一个成员“指针”和一个对象来引用对象中的成员。但成员“指针”与指针语法一起使用,因此得名。
您可以通过两种方式获得对象:您拥有对该对象的引用,或者您拥有指向该对象的指针。
对于引用,使用
.*
将其与成员指针组合,对于指针,使用->*
将其与成员指针组合。但是,作为一项规则,如果可以避免,就不要使用成员指针。
它们遵循相当反直觉的规则,并且无需任何显式强制转换就可以绕过受保护的访问,也就是说,无意中……
干杯&呵呵,
So called "pointers" to members in C++ are more like offsets, internally. You need both such a member "pointer", and an object, to reference the member in the object. But member "pointers" are used with pointer syntax, hence the name.
There are two ways you can have an object at hand: you have a reference to the object, or you have a pointer to the object.
For the reference, use
.*
to combine it with a member pointer, and for the pointer, use->*
to combine it with a member pointer.However, as a rule, don't use member pointers if you can avoid it.
They obey pretty counter-intuitive rules, and they make it possible to circumvent
protected
access without any explicit casting, that is, inadvertently…Cheers & hth.,
指向成员的指针访问运算符:
.*
和->*
指向成员的指针访问运算符
.*
和->*
分别用于结合对象和指向对象的指针来取消引用指向成员的指针 。此描述适用于指向数据成员的指针和指向成员函数的指针。例如,考虑
Foo
类:如果您声明一个指向
Foo
int 数据成员的成员指针iPtr
code>:您可以初始化此成员指针
iPtr
,使其指向Foo::i
成员:要取消引用该指针,您需要将其与
Foo
对象。现在考虑对象
foo
和指向对象fooPtr
的指针:然后,您可以结合
foo
取消引用iPtr
或fooPtr
:类似地,您可以将
.*
和->*
与指向函数成员的指针一起使用。但请注意,您需要将它们括在括号内,因为函数调用运算符(即()
)的优先级高于.*
和->*
:总而言之:您需要一个对象来取消引用指向成员的指针,以及您使用哪个对象,
.*
或-> ;*
用于取消引用指向的指针成员,取决于这个所需的对象是直接提供还是通过对象指针提供。C++17 — 使用
std::invoke()
代替自 C++17 起,这两个运算符的使用都可以替换为
std::invoke
函数模板。std::invoke
提供了一种统一的方式来取消引用成员指针,无论您是将它们与对象还是对象指针结合使用,并且也无论指向成员的指针对应的是指向数据成员的指针还是指向成员函数的指针:这种统一的语法对应于普通函数调用语法,它可以使编写泛型变得更容易 代码。
Pointer-to-member access operators:
.*
and->*
The pointer-to-member access operators,
.*
and->*
, are for dereferencing a pointer to member in combination with an object and a pointer to object, respectively. This description applies to both pointers to data members and pointers to member functions.For example, consider the class
Foo
:If you declare a member pointer,
iPtr
, to anint
data member ofFoo
:You can initialize this member pointer
iPtr
so that it points to theFoo::i
member:To dereference this pointer, you need to use it in conjunction with a
Foo
object.Consider now the object
foo
and the pointer to objectfooPtr
:Then, you can dereference
iPtr
in combination withfoo
orfooPtr
:Analogously, you can use
.*
and->*
with pointers to function members. Note however that you will need to enclose them between parentheses because the function call operator, i.e.,()
, has higher precedence than both.*
and->*
:To conclude: you need an object to dereference a pointer to a member, and which one you use, either
.*
or->*
for dereferencing the pointer to member, depends on whether this needed object is directly provided or through an object pointer.C++17 — Using
std::invoke()
insteadThe use of both operators can be replaced since C++17 by the
std::invoke
function template.std::invoke
provides a unified way of dereferencing member pointers regardless of whether you use them in combination with an object or an object pointer, and also regardless of whether the pointer to member corresponds to a pointer to data member or pointer to member function:This unified syntax corresponds to the ordinary function call syntax, and it may make it easier to write generic code.
您不能像普通指针一样取消引用指向成员的指针 - 因为成员函数需要 this 指针,并且您必须以某种方式传递它。因此,您需要使用这两个运算符,一侧为对象,另一侧为指针,例如
(object.*ptr)()
。考虑使用
function
和bind
(std::
或boost::
,具体取决于您是否编写 C++ 03 或 0x)而不是那些。You cannot dereference pointer to members as normal pointers — because member functions require
this
pointer, and you have to pass it somehow. So, you need to use these two operators, with object on one side, and pointer on another, e.g.(object.*ptr)()
.Consider using
function
andbind
(std::
orboost::
, depending on whether you write C++03 or 0x) instead of those, though.