c++11 std::thread 和类友元函数之间的交互



我在理解编译器错误时遇到问题,我试图使用声明为 c++11 std::thread 对象中类的好友的函数。我创建了一个小示例来显示我遇到的问题。基本上,当编译器只看到aafriend函数原型时,当该函数传递到线程对象时,它会抛出一个未定义的符号错误。我正在使用 g++ 4.9.2。

//test.cpp
#include <thread>
class A {
public:
  friend void aa(A &p);
  void av(void);
};
void A::av() {
  std::thread t1(aa,std::ref(*this));
}
void aa(A &p) {
  p;
}
int main() {
  A ai;
  ai.av();
  return 0;
}

编译器命令:

g++ -o test test.cpp -g -O0 -std=c++11 -lpthread

我收到编译器错误:

test.cpp: In member function ‘void A::av()’:
test.cpp:12:18: error: ‘aa’ was not declared in this scope
   std::thread t1(aa,std::ref(*this));

在上面,如果我替换行

std::thread t1(aa,std::ref(*this));

aa(*this);

这编译得很好。或者,如果我在A::av的定义上方添加函数的另一个原型声明,例如:

void aa(A &p);

它使用线程对象声明可以很好地编译。

那么,当我尝试仅使用友元原型声明线程对象时,为什么编译器会反对呢?

我意识到在这个微不足道的例子中,我可以将aa的声明移到A::av的定义之上,但是在实践中我想做一些更复杂的事情,我有一个包含B::av的派生类B,并且aa的定义在逻辑上放在A的实现文件中, 而类A的定义与aa的原型位于类B定义中包含的头文件中。那么这是一个编译器错误,还是我声明某些内容的方式存在问题?

只有类内声明,friend 函数只能通过依赖于参数的查找来获得。要按名称指定它而不调用它,就像在 av 的定义中所做的那样,您需要事先在全局命名空间中声明它,或者将定义移动到前面的位置。

最新更新