1

考慮一個簡單的例子:爲什麼不能使用成員指針解引用的範圍解析?

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對象使用範圍的分辨率。我同意在使用->*時應該禁止使用該語法,因爲操作符有時可能會以意想不到的方式重載,但我無法理解在與.*解引用時防止顯式範圍解析的原因。

我想禁用指向基類的虛函數的成員指針的虛擬調度。

回答

4

您聲明的變量的名稱是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

也許如此...但這個概念限制了直接訪問使用指針的虛擬成員函數的可能性... –

相關問題