运算符 == 或 << 中的朋友我什么时候应该使用它?

发布于 2024-09-25 21:24:04 字数 499 浏览 1 评论 0 原文

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

我有一堂课,演示。我在代码中将它用于两个变量 present1present2,我将它们与 == 进行比较:

if(present1==present2)

以下是我定义运算符 ==(在类演示中):

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

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

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

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

I feel I have a bit of a hole in my understanding of the friend keyword.

I have a class, presentation. I use it in my code for two variables, present1 and present2, which I compare with ==:

if(present1==present2)

Here's how I defined the operator == (in class presentation):

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

However, I was told that using friend and defining it outside of the class is better:

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

Why? What's the difference between the two?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

梦里兽 2024-10-02 21:24:05

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

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

In the first case, your function operator== is a nonstatic class member. It has therefore access to private and protected member variables.

In the second case, the operator is externally declared, therefore it should be defined as a friend of the class to access those member variables.

渡你暖光 2024-10-02 21:24:05

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

对于operator==,通常您有兴趣比较同一类的两个对象。实施作为一种方法可以解决您的问题。

然而,想象一下,您编写了一个字符串类,并且想要一个运算符在这种情况下工作:

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

要使表达式 s1 == s2 合法,您必须定义一个 operator==< /code> 作为 MyString 类的外部函数。

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

如果操作员需要访问您班级的私有成员,那么它必须是您班级的友元。

对于适用于流的运算符 <<>>,您可以定义一个运算符,其左操作数是流实例,右操作数是你的类,所以它们不能是你类的方法。就像上面的例子一样,如果需要访问私有成员,它们必须是你的类和朋友的外部函数。

An operator implemented as a method, can only be called, if the left hand side expression is a variable (or a reference to the object) of the class, the operator is defined for.

In case of an operator== usually you are interested in comparing two objects of the same class. Implementation, as a method solves your problem here.

Imagine however, that you write a string class and you want an operator, to work in this scenario:

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

To make the expression s1 == s2 legal, you have to define an opetator== as a function external to MyString class.

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

If the operator needs an access to the private members if your class, it has to be a friend of your class.

In case of operators << and >>, that work on streams, you define an operator, whose left operand is a stream instance and the right one is your class, so they can't be methods of your class. Like in the example above, they have to be functions external to your class and friends, if the access to private members is required.

芸娘子的小脾气 2024-10-02 21:24:05

我喜欢伯努瓦的回答(但我不能投票赞成),但我认为举一个例子来澄清它不会有什么坏处。这是我的一些货币代码(假设其他所有内容都放置正确):

// 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;
}

希望有所帮助。

I like Benoit's answer (but I can't vote it up), but I figure an example wouldn't hurt to clarify it. Here's some Money code I have (assume everything else is placed right):

// 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;
}

Hope that helps.

苍风燃霜 2024-10-02 21:24:05

在这里看看这个重复的内容: should-operator-be-implemented-as-a-friend-or-as-a-member-function

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

就您而言,将其作为课程的一部分来实现是有意义的。友元技术用于(并且很有用)用于使用多种类型的情况,并且通常不适用于 ==!=

Take a look at this sorta duplicate here: should-operator-be-implemented-as-a-friend-or-as-a-member-function

What is important to point out, this linked question is about << and >> which should be implemented as friends since the two operand are different types.

In your case it makes sense to implement it as part of the class. The friend technique is used (and useful) for cases where more than one type is used and often does not apply to == and !=.

初见终念 2024-10-02 21:24:04

您的解决方案有效,但它不如 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 的私有成员,那么实际上最好的解决方案是使其成为非成员、非友元函数。换句话说,不要授予不需要的函数访问权限。

Your solution works, but it's less powerful than the friend approach.

When a class declares a function or another class as friend it means that friend function or class have access to the declaring class' privates and protected members. It's as if the declared entity was a member of the declaring class.

If you define operator==() as a member function then just like with the friend case the member function has full access to the class' members. But because it is a member function it specifies a single parameter, as the first parameter is implied to be this: an object of type presentation (or a descendent thereof). If, however, you define the function as a non-member then you can specify both parameters, and this will give you the flexibility of comparing any two types that can cast into a presentation using that same function.

For example:

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 );
}

Lastly, this raises the question "why the friend declaration?". If the operator==() function does not need access to private members of presentation then indeed the best solution is to make it a non-member, non-friend function. In other words, don't give a function access privileges which is doesn't need.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文