如何从私有库 class 调用静态方法?

How to call a static method from a private base class?

由于第三方库的布局,我有类似下面的代码:

struct Base
{
    static void SomeStaticMethod(){}
};

struct Derived1: private Base {};

struct Derived2: public Derived1 {
    void SomeInstanceMethod(){
        Base::SomeStaticMethod();
    }
};

int main() {
    Derived2 d2;
    d2.SomeInstanceMethod();

    return 0;
}

我在使用 MSVC 时遇到编译器错误 C2247:

Base::SomeStaticMethod not accessible because Derived1 uses private to inherit from Base.

我知道由于私有说明符,我无法通过继承从 Derived2 访问 Base 成员,但我仍然应该能够调用 Base 的静态方法 -不管 BaseDerived2.
之间有任何继承关系 如何解决歧义并告诉编译器我只是在调用静态方法?

这样做:

struct Derived2: public Derived1 {
    void SomeInstanceMethod(){
        ::Base::SomeStaticMethod();
//      ^^
//      Notice leading :: for accessing root namespace.
    }
};

如果想通过层级调用可以这样做:

struct Derived1: private Base {
protected:
    using Base::SomeStaticMethod;
};

struct Derived2: public Derived1 {
    void SomeInstanceMethod(){
        Derived1::SomeStaticMethod();
    }
};

否则,如果您想直接在 Base 上调用它,请按照@michalsrb 提到的方法进行操作。

几种可能性:

  1. 不要使用继承结构来调用方法。使用 ::Base::SomeStaticMethod() 调用它。 Base 可在全局命名空间中访问。

  2. 通过写using Base::SomeStaticMethod;

  3. private函数带入Derived1的命名空间

我认为 michalsrb 的回答更好,但为了完整起见:

namespace
{
    void SomeStaticMethodProxy()
    {
        return Base::SomeStaticMethod();
    }
}

struct Derived2: public Derived1 {
    void SomeInstanceMethod(){
        SomeStaticMethodProxy();
    }
};

也可以。

其他答案提供了解决问题的方法,我将尝试解释发生了什么。是因为injected-class-name.

9.2 (N4594)

[...]The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name. For purposes of access checking, the injected-class-name is treated as if it were a public member name.[...]

请注意,即使您键入 Base::SomeStaticMethod(),显然 SomeStaticMethod 会在 Base 范围内查找(它是限定名称),但名称 Base 本身也必须以某种方式查找,(在这个例子中作为一个 非限定名称 (因为它没有出现在范围解析运算符之后))

发生的情况是,当您在 Derived2 中搜索(未限定的)名称 Base 时,首先搜索 Derived2 范围,然后搜索 Derived1 范围,然后搜索 Base 范围,最后找到 injected-class-name。然后进行访问控制(因为访问控制发生在 名称查找之后)并且它会发现您查找的名称是 Base 的成员,无法从Derived2.