为什么友元运算符<<在某些情况下使用,而在其他情况下不使用
Why is friend operator<< used in some cases and other cases not
说我有一个Complex
类。
我看过
friend ostream& operator<<( ostream& stream, Complex z)
(即朋友函数)
ostream& operator<<( ostream& stream, Complex z)
(即成员函数)
用过,我很难看看何时应该排除朋友,而包括朋友则被认为很重要。
我的理解:成员函数和朋友函数都可以访问Complex
类的私人成员,朋友函数只能在类本身中定义,并且它还可以访问其他类的私人成员(和公共),成员函数没有。
另一个问题,因为ostream& operator<<( ostream& stream, Complex z)
是成员函数,为什么不必在类本身中声明它?我认为所有成员功能都必须在类中声明?
您可以以这两种方式实现操作员超载,如果您不需要用隐式转换为Complex
类型调用它,您可以使用成员函数。但是有缺点,并且通过免费功能提供friend
如果需要访问私人成员,则已成为标准方式。这里最好的参考是Scott Meyer关于免费功能如何改善封装的文章。他对成员与非会员功能的建议明确包括operator <<
:
if (f needs to be virtual) make f a member function of C; else if (f is operator>> or operator<<) { make f a non-member function; if (f needs access to non-public members of C) make f a friend of C; } else if (f needs type conversions on its left-most argument) { make f a non-member function; if (f needs access to non-public members of C) make f a friend of C; } else if (f can be implemented via C's public interface) make f a non-member function; else make f a member function of C;
首先,
由于
ostream& operator<<( ostream& stream, Complex z)
是成员函数,为什么不必在课程中声明它?
因为它不是成员函数。同类内部使用friend
关键字声明的函数也不是。
朋友函数只能在课程本身中定义,并且它还可以访问其他类的私人成员(和公共),成员函数不会
成员功能在访问权利方面绝不是非会员功能。相反的事实 - 例如,成员函数可以访问其班级朋友的私人成员,非会员(甚至friend
)函数都不会。
到您的原始问题:如果需要,则使用friend
,因为它的作用。别无其他。
首先,朋友函数在类本身中未定义。朋友函数的定义与课堂外的任何其他功能一样定义。仅在班级中与 friend 关键字一起发表声明。
我将解释为什么需要以一种易于理解的方式将朋友用于某些操作员超载:
您已经知道,当对象调用其类成员函数时,该函数知道该对象的成员变量值是什么,并且可以自动与这些变量一起使用。您不必在功能中明确包含对象作为参数。
类似地,当您将操作员重载函数定义为成员函数时,该函数已经知道调用该函数的对象。现在让我们考虑您的示例:
friend ostream& operator<<( ostream& stream, Complex z)
考虑如何调用此功能:
Complex z;
cout << z;
编译器看到此表达式时,它会调用非会员函数操作员&lt;&lt;与呼叫
operator<<(cout, z)
如果要将此功能声明为:
ostream& operator<<( ostream& stream, Complex z)
这不是成员函数。成员函数将如下:
ostream& operator<<(ostream& stream)
你为什么要问?因为该函数已经知道有关对象调用此函数的所有信息。因此,它只需要了解COUT。
请记住,只有当左操作数是函数为成员的类的对象时,二进制运算符的运算符过载函数才能成为成员函数。现在考虑如何调用此功能。由于二进制运算符超载要求左操作数是定义函数的类的对象
z << cout
这将导致编译器调用,例如:
z.operator<<(cout)
但是,不使用C 程序员来语句,例如 z&lt;&lt;cout 和这样的语句只会导致混乱。每个人都期望 cout&lt;&lt;z ,但是由于您超载运算符&lt;&lt;作为会员函数,您将必须拨打 z&lt;&lt;cout 。因此,对于此类操作员,非成员的朋友功能是首选。还请记住,某些运算符,例如(),[], ->或任何作业操作员,只能将其重载为成员函数。
希望您了解为什么在某些情况下更好地使用朋友。
关于您的第二个问题:
另一个问题,因为Ostream&amp;运算符&lt;&lt;(ostream&amp; stream,复杂z)是成员函数,为什么不必在类本身中声明它?我认为所有成员功能都必须在班上声明?
所有成员功能都必须在类中声明。您可能会混淆声明和定义。定义可以在课堂内或外部,但是声明必须在课堂内。还有,
朋友函数只能在类本身中定义,并且它还可以访问其他类的私人成员(和公共),而成员函数不具有。
。
这是错误的。同类的朋友功能和非静态成员功能都可以访问该类的私人和公共成员变量。只有静态成员函数无法访问类的非静态成员变量。
1.朋友流&lt;&lt;意味着全球流操作员可以访问复杂的成员。对于以下exmaple,在main()中,Globle Outpream可以直接访问复杂成员。
int main(int ac, char** av)
{
Complex complex;
std::cout << complex;
return 0;
}
2.成员函数&lt;&lt;复杂的意思是复杂本身是流,它可以接受类型是复杂的参数。对于以下示例:
int main(int ac, char** av)
{
Complex comp1, comp2;
comp1 << comp2;
return 0;
}
即使是thogh的使用情况,它是刻板的。
- 在没有太多条件句的情况下,我如何避免被零除
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 在未初始化映射的情况下,将值插入到映射的映射中
- 是默认情况下分配给char数组常量的值
- 为什么我不能在不创建字符串变量的情况下使用函数的字符串输出
- 如何在不产生任何垃圾的情况下获得C中的像素
- 在已经使用Git的情况下减少编译时间
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 如何在没有信号的情况下从C++执行QML插槽
- 如何在不知道向量大小的情况下输入向量内部的向量?
- 为什么在某些情况下不写入此文件?
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 在没有Xcode的情况下在Mac捆绑包中嵌入框架
- UE4-如何在给定4个屏幕坐标的情况下缩放纹理或材质
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 在C++中如何在没有pow的情况下进行基础计算
- 松弛原子与无同步情况下的记忆连贯性
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 我是c ++的新手,你能解释一下在这种情况下的指针吗
- 在没有参数列表的情况下使用模板名称"Event"无效,模板问题