Meh*_*dad 59 c++ operators pointer-to-member operator-arrow-star
是的,我已经看到了这个问题,而这个FAQ(错误的链接) 这个常见问题,但我还是不明白->*,并.*用C++的意思.
这些页面提供了有关运算符的信息(例如重载),但似乎并不能很好地解释它们是什么.
什么是->*和.*C++,你什么时候需要使用它们->和.?相比?
Arm*_*yan 67
我希望这个例子能为你清楚
//we have a class
struct X
{
void f() {}
void g() {}
};
typedef void (X::*pointer)();
//ok, let's take a pointer and assign f to it.
pointer somePointer = &X::f;
//now I want to call somePointer. But for that, I need an object
X x;
//now I call the member function on x like this
(x.*somePointer)(); //will call x.f()
//now, suppose x is not an object but a pointer to object
X* px = new X;
//I want to call the memfun pointer on px. I use ->*
(px ->* somePointer)(); //will call px->f();
Run Code Online (Sandbox Code Playgroud)
现在,你不能使用x.somePointer(),或者px->somePointer()因为在类X中没有这样的成员.为此使用特殊的成员函数指针调用语法...只是自己尝试一些例子,你会习惯它
spr*_*aff 19
编辑:顺便说一句,虚拟成员函数指针变得奇怪.
对于成员变量:
struct Foo {
int a;
int b;
};
int main ()
{
Foo foo;
int (Foo :: * ptr);
ptr = & Foo :: a;
foo .*ptr = 123; // foo.a = 123;
ptr = & Foo :: b;
foo .*ptr = 234; // foo.b = 234;
}
Run Code Online (Sandbox Code Playgroud)
成员函数几乎相同.
struct Foo {
int a ();
int b ();
};
int main ()
{
Foo foo;
int (Foo :: * ptr) ();
ptr = & Foo :: a;
(foo .*ptr) (); // foo.a ();
ptr = & Foo :: b;
(foo .*ptr) (); // foo.b ();
}
Run Code Online (Sandbox Code Playgroud)
Joh*_*itb 13
简而言之:您使用->并且.如果您知道要访问的成员.并且使用->*和.*,如果你不知道你要访问哪些成员.
带有简单侵入列表的示例
template<typename ItemType>
struct List {
List(ItemType *head, ItemType * ItemType::*nextMemPointer)
:m_head(head), m_nextMemPointer(nextMemPointer) { }
void addHead(ItemType *item) {
(item ->* m_nextMemPointer) = m_head;
m_head = item;
}
private:
ItemType *m_head;
// this stores the member pointer denoting the
// "next" pointer of an item
ItemType * ItemType::*m_nextMemPointer;
};
Run Code Online (Sandbox Code Playgroud)
.*和->*指向成员的指针访问运算符.*和->*分别用于取消引用指向成员的指针与对象和指向对象的指针的组合。此描述适用于指向数据成员的指针和指向成员函数的指针。
例如,考虑一下类Foo:
struct Foo {\n int i;\n void f();\n};\nRun Code Online (Sandbox Code Playgroud)\n如果您声明一个指向的数据成员的成员iPtr指针:intFoo
int Foo::* iPtr;\nRun Code Online (Sandbox Code Playgroud)\n您可以初始化该成员指针iPtr,使其指向Foo::i成员:
iPtr = &Foo::i;\nRun Code Online (Sandbox Code Playgroud)\n要取消引用该指针,您需要将其与对象结合使用Foo。
现在考虑对象foo和指向对象的指针fooPtr:
Foo foo;\nFoo* fooPtr = &foo;\nRun Code Online (Sandbox Code Playgroud)\n然后,您可以iPtr结合使用fooor取消引用fooPtr:
foo.*iPtr = 0;\nfooPtr->*iPtr = 0;\nRun Code Online (Sandbox Code Playgroud)\n类似地,您可以将.*and->*与指向函数成员的指针一起使用。但请注意,您需要将它们括在括号内,因为函数调用运算符(即 )()的优先级高于.*和->*:
void (Foo::*memFuncPtr)() = &Foo::f;\n\n(foo.*memFuncPtr)();\n(fooPtr->*memFuncPtr)();\nRun Code Online (Sandbox Code Playgroud)\n总而言之:您需要一个对象来取消引用指向成员的指针,而使用哪个对象来.*取消->*引用指向成员的指针,取决于是直接提供还是通过对象指针提供所需的对象。
std::invoke()代替自 C++17 起,这两个运算符的使用都可以由std::invoke函数模板替换。提供了一种统一的方式来取消引用成员指针,无论您是否将它们与对象或对象指针std::invoke结合使用,也无论指向成员的指针是否对应于指向数据成员的指针或指向成员函数的指针:
// dereference a pointer to a data member\nstd::invoke(iPtr, foo) = 0; // with an object\nstd::invoke(iPtr, fooPtr) = 0; // with an object pointer\n\n// dereference a pointer to a member function\nstd::invoke(memFuncPtr, foo); // with an object\nstd::invoke(memFuncPtr, fooPtr); // with an object pointer\nRun Code Online (Sandbox Code Playgroud)\n这种统一的语法对应于普通的函数调用语法,可能会让编写通用代码变得更加容易。
\n所谓的C++成员"指针"更像内部的偏移.您需要这样的成员"指针"和对象,以引用对象中的成员.但成员"指针"与指针语法一起使用,因此名称.
有两种方法可以让手头有一个对象:你有一个对象的引用,或者你有一个指向对象的指针.
作为参考,用于.*将其与成员指针组合,对于指针,用于->*将其与成员指针组合.
但是,通常,如果可以避免使用成员指针,请不要使用它.
他们遵守相反的反直觉规则,他们可以在protected没有任何明确的投射的情况下规避访问,也就是说,无意中......
干杯&hth.,
您不能将成员的指针作为普通指针取消引用-因为成员函数需要this指针,并且您必须以某种方式传递它。因此,您需要使用这两个运算符,对象在一侧,指针在另一侧,例如(object.*ptr)()。
不过,请考虑使用functionand bind(std::或boost::,取决于您编写的是C ++ 03还是0x)而不是那些。
当你有一个普通的指针(对象或基本类型)时,你会用*它取消引用它:
int a;
int* b = a;
*b = 5; // we use *b to dereference b, to access the thing it points to
Run Code Online (Sandbox Code Playgroud)
从概念上讲,我们使用成员函数指针执行相同的操作:
class SomeClass
{
public: void func() {}
};
// typedefs make function pointers much easier.
// this is a pointer to a member function of SomeClass, which takes no parameters and returns void
typedef void (SomeClass::*memfunc)();
memfunc myPointer = &SomeClass::func;
SomeClass foo;
// to call func(), we could do:
foo.func();
// to call func() using our pointer, we need to dereference the pointer:
foo.*myPointer();
// this is conceptually just: foo . *myPointer ();
// likewise with a pointer to the object itself:
SomeClass* p = new SomeClass;
// normal call func()
p->func();
// calling func() by dereferencing our pointer:
p->*myPointer();
// this is conceptually just: p -> *myPointer ();
Run Code Online (Sandbox Code Playgroud)
我希望这有助于解释这个概念.我们实际上是取消引用指向成员函数的指针.它有点复杂 - 它不是指向内存中函数的绝对指针,而只是一个偏移量,它应用于foo或p超过.但从概念上讲,我们正在取消引用它,就像我们取消引用普通对象指针一样.
| 归档时间: |
|
| 查看次数: |
17665 次 |
| 最近记录: |