我试图理解一些导致 PC-Lint 悲伤的 boost 代码,并以一种我认为不合法的 C++ 方式使用friend关键字,但在 VS2008 中编译正常。
我以为我将朋友理解为声明类和函数的一种方式。我认为在这样的函数定义上使用是不合法的。然而,MSDN 页面 http://msdn.microsoft.com/en-us/library/928ecaad(VS.80).aspx非常具体:
友元函数可以在类声明中定义。这些函数是内联函数,与成员内联函数一样,它们的行为就好像它们是在所有类成员都被看到之后但在类作用域关闭之前(类声明的末尾)立即定义的。
在类声明中定义的友元函数不被视为在封闭类的范围内;它们在文件范围内。
所以我知道这是合法的,即使语法不寻常。
我不确定这会给他们带来什么,因为将某事物声明为朋友的正常原因是为其提供更多访问权限。但是,结构体的成员默认都是公共的,因此这里没有这样的好处。
我是否错过了一些深刻的东西,或者这只是一些风格上的提升问题,有人不喜欢在结构体之后放置内联自由函数?
请注意,_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);
}
...
};
update
感谢 Chubsdad 下面的回答,我想我现在明白了,我对正在发生的事情的总结:
- 他们希望这些函数表现得像自由函数,这样你就可以编译
intrusive_ptr_add_ref(somePtrToThreadData)
- 如果它们是在结构体之后定义的自由函数,那么它们在全局命名空间中将是可见的
- 将它们放入带有friend限定符的结构体中意味着它们的作用域位于结构体内部但不是成员函数,因此行为更像静态函数
-
Argument-dependent Lookup http://en.wikipedia.org/wiki/Argument-dependent_lookup means they will be found when used as if they were free functions
- 上述的组合意味着它们的行为就像使用自由函数语法的虚拟函数一样(将显式数据块作为参数而不是对其进行调用)