在Rob McGregor的名为"Using C++"的书中,有以下使用指向成员运算符的示例
class mycls
{
public:
int member;
int *ptr;
};
void main()
{
mycls MyClass;
// Derive a pointer type to the non-pointer class member
int mycls::*member = &mycls::member;
MyClass.ptr = new int;
mycls* pMyClass = &MyClass;
pMyClass->*member = 5;
*MyClass.ptr = 10;
cout << "pMyClass->*member = " << pMyClass->*member << "\n"; // pMyClass->*member = 5
cout << "MyClass.*member = " << MyClass.*member << "\n"; // MyClass.*member = 5
cout << "*MyClass.ptr = " << *MyClass.ptr << "\n"; // *MyClass.ptr = 10
cout << "*pMyClass->ptr = " << *pMyClass->ptr << "\n"; // *pMyClass->ptr = 10
delete MyClass.ptr;
}
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我不明白为什么成员变量mycls::member可能成为(猜测)这行代码之后的指针:
int mycls::*member = &mycls::member;
Run Code Online (Sandbox Code Playgroud)
这是做什么的?
假设你有一个局部变量:
int member;
Run Code Online (Sandbox Code Playgroud)
您可以使用以下命令指向它:
int *ptr = &member;
Run Code Online (Sandbox Code Playgroud)
要获取指向成员语法的指针,我们只需mycls::在适当的位置追加:
int mycls::*member = &mycls::member;
Run Code Online (Sandbox Code Playgroud)
通过一个示例可以更清楚地显示指针如何在类的正确类型的任何成员之间切换:
class C
{
public:
int a;
int b;
};
void main()
{
// make pointer to member, initially pointing to a
int C::*ptrToMember = &C::a;
C x;
C *ptrToObj = &x; // make pointer to object x
ptrToObj->*ptrToMember = 2; // store in a;
ptrToMember = &C::b; // change pointer to b
ptrToObj->*ptrToMember = 3; // store in b;
}
Run Code Online (Sandbox Code Playgroud)
注意a我们在创建类型对象之前如何创建指向成员的指针C.它只是指向成员的指针,而不是指向特定对象成员的指针.在"商店"步骤中,我们必须说明哪个对象以及哪个成员.
更新
OP在评论中询问这是否相同:
int *ptr = &(ptrToObj->a);
Run Code Online (Sandbox Code Playgroud)
不,这不对.这是指向int内存中任何位置的指针.
理解这一点的最简单方法是考虑技术上的含义."指针"是内存中的绝对位置:在哪里查找对象."指向成员的指针"是相对位置,有时称为偏移:在外部对象的存储内找到对象的位置.在内部,它们只是数字.必须将指向成员的指针添加到普通指针以生成另一个指针.
因此,如果您有一个指向对象的指针(一个int对象!),您可以使用它来更改存储在内存中该绝对位置的内容:
*ptr = 123;
Run Code Online (Sandbox Code Playgroud)
但是如果你有一个指向成员的指针,那么它不是一个内存位置.它是一个偏移量,一个要添加到内存位置的量.你不能单独使用它.您必须将其"添加"到对象指针:
ptrToObj->*ptrToMember = 132;
Run Code Online (Sandbox Code Playgroud)
这意味着:转到内存中的位置ptrToObj,然后沿着距离移动ptrToMember.