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;
}
我正在使用MSVC获得编译器错误C2247:
Base :: SomeStaticMethod无法访问,因为Derived1使用private从Base继承.
我知道我不能访问Base从成员Derived2通过继承,因为私人符,但我仍然应该能够调用静态方法Base-无论之间的继承关系Base和Derived2.
如何解决歧义并告诉编译器我只是调用静态方法?
mic*_*srb 22
做这个:
struct Derived2: public Derived1 {
    void SomeInstanceMethod(){
        ::Base::SomeStaticMethod();
//      ^^
//      Notice leading :: for accessing root namespace.
    }
};
我认为michalsrb的答案更好,但为了完整性:
namespace
{
    void SomeStaticMethodProxy()
    {
        return Base::SomeStaticMethod();
    }
}
struct Derived2: public Derived1 {
    void SomeInstanceMethod(){
        SomeStaticMethodProxy();
    }
};
也会工作.
其他答案提供了解决问题的方法,我将尝试解释发生了什么.这是因为注入类名.
9.2(N4594)
[...]类名也插入到类本身的范围内; 这被称为注入类名.出于访问检查的目的,inject-class-name 被视为公共成员名称.[...]
请注意,即使您键入Base::SomeStaticMethod(),显然SomeStaticMethod也会在Base范围内查找(它是限定名称),但名称Base本身也必须以某种方式查找,(在此示例中为非限定名称(因为它不会在范围解析运算符后出现))  
当您搜索(未命名)名称Base时Derived2,Derived2会搜索第一个范围,然后Derived1搜索范围,然后搜索Base范围,最后找到inject -name-name.然后进行访问控制(因为访问控制发生在名称查找之后),它会发现你查找的名称Base是无法访问的成员Derived2.
如果要通过层次结构调用它,可以执行此操作:
struct Derived1: private Base {
protected:
    using Base::SomeStaticMethod;
};
struct Derived2: public Derived1 {
    void SomeInstanceMethod(){
        Derived1::SomeStaticMethod();
    }
};
否则,如果你想直接调用它,就像@michalsrb一样提到Base.