2013-02-27 64 views
1

的提前聲明我有以下的命名空間和類層次結構:全球友元函數

namespace Ns1 { 
    class Outer { 
    private: 
      class Inner { 
      }; 
      QSet<Inner> set; 
    }; 
} 

現在我需要聲明一個全局函數:

uint qHash(Ns1::Outer::Inner const& el); 
bool operator==(Ns1::Outer::Inner const& el1, 
       Ns1::Outer::Inner const& el); 

因此函數必須是一個朋友到外和內在。 的問題,並表明該功能是在全球範圍內:

friend uint qHash(Ns1::Outer::Inner const& el); 
friend operator==(Ns1::Outer::Inner const& el1, 
       Ns1::Outer::Inner const& el); 

我不能處理這種情況的前置聲明。任何解決方案

+4

爲什麼這個功能需要是一個「全局」功能?我認爲問題本身就在這裏。如果它可以接受的參數是'Ns1 :: Outer :: Inner',那麼在命名空間'Ns1'之外我沒有看到任何要點。鑑於'Inner'是'private'到'Outer',我也沒有看到任何使它成爲非成員函數的觀點。 – Nawaz 2013-02-27 14:58:40

+0

Plz。問題是我說的問題。不要讓你個人的假設。如果存在,請給出解決方案。 – user14416 2013-02-27 15:00:42

+0

如果'Inner'是私有的,你希望如何獲得一個'Inner'對象來將它傳遞給函數?這看起來像一個設計問題 - 就像'friend'的許多用法一樣。不,你不需要'f'成爲'Inner'的朋友 - 除非它使用私有/受保護的方法。 – 2013-02-27 15:01:03

回答

2

編輯:

你是對的!你已經找到了這種語言無法處理的特殊情況(因爲friend船隻聲明只適用於之前聲明的函數,或者適用於最內層的名稱空間)。不幸的是,這意味着你將不得不稍微重構你的代碼,因爲你想做的事情不能完全按照這種方式完成。

最簡單的方法是在Ns1命名空間中定義這兩個函數,然後在using中定義它們到全局命名空間中。除了嵌套命名空間中有兩個額外的函數之外,這基本上與您想要的效果基本相同。

你的其他選擇涉及到從根本上解決問題:爲什麼你的類對象的公共接口不能提供足夠的能力以至於需要友誼?例如,如果您打算在全局範圍內傳遞Inner對象,爲什麼InnerOuter內保密?

爲什麼散列函數和比較函數需要訪問Inner的內部狀態? Inner爲什麼不提供一個公共的比較界面,然後由操作員使用?

+1

實際上這並不能解決它,因爲顯然如果你使用::來限定它們的功能,就必須聲明這些函數。而且你不能轉發他們,因爲他們的簽名需要Outer的完整定義。看起來像一個語言缺陷。 – user1610015 2013-02-27 16:26:52

+0

是的,這個答案不能解決問題。 – user14416 2013-02-27 16:29:00