2010-09-03 58 views
3

我想了解一些引起PC-Lint悲傷的boost代碼,並以某種方式使用friend關鍵字,這種方式我並不認爲是合法的C++,但在VS2008中編譯好。爲什麼朋友函數會被定義爲struct - boost thread_data的一部分?

我以爲我理解朋友是一種聲明類和函數的方法。我不認爲用這種函數定義是合法的。但是,the MSDN page是非常具體的:

朋友函數可以在類聲明中定義。這些函數是內聯函數,並且像成員內聯函數一樣,它們的行爲就好像在所有類成員已經被查看之後但在類作用域關閉之前(類聲明結束)一樣。

在類聲明中定義的朋友函數不在封閉類的範圍內考慮;他們在文件範圍內。

所以我明白,這是合法的,如果不尋常的語法。

我不確定它是如何得到它們的,因爲聲明某個朋友的正常原因是爲了增加訪問權限。然而,一個結構的成員默認都是公共的,所以這裏沒有這樣的好處。

我是否缺少深奧的東西,或者這只是一些文體提升問題,有人不喜歡在結構的主體之後放置內聯自由函數?

請注意,_InterlockedIncrement是Win32上的內部函數。

# define BOOST_INTERLOCKED_INCREMENT _InterlockedIncrement 

struct thread_data_base 
{ 
    long count; 
    detail::win32::handle_manager thread_handle; 
    detail::win32::handle_manager interruption_handle; 
    boost::detail::thread_exit_callback_node* thread_exit_callbacks; 
    boost::detail::tss_data_node* tss_data; 
    bool interruption_enabled; 
    unsigned id; 

    thread_data_base(): 
     count(0),thread_handle(detail::win32::invalid_handle_value), 
     interruption_handle(create_anonymous_event(detail::win32::manual_reset_event,detail::win32::event_initially_reset)), 
     thread_exit_callbacks(0),tss_data(0), 
     interruption_enabled(true), 
     id(0) 
    {} 
    virtual ~thread_data_base() 
    {} 

    friend void intrusive_ptr_add_ref(thread_data_base * p) 
    { 
     BOOST_INTERLOCKED_INCREMENT(&p->count); 
    } 
... 
}; 

更新

得益於以下Chubsdad的答案,我想我明白,現在,我發生了什麼事的總結:

  • 他們希望這些表現得像免費功能,讓你可以只編譯intrusive_ptr_add_ref(somePtrToThreadData)
  • 如果它們是在結構體後面定義的自由函數,它們將在全局命名空間中可見
  • 把它們的結構內與朋友預選賽意味着它們的作用域的結構裏面,但不是成員函數,這樣的行爲更像靜態函數
  • Argument-dependent Lookup意味着使用時就好像它們是免費的功能
      他們會被發現
    • 它們的行爲如同它們是使用自由函數的語法(考慮,而不是在其上調用的顯式數據塊作爲PARAM)
+0

很坦率地說它看起來毫無意義,也許'friend'關鍵字強制函數以某種模糊的方式內聯? – 2010-09-03 01:16:27

+0

何時在代碼中註釋時,您需要一個? :) – 2010-09-03 01:18:59

+1

難道這是解決模板類的依賴類型問題的方法嗎? - 可能會查找朋友不在的位置,或許?順便說一句,AFAIK使這個朋友不太可能強迫這個內聯比成爲它的成員 - 但有理由使用「內聯」語法的朋友(例如看看巴頓 - 納克曼的伎倆 - http:// en.wikipedia.org/wiki/Barton-Nackman_trick)。 – Steve314 2010-09-03 01:40:13

回答

5

在類定義中定義「朋友」函數是完全正確的。在這種特殊情況下,由於友元函數採用類型爲thread_data_base的參數,所以只有在ADL(參數相關查找)的情況下,朋友函數定義纔可見$ 3.4.2當從類定義的詞法範圍外調用時

從Herb Sutter退房Namespace and the Interface Principle

1
虛擬官能團的上述裝置的組合

我是否缺少深奧的東西,或者這只是一些文體提升問題,有人不喜歡在結構的主體之後放置內聯自由函數?

你的猜測似乎是最可能的原因:有人想聲明一個超類函數,但由於該函數與類密切相關,所以它們使用了神祕的語法如此。爲什麼他們首先做到了這一點,而不是讓它成爲會員功能,這是任何人的猜測。

+0

使它成爲非成員的原因是'intrusive_ptr'的工作方式; 'intrusive_ptr_add_ref'和'intrusive_ptr_release'是非成員,所以它們可以被你無法修改的類覆蓋。 – 2010-09-03 02:02:45

+0

是的,我沒有問爲什麼它是非會員,只是爲什麼他們覺得有必要使用這種內聯的朋友把戲。順便說一句,我不認爲你應該使用「重載」這個詞來表達虛擬成員函數以外的任何東西,只是爲了避免混淆。 – 2010-09-03 02:10:59

+0

對不起,我的意思是「超載」。 – 2010-09-03 13:32:05

相關問題