25

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

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 继承。

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

4

5 回答 5

22

做这个:

struct Derived2: public Derived1 {
    void SomeInstanceMethod(){
        ::Base::SomeStaticMethod();
//      ^^
//      Notice leading :: for accessing root namespace.
    }
};
于 2016-09-06T13:18:50.030 回答
8

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

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

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

也将工作。

于 2016-09-06T13:22:37.860 回答
8

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

9.2 (N4594)

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

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

发生的情况是,当您在 中搜索 (unqalified) nameBaseDerived2,首先搜索范围Derived2,然后Derived1搜索范围,然后搜索Base范围,最后找到注入类名称。然后进行访问控制(因为访问控制发生名称查找之后),它会发现您查找的名称是Base的成员,无法从Derived2.

于 2016-09-06T17:44:31.137 回答
6

如果你想通过层次结构调用它,你可以这样做:

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

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

否则,如果你想直接在Base.

于 2016-09-06T13:20:01.450 回答
4

几种可能性:

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

  2. 通过编写将private函数带入命名空间Derived1using Base::SomeStaticMethod;

于 2016-09-06T13:22:20.910 回答