【问题标题】:Why can't one use scope resolution with member pointer dereference?为什么不能将范围解析与成员指针取消引用一起使用?
【发布时间】:2017-01-30 07:33:23
【问题描述】:

考虑一个简单的例子:

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

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

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

【问题讨论】:

    标签: c++ language-lawyer virtual-functions dereference member-pointers


    【解决方案1】:

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

    所以范围解析机制按预期工作:它解析了范围。

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

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

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

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

    【讨论】:

    • 也就是说原因在于范围运算符的优先级?
    • @W.F.:一点也不。原因是作用域解析的目的是解析作用域,但foo_member已经在当前作用域内,不在FooParent的作用域内。因此,如果有的话,原因可能是您对“范围”概念的误解。
    • 哦,等等,现在我明白了你想要做什么:你想要执行直接的、静态的基本函数调用,而不需要虚拟调度。我没有在你原来的问题中明白这一点。让我考虑一下。
    • @WF:我想是反过来的:禁用虚拟调用机制的功能只存在于在类成员访问中使用显式限定的有限形式表达式,但不在指向成员的表达式中。 (如果您认为这是一个非常有用且必要的功能,请随时将其作为语言扩展提出。)
    • @W.F.:如果可以,请记录下这个特定问题在接下来的三年内出现的频率。如果你觉得如果这是一个特性,语言会显着丰富,那么提出这个作为扩展是完全可行的。我们最希望看到一些好的激励案例,即现有解决方案要么差得令人难以忍受,要么核心语言特性可以使代码不易出错且更易于理解。
    猜你喜欢
    • 2011-12-13
    • 2016-08-13
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 2011-02-24
    • 2013-07-19
    相关资源
    最近更新 更多