我总是想知道为什么在使用解引用运算符*
方面调用指向函数的指针与调用指向成员函数的指针之间存在风格差异,即
void(*fptr)()=&f; // pointer to function f()
fptr(); // call f() via pointer to function
Foo foo; // instance of Foo
void (Foo::*fptr)()=&Foo::f; // pointer to member function f()
(foo.*fptr)(); // call foo.f() via pointer to member function
在第一部分中,您不使用*
运算符通过函数指针调用f()
,但是必须使用它通过指针调用成员函数{{1 }}。为何如此区别?为什么不使用(foo.*fptr)()
来保持一致性?有没有深刻的理由,或者只是这就是C ++的设计方式?
答案 0 :(得分:2)
我会引用C++ Common Knowledge中的内容。相关章节标题为指向成员函数的指针不是指针。在那里,作者解释了为什么指向成员函数的指针无法实现为函数指针。我将使用它(事实上它们是不同的东西)作为不同语法的理由:
恕我直言,考虑到这些差异可以证明语法差异,尽管历史性的设计选择可能起到了作用。当您获取非静态成员函数的地址时,您没有获得地址;你得到一个指向成员函数的指针。
(...)
与指向数据成员的指针一样,我们需要一个对象或指向对象的指针,以便取消引用指向成员函数的指针。 (...)在指向成员函数的指针的情况下,我们需要对象的地址用作(或计算)函数调用的
this
指针的值,并且可能还有其他原因。请注意,没有指向成员函数的“虚拟”指针。虚拟性是成员函数本身的属性,而不是引用它的指针。
这就是为什么无法实现指向成员函数的指针的一个原因,通常是作为函数的简单指针。指向成员函数的指针的实现必须在其自身内存储有关其所引用的成员函数是虚拟还是非虚拟的信息,有关所在位置的信息适当的虚函数表指针,偏移,可以添加到函数的
this
指针或从函数的{{1}}指针中减去,也可能包含其他信息。指向成员函数的指针通常实现为包含此信息的小型结构,尽管许多其他实现也在使用中。解除引用并调用指向成员函数的指针通常涉及检查存储的信息并有条件地执行适当的虚函数或非虚函数调用序列。
答案 1 :(得分:0)
如果我们只使用foo.fptr,它与我们调用成员函数的方式相同,使编译器变得复杂。实际上,fptr不是foo的成员函数。因此* fptr显示了差异。也许编译可以实现这一点,我认为这就是C ++现在的设计方式。