为什么不能使用成员指针解引用的范围解析?

问题描述:

考虑一个简单的例子:为什么不能使用成员指针解引用的范围解析?

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(); 
} 

正如你可以看到调用杆件功能时,虽然没有办法明确宣布为成员函数指针的范围可以在foo对象使用范围的分辨率。我同意在使用->*时应该禁止使用该语法,因为操作符有时可能会以意想不到的方式重载,但我无法理解在与.*解引用时防止显式范围解析的原因。

我想禁用指向基类的虚函数的成员指针的虚拟调度。

您声明的变量的名称是foo_member,位于本地块范围内。它是而不是名称Foo::foo_member,即类别Foo没有成员foo_member。相比之下,名称bar处于类别Foo的范围内,并且也在类别FooParent的范围内。

因此,范围解析机制按预期工作:它解决了范围问题。

[更新:]没有机制通过成员函数指针禁用虚拟分派。你可以调用基类子对象的成员函数是这样的:

void (FooParent::*p)() = &FooParent::bar; 
(static_cast<FooParent&>(foo).*p)(); 

但仍呼吁最终得到几乎出动。成员函数的虚拟性被烘焙到成员函数指针值中。你可以做的下一个最好的事情是使用拉姆达:

auto q = [](FooParent & f) { f.FooParent::bar(); }; 
q(foo); 
+0

所以换句话说,原因奠定了范围运算符的优先? –

+0

@ W.F .:完全没有。原因在于范围解析的目的是解决范围问题,但是'foo_member'已经在当前范围内,* not *在'FooParent'范围内。所以如果有的话,原因可能是你对“范围”概念的误解。 –

+0

也许如此...但这个概念限制了直接访问使用指针的虚拟成员函数的可能性... –