C++ 命名空间内类的友元函数
关于下面的代码,我有两个问题:C++ 命名空间内类的友元函数,c++,namespaces,friend,C++,Namespaces,Friend,关于下面的代码,我有两个问题: 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; } 名
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;
}
名称空间A{class window;}
空f(A::窗口);
名称空间A
{
类窗口
{
私人:
INTA;
friendvoid::f(窗口);
};
}
空f(A::窗口rhs)
{
std::cout当您将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),您的函数不在名称空间中,因此必须使用::告诉编译器在名称空间之外搜索它
否则,它将只查找命名空间内的函数(这就是它们存在的原因)。Koenig查找在这里不适用,因为window类位于命名空间内
虽然不太确定2),但我打赌它与1相关。1),因为函数f
是在当前名称空间之外声明和定义的。如果您将类的定义移动到与函数相同的名称空间中,无论是全局的还是其他的,您都不需要这样做
2) 在引用函数之前,您始终需要声明函数。您的类使用friend语句引用函数。这里有一个关于什么是友好类的快速解释@Hans抱歉,但这不在我的讨论范围之内question@Hans,请,请,不要链接cplusplus.com-你所说的引用是什么意思?当类不在内部时怎么办e任何NamaSpace都不是这种情况?它需要能够看到函数存在。如果类与函数定义位于同一命名空间中,则可能能够找到它,但声明顺序很重要。这也是为什么函数的定义必须位于类声明之后,因为它使用该类的成员。关于(2),参见CaptainObvlious的答案-有一个微妙的答案。Alexandan在这里不太正确。有时,朋友声明不需要引用以前声明的函数-相反,朋友声明本身算作函数的官方声明,函数可以在以后定义。参见CaptainObvlious的答案。因此,根据在上面的例子中,f(窗口)被视为命名空间a的成员?如果f(窗口)是在其自己的命名空间中定义的,比如命名空间B,会怎么样?f(窗口)会属于命名空间a和命名空间B吗?@VishnuPedireddi No,f(窗口)
将在名称空间A
和B
中声明,但仅在B
中实现。任何试图访问A::f(窗口)的尝试都将导致无法解决的链接器错误。@Vishnupediredidi:由您决定属于哪个链接器。如果您确实访问了f(窗口)在A内部,则它将属于A。如果您确实是这样做的,那么它将属于B::f(窗口)在A中,则它将属于B。因此,问题是,如果您没有将函数限定到它所属的位置,编译器将假定此函数的定义将在定义类的相同范围内。因此,编译器将假定隐式定义,并等待定义的链接时间,您将如果您没有提供链接错误,将出现链接错误。