1.当我们初始化一个成员指针或为成员指针赋值时,该指针并没有指向任何数据。成员指针指定了成员而非成员所属的对象,只有当解引用成员指针时,我们才提供对象信息。
2.和普通的函数指针类似,如果成员存在重载的问题,则我们必须显示地声明函数类型以明确指出我们想要使用的是哪个函数。和使用指向数据成员的指针一样,我们使用 .* 或者 ->*运算符作用于指向成员函数的指针。
class test { public: void Add(int){} void Add(long){} void get() {} }; auto pmf = &test::get; // 使用auto的前提是该函数不接受任何实参 void (test::*m_pf)(int) = &test::Add; // 指向int版本的Add void (test::*m_pf1)(int) = test::Add; // 错误,成员函数和指针之间不存在自动转换规则 int main() { test t; (t.*m_pf)(1); // 注意不要忘了* return 0; }
3.使用类型别名或typedef可以让成员指针更容易理解。
class test { public: void Add(int) { } }; typedef void (test::*m_pf)(int); m_pf m = &test::Add; using TestAdd = void (test::*)(int); TestAdd m_testadd = &test::Add; int main() { test t; (t.*m)(1); (t.*m_testadd)(1); return 0; }
4.从指向成员函数的指针获取可调用对象的一种方法是使用标准库模板function。通常情况下,执行成员函数的对象将被传给隐式的this形参。
std::vector<std::string> vec = {"test"}; std::function<bool(const std::string&)> fp = &std::string::empty; bool b = fp(*vec.begin()); // 可以理解为 (*vec.begin()).*fp();
5.mem_fn可以从成员指针生成一个可调用对象,和function不同的是,mem_fn可以根据成员指针的类型推断可调用对象的类型,而无须用户显示地指定。
std::vector<std::string> vec = {"test"}; bool b = std::mem_fn(&std::string::empty)(*vec.begin()); // 正确,使用 .* 调用对象 b = std::mem_fn(&std::string::empty)(vec.begin()); // 正确,使用 ->* 调用对象
6.我们还可以使用binf从成员函数生成一个可调用对象,和function类似的地方是,必须将函数中用于表示执行对象的隐式形参转换成显示的。和mem_fn类似的是,bind生成的可调用对象的第一个实参既可以是指针也可以是引用。
std::vector<std::string> vec = {"test"}; bool b = std::bind(&std::string::empty, std::placeholders::_1)(*vec.begin()); // 正确 b = std::bind(&std::string::empty, std::placeholders::_1)(vec.begin()); // 正确
时间: 2024-11-20 21:20:42