本文介绍了为什么将朋友功能定义为结构的一部分-boost thread_data?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解一些引起PC-Lint痛苦的增强代码,并以我认为不是合法的C ++但可以在VS2008中编译OK的方式使用friend关键字.

我认为我把朋友理解为声明类和函数的一种方式.我认为在这样的函数定义上使用是不合法的.但是, MSDN页面非常具体:

可以在类声明中定义

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);
    }
...
};

更新

感谢丘布斯达德在下面的回答,我想我现在已经明白了,我对正在发生的事情的总结:

  • 他们希望它们的行为类似于自由函数,因此您只需编译intrusive_ptr_add_ref(somePtrToThreadData)
  • 如果它们是在struct之后定义的自由函数,则它们将在全局命名空间中可见
  • 使用friend限定符将它们放入结构中意味着它们在结构内部具有作用域,但不是成员函数,因此其行为更像静态函数
  • 依赖于参数的查找表示将其视为原样使用自由功能
    • 以上各项的组合意味着它们的行为就好像它们是使用自由函数语法的虚拟函数一样(将显式数据块作为参数而不是对其进行调用)

解决方案

在类定义中定义"friend"函数是完全可以的.在这种特殊情况下,由于友元函数采用类型为thread_data_base的参数,因此只有在从类定义的词法范围之外调用ADL(取决于参数的查找)$ 3.4.2时,友元函数定义才可见. >

从Herb Sutter中查看命名空间和接口原理

I'm trying to understand some boost code which is causing PC-Lint grief and uses the friend keyword in a way which I didn't think was legal C++ but compiles OK in VS2008.

I thought I understood friend as a way to declare classes and functions. I didn't think it was legal to use on a function definition like this. However, the MSDN page is very specific:

Friend functions can be defined inside class declarations. These functions are inline functions, and like member inline functions they behave as though they were defined immediately after all class members have been seen but before the class scope is closed (the end of the class declaration).

Friend functions defined inside class declarations are not considered in the scope of the enclosing class; they are in file scope.

So I understand that it is legal, if unusual syntax.

I'm not sure what it gets them because the normal reason for declaring something a friend is to give it increased access. However, the members of a struct are all public by default so there's no such benefit here.

Am I missing something profound or is this just some stylistic boost issue where someone doesn't like putting inline free functions after the body of the struct?

Note that _InterlockedIncrement is an intrinsic function on 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);
    }
...
};

update

Thanks to Chubsdad's answer below, I think I understand it now, my summary of what's happening:

  • they want these to behave like free functions, so you can just compile intrusive_ptr_add_ref(somePtrToThreadData)
  • if they were free functions defined after the struct, they would be visible in the global namespace
  • putting them inside the struct with the friend qualifier means they are scoped inside the struct but are not member functions, so behave more like static functions
  • Argument-dependent Lookup means they will be found when used as if they were free functions
    • the combination of the above means they behave as if they were virtual functions using free function syntax (taking an explicit data block as a param rather than invoked on it)

解决方案

It is perfectly fine to define 'friend' functions inside a class definition. In this particular case, since the friend function takes a parameter of type thread_data_base, the friend function definition is visible only in case of ADL (argument dependent lookup) $3.4.2 when called from outside the lexical scope of the class definition

Check out Namespace and the Interface Principle from Herb Sutter

这篇关于为什么将朋友功能定义为结构的一部分-boost thread_data?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-01 03:34