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

时间:2015-04-07 18:44:45

标签: c++ c++11 friend stdthread

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

aa

编译器命令:

//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的定义之上,但是在实践中我想做一些更复杂的事情,我有一个派生类{{1}包含A::avB的定义在逻辑上放在B::av的实现文件中,而类aa的定义则包含A的原型位于类A定义中包含的头文件中。那么这是一个编译器错误,还是我已经宣布某种东西的问题?

1 个答案:

答案 0 :(得分:5)

只有一个类内声明,友元函数只能通过参数依赖查找获得。要按名称指定它而不调用它,就像在av的定义中那样,您需要事先在全局命名空间中声明它,或者将定义移动到更早的点。