为什么在非Const方法是私有的情况下不调用公共Const方法?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (20)

考虑这个代码:

struct A
{
    void foo() const
    {
        std::cout << "const" << std::endl;
    }

    private:

        void foo()
        {
            std::cout << "non - const" << std::endl;
        }
};

int main()
{
    A a;
    a.foo();
}

编译器错误是:

错误:'void A :: foo()'是private`。

但是,当我删除私人的只是工作。为什么在非const类型的私有方法时不调用公共const方法?

换句话说,为什么重载解析会在访问控制之前出现?这很奇怪。你认为这是一致的吗?我的代码工作,然后我添加一个方法,我的工作代码根本不编译。

提问于
用户回答回答于

当你调用a.foo();,编译器会通过重载解析来找到最好的函数来使用。当它建立它找到的超载集

void foo() const

void foo()

现在,由于a不是const,非const版本是最好的匹配,所以编译器会选择void foo()。然后访问限制已经到位,你会得到一个编译器错误,因为它void foo()是私有的。

请记住,在重载分辨率下,它不是“找到最佳可用功能”。它是'找到最好的功能,并尝试使用它'。如果由于访问限制或被删除而无法访问,则会出现编译器错误。

换句话说,为什么重载分辨率会在访问控制之前出现?

那么,让我们看看:

struct Base
{
    void foo() { std::cout << "Base\n"; }
};

struct Derived : Base
{
    void foo() { std::cout << "Derived\n"; }
};

struct Foo
{
    void foo(Base * b) { b->foo(); }
private:
    void foo(Derived * d) { d->foo(); }
};

int main()
{
    Derived d;
    Foo f;
    f.foo(&d);
}

现在让我们说,我其实并不是想要void foo(Derived * d)私下化。如果访问控制第一个,那么这个程序将编译并运行,Base并将被打印。这可能很难在大型代码库中找到。由于访问控制是在重载解析之后发生的,所以我得到了一个很好的编译器错误,告诉我我希望它调用的函数不能被调用,并且我可以更容易地找到该错误。

用户回答回答于

最终,这归结于标准中的断言,即在执行重载分辨率时不应考虑可访问性。这个断言可以在[over.match]第3条中找到:

...当重载解析成功,并且最佳可行函数在其使用的上下文中不可访问(子句[class.access])时,该程序不合格。

以及同一部分第1条中的注释

[注意:通过重载解析选择的函数不能保证适合上下文。其他限制(如函数的可访问性)可以使其在调用环境中使用不当。 - 结束注释]

至于为什么,我可以想到几个可能的动机:

  1. 它可以防止由于更改重载候选的可访问性而导致的意外行为更改(而是会发生编译错误)。
  2. 它从重载解析过程中消除了上下文依赖(即无论是在课堂内部还是课堂外部,重载解析都会有相同的结果)。

扫码关注云+社区