友元函数

4
以下是什么意思(特别是突出部分)?为什么表达式“f(a)”被视为“转换表达式”?
引用:“C++03 $3.4./3-”未限定名称的查找,用作函数调用的后缀表达式在3.4.2中进行描述。[注:为了确定(在解析期间)表达式是否为函数调用的后缀表达式,适用通常的名称查找规则。 3.4.2中的规则对表达式的语法解释没有影响。例如,
typedef int f;
struct A {
friend void f(A &);
operator int();
void g(A a) {
f(a);
}
};

"

f(a)表达式是等同于int(a)的强制类型转换表达式。由于该表达式不是函数调用,因此参数依赖的名称查找(3.4.2)不适用,也无法找到友元函数f。

有什么想法吗?

"
1个回答

1

这意味着解析器首先确定括号前的表达式是一个id还是一个后缀表达式。在这种情况下,它看到f,最近定义的ftypedef int f - 因此它得出结论,该表达式被解释为int(a),并且不执行Koenig查找。

让我们来看看这段代码(您可以在线尝试:http://ideone.com/clone/eRKvP

typedef int f;
namespace x {
  struct A {
    friend void f(A &);
    //friend void f(); // # 1
    operator int();
    void g(A a) {
      //void f();  // # 2
      (void)f(a); // # 3
    }
  };
}

如果您声明了一个与 g 可见的(不相关的)函数 f,它将被解释为函数调用,并且 Koenig 查找将找到正确的重载(参见第 #2 行)。 f 的友元声明在这里不适用,因为:

11.4/1:...友元的名称不在类的作用域内,

然而,令我困扰的是,取消注释 #1 会使编译器(在这种情况下是 gcc)也调用 x::f(A&)。不确定为什么会这样。[在 Comeau Online 编译器中,它按预期工作(例如,#1 不影响第 #3 行)。但最新的 beta 版本编译此代码存在问题。]
附注:正如 litb 所指出的,C++0x 中的规则略有不同:
3.4.2/3: 设 X 为通过未限定查找(3.4.1)生成的查找集合,Y 为通过参数依赖查找生成的查找集合(定义如下)。如果 X 包含:
- 类成员的声明,或 - 不是 using-declaration 的块作用域函数声明,或 - 不是函数或函数模板的声明
则 Y 为空。否则,Y 是与命名空间相关联的声明集合。
粗体项将使编译器仅考虑 void f() 并因参数过多而失败。
这似乎是通过解决 问题218 引入的。

1
取消注释#2将根据C ++ 0x规则禁用koenig查找,尽管(一些编译器即使在C ++ 03模式下也使用这些规则)。因此,它将被编译为函数调用,但作为对本地声明的函数的调用,并将导致错误。 - Johannes Schaub - litb
@Johannes Schaub - litb: 好奇为什么友元函数在类的词法作用域中,却不能在名称查找期间找到。 - Chubsdad
@Chubsdad:那是因为它不在类的范围内。 - jpalecek
1
@Chubsdad,“在类的词法作用域中”是一个措辞不当的规则。它只是意味着函数可以使用未经限定名称找到类成员。这并不意味着/也不应该意味着函数名在类的作用域内。 - Johannes Schaub - litb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接