无论这是否是一个好主意,这里都解释了为什么它失败了:
编译器使用几个不同的处理阶段来确定您的程序所说的内容。上课的原因 B 不编译是因为发生的失败发生在之前 friend 会被注意到。让我解释:
B
friend
当编译器到达它试图找出什么的时候 swap 意思是,它进行名称查找。它使用特定的规则来指定它应该看起来的位置。这是简化的,但基本上它首先查找在本地作用域中定义的符号,然后在类作用域中查找,然后在封闭(名称空间等)作用域中查找。它找到在类范围中定义的那个,并停止查找。那 swap 不采用这两个参数,因此编译失败。
swap
该 friend 声明,允许自由功能访问 B 的内部,作为一个额外的宣言 swap 您在全局命名空间中声明的函数。如果编译器在名称查找中考虑了全局命名空间中的函数,则会考虑这些声明。在班上 B ,编译器在进入此阶段之前已经停止了处理。 (而且 friend 当编译器正在编译一个版本的版本时,在更晚的阶段就需要声明 swap 适用的功能 B 对象,并想弄清楚,“在这个函数中调用 swap 可以采取这两个参数;我可以访问吗? B 的内部?“)
在班上 A ,你使用的是另一个名字。名称查找阶段在找到您的免费后才会成功 swap 功能。在班上 C ,你已经给出了名字查找的具体说明,“嘿,当你抬头时 swap 查看全局命名空间范围,并忽略您可能找到的本地和类范围内的那些。“
A
C
(注意:名称查找和 friend @ PeteBecker评论后更新。)