以下两者都在对象T::f
上调用函数t
。
1. t.f();
2. t.T::f();
3. (t.*&T::f)();
我见过第二个使用的是另一个没有的地方。这两者之间有什么区别,在什么情况下应该首选?
感谢。
编辑:抱歉,我忘记了第二个t.T::f()
。我添加了一个。
答案 0 :(得分:4)
调用t.f()
和(t.*&T::f)()
在语义上是相同的,是调用成员函数的“正常”方式。即使t.T::f()
是被覆盖的虚拟函数,调用T::f()
也会调用f()
。
表达式(t.*&T::f)()
通过获取指向成员函数的指针来调用成员函数。此表达式可能具有的唯一潜在影响是它可能会禁止内联函数的某些编译器。使用从&T::f
获得的变量来调用成员函数将是一个自定义点,但是直接调用该函数只是模糊处理并且可能是一种悲观(如果编译器不能进行足够的const传播来检测该地址)不能改变。)
我能想象是某人尝试来禁止t
上的虚拟函数调用。当然,这不起作用,因为指向成员的指针仍将调用正确的虚函数。要禁止虚拟调度,您可以使用t.T::f()
。
您应该更喜欢t.f()
而不是(t.*&T::f)()
。如果您想禁止虚拟调度,则使用t.T::f()
,否则您将使用t.f()
。禁止虚拟分派的主要用途是从覆盖函数中调用函数的基类版本。否则它很少有用。
答案 1 :(得分:1)
第一个是常规的,那是你应该选择的那个。第二个将成员函数指针带到f
,为t
取消引用,然后调用它。
如果额外旅行有实际利益,我不知道。这是调用自由函数时的*&f()
的成员版本。
您稍后添加的t.T::f()
已静默调度,以便f
T
被调用,即使它是虚拟的t
{1}}是T
的派生类,具有自己的实现。它有效地抑制了虚拟呼叫机制。
答案 2 :(得分:-1)
第二个是没有意义的,它只是模糊的代码。不,它不会禁用虚拟调度或内联。在每种情况下,它们都做同样的事情。