2016-09-06 54 views
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; 
} 

我收到編譯器錯誤C2247與MSVC:

基地:: SomeStaticMethod無法訪問因爲Derived1使用private來從Base繼承。

我知道,從Derived2通過繼承我無法訪問,因爲私有符的Base成員,但我仍然應該能夠調用Base一個靜態方法 - 無論BaseDerived2之間的繼承關係。
如何解決歧義並告訴編譯器我只是在調用靜態方法?

回答

22

這樣做:

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

5

,如果你想叫它通過層次你可以這樣做Base

4

幾個可能的原因:

  1. 不要使用繼承結構要調用的方法。使用::Base::SomeStaticMethod()來調用它。可以在全局名稱空間中訪問Base

  2. using Base::SomeStaticMethod;

8

我覺得michalsrb的答案是更能襯托private功能進入Derived1的命名空間,但是出於完整性:

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

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

也會起作用。

7

其他答案提供瞭解決問題的方法,我會嘗試解釋發生了什麼。這是因爲注入了名字

9.2(N4594)

[...]的類名也被插入到類本身的範圍;這被稱爲注入類名稱。 爲了進行訪問檢查,注入類名稱被視爲是公共成員名稱。 [...]即使你輸入Base::SomeStaticMethod()

注意,顯然SomeStaticMethodBase範圍擡頭(這是合格的名稱),但名稱Base本身也有要查找莫名其妙,(在這個例子中爲不合格的名稱(因爲它沒有範圍解析操作後出現))

會發生什麼事是,當你在Derived2搜索(unqalified)名稱Base,第一Derived2範圍進行搜索,然後Derived1小號搜索cope,然後搜索Base範圍,最後找到注入類名稱。然後訪問控制發生(因爲訪問控制發生在名稱查找後),它會發現你擡頭的名字是Base的成員,從Derived2無法訪問。

+0

非常好的分析爲什麼發生這種情況。謝謝。 – Carlton

+0

@Carlton不客氣 – PcAF

+0

輝煌!我有種直覺認爲這樣的事情一定會發生,但是這很清楚*究竟發生了什麼(並解釋了爲什麼把'::'放在前面解決了這個問題)。 –

相關問題