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

时间:2016-09-06 13:16:34

标签: 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的静态方法 - 无论BaseDerived2之间是否存在任何继承关系 如何解决模糊性并告诉编译器我只是调用静态方法?

5 个答案:

答案 0 :(得分:22)

这样做:

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

答案 1 :(得分:8)

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

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

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

也可以。

答案 2 :(得分:7)

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

9.2(N4594)

  

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

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

当您在Base中搜索(未经验证的)名称Base时,会搜索到第一个Derived2范围,然后搜索Derived2范围,然后{{搜索范围,最后找到 inject-class-name 。然后进行访问控制(因为访问控制发生在名称查找之后),并且它会找到您查找的名称是Derived1的成员,而不是#39} ; t可从Base访问。

答案 3 :(得分:5)

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

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

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

否则,如果您想直接在Base上调用它,请按@michalsrb提及。

答案 4 :(得分:4)

有几种可能性:

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

  2. 通过撰写private

  3. Derived1函数添加到using Base::SomeStaticMethod;的命名空间中