关于这个代码,我有两个问题:
namespace A { class window; }
void f(A::window);
namespace A
{
class window
{
private:
int a;
friend void ::f(window);
};
}
void f(A::window rhs)
{
std::cout << rhs.a << std::endl;
}
1)为什么我需要通过执行:: f(window)来限定窗口类中的成员函数f是全局的?
2)为什么我需要在这种特殊情况下预先声明函数f(A :: window),而当在类名称空间内没有定义类时,可以在函数声明为朋友之后声明函数
答案 0 :(得分:4)
当您将f()
声明为朋友时,如果尚未出现转发声明,则它实际上已在包含类的封闭命名空间中完成(在本例中为A
)。
所以这......
namespace A
{
class window
{
private:
friend void ::f(window);
};
}
基本上就是这个......
namespace A
{
class window;
void f(window);
class window
{
private:
friend void f(window);
};
}
编辑:以下是C ++标准的一个片段,明确说明了这种情况:
标准7.3.1.2 / 3:
首先在名称空间中声明的每个名称都是该名称空间的成员。 如果非本地类中的朋友声明首先声明一个类或函数,那么友元类或函数是最内层封闭命名空间的成员。非限定查找找不到朋友的名称(3.4.1 )或通过限定查找(3.4.3),直到在该命名空间范围内提供匹配声明(在授予友谊的类定义之前或之后)。
答案 1 :(得分:3)
对于1),您的函数不在命名空间中,因此您必须使用::来告诉编译器在命名空间之外搜索它。
否则,它只会查找命名空间内的函数(这就是它们存在的原因)。 Koenig查找在这里不适用,因为窗口类在命名空间内。
不太确定2)但是我敢打赌它与1)有关。
答案 2 :(得分:1)
1)因为函数f
是在当前命名空间之外声明和定义的。如果您将类的定义移动到与函数相同的名称空间中,无论是全局函数还是其他函数,您都不需要。
2)你总是需要在引用之前声明一个函数。您的类使用friend语句引用该函数。