operator ==或<<的朋友我应该什么时候使用它?

时间:2010-10-03 14:04:41

标签: c++ operator-overloading friend

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

我有一个班级presentation。我在代码中使用了两个变量present1present2,我将其与==进行比较:

if(present1==present2)

以下是我如何定义运算符==(在class presentation中):

bool operator==(const presentation& p) const;

但是,我被告知使用friend并在课堂外定义它更好:

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

为什么呢?这两者有什么区别?

5 个答案:

答案 0 :(得分:13)

您的解决方案有效,但功能不如friend方法。

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

如果将operator==()定义为成员函数,那么就像使用friend情况一样,成员函数可以完全访问类的成员。但因为它是一个成员函数,所以它指定一个参数,因为第一个参数隐含为this:类型为presentation的对象(或其后代)。但是,如果您将函数定义为非成员,则可以指定这两个参数,这样您就可以灵活地比较使用相同函数转换为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的私有成员,那么确实最好的解决方案是使其成为非成员,非朋友函数。换句话说,不要给出不需要的功能访问权限。

答案 1 :(得分:2)

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

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

答案 2 :(得分:1)

我喜欢Benoit的答案(但我不能投票),但我想一个例子并不会让人明白它。这里有一些我有的Money代码(假设其他一切都是正确的):

// header file
friend bool operator ==(const Money, const Money); // are the two equal?

// source file
bool operator ==(const Money a1, const Money a2)
{
    return a1.all_cents == a2.all_cents;
}

希望有所帮助。

答案 3 :(得分:0)

在这里看一下这个副本:should-operator-be-implemented-as-a-friend-or-as-a-member-function

重要的是要指出,这个关联的问题是关于<<>>应该作为朋友实现,因为这两个操作数是不同的类型。

在你的情况下,将它作为课程的一部分来实现是有意义的。对于使用多种类型且通常不适用于==!=的情况,使用友元技术(并且非常有用)。

答案 4 :(得分:0)

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

如果是operator==,通常您有兴趣比较同一类的两个对象。实现,作为一种方法解决了你的问题。

但是,想象一下,你编写一个字符串类,并且你想要一个运算符,在这种情况下工作:

const char *s1 = ...
MyString s2 = ...
if(s1 == s2){...

要使表达式s1 == s2合法,您必须将opetator==定义为MyString类外部的函数。

bool operator==(const char *, const MyString&);

如果您的班级需要访问私人会员,则必须是您班级的朋友。

如果运算符<<>>适用于流,则定义一个运算符,其左操作数是流实例,右操作数是您的类,因此它们不能是你班级的方法。与上面的示例一样,如果需要访问私有成员,则必须是您的班级和朋友外部的功能。