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

问题描述:

由于第三方库的布局,我有类似下面的代码:如何从私有基类调用静态方法?

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; 
} 

我收到编译器错误C2247与MSVC:

基地:: SomeStaticMethod无法访问因为Derived1使用private来从Base继承。

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

这样做:

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

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

否则,如果你想直接把它做提到@michalsrb:

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

这不起作用(同样的错误C2247)。如果这是相关的,我正在使用MSVC 2013。 – Carlton

+1

你确定吗?它*应该*工作?你写了领先的'::'吗? – Bathsheba

+0

积极。我复制/粘贴你的代码并清理/重建我的项目。 – Carlton

,如果你想叫它通过层次你可以这样做Base

几个可能的原因:

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

  2. using Base::SomeStaticMethod;

我觉得michalsrb的答案是更能衬托private功能进入Derived1的命名空间,但是出于完整性:

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

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

也会起作用。

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

9.2(N4594)

[...]的类名也被插入到类本身的范围;这被称为注入类名称。 为了进行访问检查,注入类名称被视为是公共成员名称。 [...]即使你输入Base::SomeStaticMethod()

注意,显然SomeStaticMethodBase范围抬头(这是合格的名称),但名称Base本身也有要查找莫名其妙,(在这个例子中为不合格的名称(因为它没有范围解析操作后出现))

会发生什么事是,当你在Derived2搜索(unqalified)名称Base,第一Derived2范围进行搜索,然后Derived1小号搜索cope,然后搜索Base范围,最后找到注入类名称。然后访问控制发生(因为访问控制发生在名称查找后),它会发现你抬头的名字是Base的成员,从Derived2无法访问。

+0

非常好的分析为什么发生这种情况。谢谢。 – Carlton

+0

@Carlton不客气 – PcAF

+0

辉煌!我有种直觉认为这样的事情一定会发生,但是这很清楚*究竟发生了什么(并解释了为什么把'::'放在前面解决了这个问题)。 –