为什么可以将友元函数定义放置在类定义中
Why is it possible to place friend function definitions inside of a class definition?
朋友函数不应该在类之外显式定义吗
如果是这样,为什么我可以像任何成员函数一样在类定义中声明友元函数
这是什么
它只适用于某些操作员,如<
操作员,还是适用于所有操作员
如果它适用于所有人,那么这样做有什么缺点吗
应该避免吗?如果是,为什么?
class person
{
public:
bool operator<(int num)
{
return x < num ? true : false ;
}
bool operator<(person& p)
{
return x < p.x ? true : false ;
}
friend bool operator<(int num, person &p)
{
return p.x < num ? true : false ;
}
void setX(int num)
{
x = num;
}
private:
int x;
};
更新:
我并不是要求选择非成员运算符重载或成员运算符重载
我想知道的是:
为什么允许我们在类定义中移动友元方法的定义
这没有违反任何规定吗?如果不是,我们为什么会有朋友呢
我们可以简单地将重载定义为成员函数(我知道成员函数的局限性),但我想说的是,知道这一点,编译器为什么不抱怨我没有在类定义之外定义友元函数,因为它不需要在类定义之内(因为它有类参数)那么,为什么我们可以在类定义中定义友元函数呢?
朋友函数不应该在类之外显式定义吗
友元函数可以在类声明中定义(给定函数体)。这些函数是内联函数,与成员内联函数一样,它们的行为就像是在看到所有类成员之后但在类作用域关闭之前(类声明的末尾)立即定义的一样。在类声明中定义的友元函数在封闭类的作用域中。报价
是否只适用于某些运算符,如<操作员还是适用于所有操作员
最好尽量避免使用友元函数,因为它们与您使用私有类作用域所做的相反,主要是"隐藏"变量。如果你所有的函数都是友元函数,那么拥有私有变量有什么用?
尽管如此,还是有一些常见的运算符经常被声明为友元函数,它们是operator<<
和operator>>
Alexandru Barbarosie的答案是正确的。这意味着我们可以在类中声明一个友元函数,它不是成员函数。这可以很好地组织代码。我认为一个例子可以帮助理解它,以防它不清楚。
#include <iostream>
class A {
public:
A(int val) : val(val) {}
// The following isn't a member function, it is a friend
// function declared inside the class and it has file scope
friend void draw (A &a) {
std::cout << "val: " << a.val << "n";
}
private:
int val;
};
int main() {
A a(5);
draw(a); // outputs "val: 5"
//A::draw(a); // Error: 'draw' is not a member of 'A'
}
如果您要创建一个只包含头的类(这使部署变得更加容易),那么在该类中定义一个友元函数是唯一的方法,因为定义只能出现在一个翻译单元中。包含保护的常规技术不起作用,因为它只处理递归包含之类的事情。
如果您试图编写符合标准的代码,这可能是一件大事。例如,要实现C++规范标准中的RandomNumberEngine命名需求,需要提供operator<<
。这必须是一个friend
,才能将std::ostream&
对象作为其第一个参数(否则它将看起来像一个普通的单参数成员函数运算符重载)。通常,friend
声明将放在单独的.cpp
源文件中的类定义和函数定义中。但是,如果您想要一个只有头的实现,则必须在类中定义它,以避免出现多个定义错误。
因为运算符需要知道所用表达式右侧的详细信息,所以如果它必须访问位于右侧的类型的私有数据,那么它需要是该类的friend
。
如果您试图比较int
和person
,就像您的例子中一样,有两种选择:
- 您提供了从
person
到int
的隐式转换,以便<
可以在不访问任何私有字段的情况下使用它 - 或者将运算符声明为
person
的friend
,以便它可以访问比较右侧的x
正如Jack提到的,在需要访问私有数据的地方需要友元函数。还有另一个目的。这与继承类型有关。只有派生类及其友元才能将指向私有基的指针转换为派生类型。因此,有时您可能希望将某个函数作为派生类的朋友,以允许在函数体内部进行此操作。
- 在命名空间中定义函数还是限定函数
- 为什么在定义函数之前先声明它
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- 这个c++代码是如何在没有定义函数的情况下运行的
- 具有外部"c"和程序集的未定义函数
- 已定义函数时出现 G++ "未定义的引用"错误
- 将自定义函数传递到基抽象类中以延迟执行
- C++使用 rand 定义函数语法
- Arduino:在 loop() 和自定义函数中运行相同的代码时出现问题
- 将具有固定签名的自定义函数名称注入 CRTP
- 使用定义函数模板别名
- 是否可以使用单个定义定义函数的常量和常规版本?(使用模板,自动,decltype等)
- 在内联程序集中定义函数和从 C++ 调用时出现问题
- 在 Metal 着色器代码中,如何定义函数的 in/out 参数变量?
- 声明和定义函数静态会产生"undefined reference to function_name()"
- 朋友定义函数的名称空间是什么
- 介子 对用户定义函数的未定义引用
- 如何使用 "using" 关键字定义函数原型/签名
- 在 C 结构中定义C++函数