【问题标题】:Why doesn't private inheritance resolve ambiguity for static functions ? (tested in MSVC)为什么私有继承不能解决静态函数的歧义? (在 MSVC 中测试)
【发布时间】:2014-12-28 18:56:35
【问题描述】:

我想知道为什么对静态函数的调用是模棱两可的,即使两者中的一个显然不可能调用,因为它是私有的。 我希望我可以使用私有/受保护的继承来帮助编译器解决歧义。

它是特定于 MSVC 还是在标准中以某种方式指定?

struct A
{
    static int num() { return 0; }
};

struct B
{
    static int num() { return 1; }
};

struct C : public A, private B
{};

int main()
{
     C::num(); // Ambiguous access of num
}

背景是我正在尝试一种通过继承在许多派生类(C、D、E、F、G)中重用重载行为(A 中的行为)的方法,以某种方式遵守 Don 的规则不要重复自己。

【问题讨论】:

  • 访问检查在之后重载决议完成

标签: c++ static-methods ambiguous-call private-inheritance


【解决方案1】:

是的,它在 C++ 标准第 3.4 节 [basic.lookup] 中指定

只有在名称查找和函数重载解析(如果适用)成功后才考虑访问规则(第 11 条)

名称查找不关心可访问性:它同时找到A::numB::num,因此编译器存在歧义。

您可以使用 :

显式调用 A::num
C::A::num();

如果您明确尝试调用B::num,那么您的编译器确实会发出访问错误:

C::B::num(); // Error

您还可以将基名称显式引入派生类的范围内,这将解决歧义:

struct C : public A, private B
{
    using A::num;    
};

【讨论】:

  • 我明白了。所以我可以明确地解决派生中的歧义,在每个函数的基础上,但是没有办法指定一个基类的所有成员优先于另一个,这是我天真地试图实现的。如果有意义的话,唯一的方法是“垂直”重载?
  • 是的,没错。但一般来说,你应该首先尽量避免名称冲突(当然是指非虚拟成员),这样一开始就不会出现问题。
  • 现实生活中的例子稍微复杂一些:许多派生必须重载A::num,但为了冗长和DRY,它们从另一个基类继承重载。我将使用using 解决方案,因为它不那么冗长。
【解决方案2】:

为了帮助编译器,你可以这样做

 struct C : public A, private B
 {
      using A::num;
 };

【讨论】:

    【解决方案3】:

    在重载解决方案中有意考虑私有成员。

    假设你有

    class C {
    public:
      static void f(int);
      static void g();
    private:
      static void f(long);
    };
    
    void C::g() {
      f(0L); // okay
    }
    void g() {
      f(0L); // error, does not silently call f(int)
    }
    

    在重载解决期间仅使公共成员可用会导致对代码的重新解释非常令人惊讶,其中看起来应该以完全相同的方式工作的代码会默默地调用不同的重载。

    使此类代码成为错误被认为比替代方法更容易。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 2019-12-28
      • 1970-01-01
      • 2018-05-23
      • 2016-09-20
      • 2011-12-26
      相关资源
      最近更新 更多