C++ 运算符中的友元==或<&书信电报;我应该什么时候用?

C++ 运算符中的友元==或<&书信电报;我应该什么时候用?,c++,operator-overloading,friend,C++,Operator Overloading,Friend,我觉得我对friend关键字的理解有点漏洞 我有一门课,演示。我在代码中使用它作为两个变量,present1和present2,我将其与=进行比较: if(present1==present2) 下面是我如何定义运算符==(在课堂演示中): 但是,有人告诉我,使用friend并在类外定义它更好: friend bool operator==(presentation&, presentation&); 为什么??这两者之间有什么区别?在第一种情况下,您的函数操作符==是一个非

我觉得我对
friend
关键字的理解有点漏洞

我有一门课,
演示
。我在代码中使用它作为两个变量,
present1
present2
,我将其与
=
进行比较:

if(present1==present2)
下面是我如何定义运算符
==
(在
课堂演示中)

但是,有人告诉我,使用
friend
并在类外定义它更好:

friend bool operator==(presentation&, presentation&);

为什么??这两者之间有什么区别?

在第一种情况下,您的函数
操作符==
是一个非静态类成员。因此,它可以访问私有和受保护的成员变量

在第二种情况下,运算符是外部声明的,因此应该将其定义为类的朋友,以访问这些成员变量。

我喜欢Benoit的答案(但我不能投票赞成),但我想用一个示例来澄清它不会有什么坏处。以下是我的一些货币代码(假设其他所有东西都放对了):


希望能有所帮助。

您的解决方案可行,但它不如
friend
方法强大

当一个类将一个函数或另一个类声明为
friend
时,这意味着friend函数或类可以访问声明类的私有成员和受保护成员。这就好像声明的实体是声明类的成员一样

如果将
operator==()
定义为成员函数,则与
friend
情况一样,成员函数可以完全访问类的成员。但由于它是一个成员函数,因此它指定了一个参数,因为第一个参数暗示为
this
:类型为
presentation
的对象(或其后代)。但是,如果将函数定义为非成员,则可以指定这两个参数,这将使您能够灵活地比较可以使用相同函数转换为
演示文稿的任何两种类型

例如:

class presentation {
    friend bool operator==(const presentation&, const presentation&);
    // ...
};

class Foo : public presentation { /* ... */ };
class Bar : public presentation { /* ... */ };

bool operator==(const presentation& p1, const presentation& p2)
{
    // ...
}

bool func(const Foo& f, const Bar& b, const presentation& p)
{
    return f == b || f == p );
}

最后,这引出了一个问题:“为什么要声明
friend
?”。如果
operator==()
函数不需要访问
presentation
的私有成员,那么最好的解决方案就是使其成为非成员、非友元函数。换句话说,不要授予不需要的函数访问权限。

看看这里的分类副本:

需要指出的是,这个链接问题是关于
的,这两个操作数是不同类型的,因此应该作为朋友来实现


在您的情况下,将其作为类的一部分实现是有意义的。friend技术用于(并且非常有用)使用多种类型的情况,通常不适用于
==
=

只能调用作为方法实现的运算符,如果左侧表达式是类的变量(或对对象的引用),则该运算符是为类定义的

在使用
操作符==
的情况下,您通常对比较同一类的两个对象感兴趣。实现,作为解决您的问题的一种方法

但是,想象一下,您编写了一个字符串类,并且希望有一个运算符在这种情况下工作:

const char *s1 = ...
MyString s2 = ...
if(s1 == s2){...
要使表达式
s1==s2
合法,必须将
opetator==
定义为
MyString
类外部的函数

bool operator==(const char *, const MyString&);
如果操作员需要访问您的类的私有成员,则必须是您的类的朋友


对于处理流的运算符
,您定义了一个运算符,其左操作数是流实例,右操作数是您的类,因此它们不能是您的类的方法。如上例所示,如果需要访问私人成员,则它们必须是您的类和朋友之外的函数。

-1不完整且无法理解对我来说这是完全可以理解的。运算符==应该是类外的友元函数,还是在类内定义的?机器人可以理解这个问题?>\u>“我认为不完整是指他解释为什么它得到了-1。@纳达夫我澄清了你的问题,我想——你能检查一下,确保我得到了正确的答案吗?”?(此外,如果您选择的答案没有回答您的问题,您将希望取消接受该答案。)好的,但我为什么希望它被外部声明?即使声明在类中列为public,它是否仍在外部?第一个也可以吗?都可以。但是在第二种情况下,函数不是类的一部分,即使它可能在同一个头文件中。如果总是让运算符重载外部友元函数(即使没有必要),那么所有运算符重载都将在类外“一起”。@Emile:我认为它归结为功能,正如wilhelmtell所说。如果实现成员
运算符==
(和其他运算符),则在使用它时,会在rhs(而不是lhs)上获得隐式转换。如果将其实现为非成员函数,则会对这两个函数进行隐式转换。样式很好,但有些运算符不能使用非成员函数重载,所以只需要到目前为止。@Steve:说得好。我没有考虑过LHS的隐式转换。
const char *s1 = ...
MyString s2 = ...
if(s1 == s2){...
bool operator==(const char *, const MyString&);