为什么不能将范围解析与成员指针取消引用一起使用?

W.F*_*.F. 2 c++ virtual-functions member-pointers dereference language-lawyer

考虑一个简单的例子:

struct FooParent {
   virtual void bar() { }
};

struct Foo: FooParent {
   void bar() { }
};

int main() {
   Foo foo;
   void (Foo::*foo_member)() = &FooParent::bar;
   //(foo.*FooParent::foo_member)();
   foo.FooParent::bar();
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,foo在调用 bar 成员函数时可以在对象上使用范围解析,但无法显式声明成员函数指针的范围。我同意在使用时应禁止该语法,->*因为运算符有时可能会以意想不到的方式重载,但我无法理解在取消引用时阻止显式范围解析背后的原因.*

我正在尝试禁用指向基类的虚函数的成员指针的虚拟分派。

Ker*_* SB 5

您声明的变量的名称是foo_member, 在您的本地块作用域内。它不是一个名称Foo::foo_member,即该类Foo没有成员foo_member。相比之下,名称bar存在于类的范围内Foo,并且也存在于类的范围内FooParent

因此范围解析机制按预期工作:它解析范围。

[更新:] 没有机制可以通过成员函数指针禁用虚拟调度。您可以像这样调用基本子对象的成员函数:

 void (FooParent::*p)() = &FooParent::bar;
 (static_cast<FooParent&>(foo).*p)();
Run Code Online (Sandbox Code Playgroud)

但电话最终仍以虚拟方式发送。成员函数的虚拟性被烘焙到成员函数指针值中。您可以做的下一个最好的事情是使用 lambda:

auto q = [](FooParent & f) { f.FooParent::bar(); };
q(foo);
Run Code Online (Sandbox Code Playgroud)