如何从私有基类调用静态方法?

Car*_*ton 25 c++ static-methods private-inheritance

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

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;
}
Run Code Online (Sandbox Code Playgroud)

我正在使用MSVC获得编译器错误C2247:

Base :: SomeStaticMethod无法访问,因为Derived1使用private从Base继承.

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

mic*_*srb 22

做这个:

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

  • 比尔盖茨创造了MSVC错误,吉尔贝茨发现它:-)这使我的一天 (18认同)

Mar*_*ica 8

我认为michalsrb的答案更好,但为了完整性:

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

struct Derived2: public Derived1 {
    void SomeInstanceMethod(){
        SomeStaticMethodProxy();
    }
};
Run Code Online (Sandbox Code Playgroud)

也会工作.


PcA*_*cAF 7

其他答案提供了解决问题的方法,我将尝试解释发生了什么.这是因为注入类名.

9.2(N4594)

[...]类名也插入到类本身的范围内; 这被称为注入类名.出于访问检查的目的,inject-class-name 被视为公共成员名称.[...]

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

当您搜索(未命名)名称BaseDerived2,Derived2会搜索第一个范围,然后Derived1搜索范围,然后搜索Base范围,最后找到inject -name-name.然后进行访问控制(因为访问控制发生名称查找之后),它会发现你查找的名称Base是无法访问的成员Derived2.


sky*_*ack 5

如果要通过层次结构调用它,可以执行此操作:

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

struct Derived2: public Derived1 {
    void SomeInstanceMethod(){
        Derived1::SomeStaticMethod();
    }
};
Run Code Online (Sandbox Code Playgroud)

否则,如果你想直接调用它,就像@michalsrb一样提到Base.