我最近一直在学习如何使用std::mem_fn
库设施。在C ++ Primer第5版中,他们举例说明了std::mem_fn
的使用情况,以下代码段svec
是vector
的{{1}}:
string
注意:在上面的代码段中没有使用 - > *
虽然我了解使用情况auto f = mem_fn(&string::empty); // f takes a string or a string*
f(*svec.begin()); // ok: passes a string object; f uses .* to call empty
f(&svec[0]); // ok: passes a pointer to string; f uses .-> to call empty
和.*
。我对此并不清楚。
所以,我的问题是->*
,.*
,->*
做了什么?
答案 0 :(得分:3)
您有一个对象o
和一个指向其成员m
的指针。操作符.*
允许您访问对象的尖头成员:
o.*m
您有一个指向对象p
的指针和指向其成员m
的指针。运算符->*
允许您访问指向对象的尖头成员:
p->*m
我担心运营商.->
不存在。
答案 1 :(得分:1)
.*
和->*
运算符被称为成员访问运算符的指针,并且它们的名称表明它们允许您在给定指向该类的适当指针的情况下访问对象的数据或函数成员构件。
struct foo
{
int a;
float b;
void bar() { std::cout << "bar\n"; }
};
int main()
{
int foo::* ptra = &foo::a;
float foo::* ptrb = &foo::b;
void (foo::* ptrbar)() = &foo::bar;
foo f;
foo * fptr = &f;
f.*ptra = 5;
f.*ptrb = 10.0f;
(f.*ptrbar)();
fptr->*ptra = 6;
fptr->*ptrb = 11.0f;
(fptr->*ptrbar)();
return 0;
}
答案 2 :(得分:1)
运算符.*
和->*
调用成员函数(BTW对C ++中的.->
没有意义 - 它是语法错误)。
这些是二元运算符。左操作数是一个对象(用于.*
)或指向对象的指针(用于->*
),右操作数是指向成员的指针(可以是成员字段或成员函数) )。应用此运算符的结果是能够使用成员字段或方法。
从历史的角度来看,这些运营商也许是有道理的。假设您使用常规C指针指向函数:
typedef int (*CalcResult)(int x, int y, int z);
CalcResult my_calc_func = &CalcResult42;
...
int result = my_calc_func(11, 22, 33);
如果您决定&#34;重写&#34;该怎么办?你的程序是面向对象的吗?您的计算函数将是类中的方法。要创建指针,需要一个新类型,一个指向成员函数的指针:
typedef int (MyClass::*CalcResult)(int x, int y, int z);
CalcResult my_calc_func = &MyClass::CalcResult42;
...
MyClass my_object;
int result = (my_object.*my_calc_func)(11, 22, 33);
当我试图记住这个.*
运算符的语法时,我总是使用这个类比 - 这有帮助,因为常规的指针到函数语法更少复杂并且更频繁地使用。
请注意括号:
int result = (my_object.*my_calc_func)(11, 22, 33);
使用此.*
运算符时几乎总是需要它们,因为它的优先级很低。尽管my_object .* (my_calc_func(11, 22, 33))
没有意义,但如果没有括号,编译器会尝试理解它。
->*
运算符的工作方式基本相同。如果要通过指针给出应用方法的对象,则使用它:
typedef int (*MyClass::CalcResult)(int x, int y, int z);
CalcResult my_calc_func = &MyClass::CalcResult42;
...
MyClass my_object1, my_object2;
MyClass* my_object = flag ? &my_object1 : &my_object2;
int result = (my_object->*my_calc_func)(11, 22, 33);