看看下面的例子:
A.H:
class A {
protected:
template<class T>
friend void b();
};
b.h:
template<class T>
void b() {}
main.cxx:
#include "a.h"
int main()
{
b<double>();
}
请注意,我忘了包含&#34; b.h&#34;在主文件中。不幸的是,编译器在A类中获取了友元声明并编译了main函数而没有抱怨。我留下了一个神秘的链接错误,这是令人惊讶的,因为实例化应该发生在main.cxx中:
[joel@fedora-joel friend]$ g++ main.cxx
/tmp/ccfpaeHw.o: In function `main':
main.cxx:(.text+0x5): undefined reference to `void b<double>()'
collect2: error: ld returned 1 exit status
我的问题是:编译器为什么允许这样做?有没有办法对付它?
答案 0 :(得分:4)
ISO / IEC 14882:2003,§11.4,第3段说明了这一点:
首先在朋友声明中声明的函数具有外部链接(3.5)。否则,该函数将保留其先前的链接(7.1.1)。
因此,朋友声明兼作函数声明。这允许main
调用该函数,因此没有编译器错误。
发生链接器错误,因为声明没有匹配的函数定义。
我没有办法避免这种行为(因为标准规定了它)。这也是有道理的,因为无论如何都需要函数声明来使友元声明有效(否则你有一个未声明函数的朋友声明)。因此,如果友元声明不会作为函数声明加倍,则必须以其他方式提供函数声明(通过包含适当的标题,例如。)。