为什么将朋友函数定义为结构的一部分 - boost thread_data?

时间:2010-09-03 00:57:50

标签: c++ boost boost-thread

我正在尝试理解一些导致PC-Lint悲伤的提升代码并以一种我认为不合法的C ++但在VS2008中编译好的方式使用friend关键字。

我认为我理解朋友是宣告课程和职能的一种方式。我认为在这样的函数定义上使用是不合法的。但是,the MSDN page非常具体:

可以在类声明中定义Friend函数。这些函数是内联函数,就像成员内联函数一样,它们的行为就好像它们是在看到所有类成员之后但在类范围关闭之前(类声明结束)之后立即定义的。

在类声明中定义的Friend函数不在封闭类的范围内考虑;它们在文件范围内。

所以我理解这是合法的,如果有不寻常的语法。

我不确定它是什么,因为宣布朋友的正常理由是为了增加访问权限。但是,结构的成员默认都是公共的,因此这里没有这样的好处。

我是否遗漏了一些深刻的东西,或者这只是一些风格上的提升问题,有人不喜欢在结构体之后放置内联自由函数?

请注意,_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)
  • 即可
  • 如果它们是在struct之后定义的自由函数,它们将在全局命名空间中可见
  • 使用friend限定符将它们放在struct中意味着它们在struct中作用域但不是成员函数,所以表现得更像静态函数
  • Argument-dependent Lookup表示在使用它们时就会发现它们就像是自由函数一样
    • 上述组合意味着它们就像使用自由函数语法的虚函数一样(将显式数据块作为参数而不是在其上调用)

2 个答案:

答案 0 :(得分:5)

在类定义中定义'friend'函数是完全正确的。在这种特殊情况下,由于friend函数采用类型为thread_data_base的参数,因此只有在ADL(参数相关查找)$ 3.4.2的情况下,当从类定义的词法范围外调用时,友元函数定义才可见

查看Herb Sutter的Namespace and the Interface Principle

答案 1 :(得分:1)

  

我是否遗漏了一些深刻的东西,或者这只是一些风格上的提升问题,有人不喜欢在结构体之后放置内联自由函数?

你的猜测似乎是最可能的原因:有人想要声明一个类外的函数,然后将声明保留在类中,因为该函数与类密切相关,因此它们使用诸如此类的神秘语法。为什么他们首先这样做而不是让它成为一个成员函数是任何人的猜测。