2010-09-03 63 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

相关问题