以下类定义声明了一个朋友函数,该函数为其提供了内联定义。我试图从具有与朋友功能相同名称的类方法中调用朋友功能,但是为了使其起作用,我必须从封闭的名称空间(也需要一个前向声明,类{{1})中访问它。 })。为什么名称查找可用于类C
而不能在类A
中工作?请注意,B
的参数与其朋友函数的参数不同。
B::swap
答案 0 :(得分:4)
这是一个好主意,以下是其失败原因的解释:
编译器使用几个不同的处理阶段来确定您的程序说什么。类B
之所以不能编译,是因为发生的故障发生在friend
被注意到之前。让我解释一下:
当编译器试图找出swap
的含义时,它将进行名称查找。它使用特定的规则来指定外观。这是经过简化的,但是基本上,它首先查找在局部范围内定义的符号,然后在类范围内,然后在封闭(名称空间等)范围内。它找到在类范围内定义的那个,并停止查找。 swap
不使用这两个参数,因此编译失败。
friend
声明允许您使用自由函数访问B
的内部结构,它是您在全局命名空间中声明的swap
函数的附加声明。如果编译器在名称查找中考虑了全局命名空间中的函数,则将考虑这些声明。在类B
中,编译器在进入此阶段之前已经停止了处理。 (而且,friend
声明在以后的阶段中是必需的,因为编译器正在编译与swap
对象一起使用的B
函数的版本,并想弄清楚,“在名为swap
的函数中,它可以接受这两个参数;我可以访问B
的内部信息吗?”)
在A
类中,您使用了另一个名称。直到找到免费的swap
函数,名称查找阶段才会成功。在类C
中,您提供了有关名称查找的特定说明,“嘿,当您查找swap
时,请查看全局命名空间范围,而忽略本地和类中的名称-您可能会发现的范围。”
(注意:@PeteBecker发表评论后,名称查找和friend
的描述已更新。)
答案 1 :(得分:0)
inline
friend
?在这种情况下为什么不static
呢?而不是friend
吗?然后创建一个称为static
的全局变量。对我来说,这是一个糟糕的设计,而不是实际的问题。
方法swap
应该是工作方法,而不是friend
(因为不再需要朋友了):
struct C {
C(int x) : v{ x } {}
void swap(C& other) { std::swap(this->v, other.v); }
private:
int v;
};
void swap(C& x, C& y)
{
x.swap(y);
}