class 体内的 C++ 友元运算符定义用作函数声明?
C++ friend operator definition inside class body serves as function declaration?
我是阅读 C++ Primer 一书的新手。它说:
A friend declaration only specifies access. It is not a general declaration of the function. If we want users of the class to be able to call a friend function, then we must also declare the function separately from the friend declaration. To make a friend visible to users of the class, we usually declare each friend (outside the class) in the same header as the class itself.
但我刚刚发现 不是 在 class 体内定义的友元运算符函数的情况。在以下代码中,找不到 f
但找到了 operator+
:
struct X
{
friend void f()
{
// friend functions can be defined in the class
// this does NOT serve as a declaration, even though this is already a definition
// to use this function, another declaration is REQUIRED
}
friend X operator+(const X & x1, const X & x2)
{
// this stuff serves as declaration somehow
return {x1.v + x2.v};
}
void foo()
{
f(); // ERROR: no declaration for f
X tmp = X {1} + X {2}; // CORRECT
}
int v;
};
有人能告诉我是什么造成了这种差异吗?
我使用的是 g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0,作为参考。
我在 Whosebug 上搜索了很多涉及朋友声明和定义的问题,但没有找到答案。对不起,如果这个问题重复了。
即使我们在 class 中定义函数,我们仍然必须在 class 本身之外提供声明以使该函数可见。即使我们只从授予 class 的友谊成员中调用朋友,声明也必须存在。这意味着在您的示例中,您应该转发声明函数f
,如下所示:
//forward declare f
void f();
struct X
{
//no ADL here since this function f has no parameters of type X. So we also need to declare this outside struct X which we did by providing forward declaration
friend void f()
{
}
void foo()
{
f(); // WORKS NOW because of the forward declaration
X tmp = X {1} + X {2}; //operator+ found using ADL
}
//other members here
};
程序输出可见here.
调用 operator+
的原因是因为 ADL
代表 参数依赖查找 。特别是,operator+
可以使用 ADL 找到,因为它具有 X
类型的参数。所以在这种情况下,您不需要在 struct X
.
之外显式声明 operator+
区别在于operator+
以X
为参数,然后是ADL could find名称; f
一无所获,ADL也无能为力
(强调我的)
Names introduced by friend declarations within a non-local class X become members of the innermost enclosing namespace of X, but they do not become visible to ordinary name lookup (neither unqualified nor qualified) unless a matching declaration is provided at namespace scope, either before or after the class definition. Such name may be found through ADL which considers both namespaces and classes.
我是阅读 C++ Primer 一书的新手。它说:
A friend declaration only specifies access. It is not a general declaration of the function. If we want users of the class to be able to call a friend function, then we must also declare the function separately from the friend declaration. To make a friend visible to users of the class, we usually declare each friend (outside the class) in the same header as the class itself.
但我刚刚发现 不是 在 class 体内定义的友元运算符函数的情况。在以下代码中,找不到 f
但找到了 operator+
:
struct X
{
friend void f()
{
// friend functions can be defined in the class
// this does NOT serve as a declaration, even though this is already a definition
// to use this function, another declaration is REQUIRED
}
friend X operator+(const X & x1, const X & x2)
{
// this stuff serves as declaration somehow
return {x1.v + x2.v};
}
void foo()
{
f(); // ERROR: no declaration for f
X tmp = X {1} + X {2}; // CORRECT
}
int v;
};
有人能告诉我是什么造成了这种差异吗? 我使用的是 g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0,作为参考。 我在 Whosebug 上搜索了很多涉及朋友声明和定义的问题,但没有找到答案。对不起,如果这个问题重复了。
即使我们在 class 中定义函数,我们仍然必须在 class 本身之外提供声明以使该函数可见。即使我们只从授予 class 的友谊成员中调用朋友,声明也必须存在。这意味着在您的示例中,您应该转发声明函数f
,如下所示:
//forward declare f
void f();
struct X
{
//no ADL here since this function f has no parameters of type X. So we also need to declare this outside struct X which we did by providing forward declaration
friend void f()
{
}
void foo()
{
f(); // WORKS NOW because of the forward declaration
X tmp = X {1} + X {2}; //operator+ found using ADL
}
//other members here
};
程序输出可见here.
调用 operator+
的原因是因为 ADL
代表 参数依赖查找 。特别是,operator+
可以使用 ADL 找到,因为它具有 X
类型的参数。所以在这种情况下,您不需要在 struct X
.
operator+
区别在于operator+
以X
为参数,然后是ADL could find名称; f
一无所获,ADL也无能为力
(强调我的)
Names introduced by friend declarations within a non-local class X become members of the innermost enclosing namespace of X, but they do not become visible to ordinary name lookup (neither unqualified nor qualified) unless a matching declaration is provided at namespace scope, either before or after the class definition. Such name may be found through ADL which considers both namespaces and classes.