I see in a header that I didn't write myself the following:
我在标题中看到我没有写下以下内容:
class MonitorObjectString: public MonitorObject {
// some other declarations
friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) { return(lhs.fVal==rhs.fVal); }
I can't understand why this method is declared as friend. I thought it would make sense if the function is defined in another place and needs to access the internal member of the class, but this is not the case here as it is inline and doesn't even need to have access to the members.
我无法理解为什么这个方法被声明为朋友。我认为如果函数在另一个地方定义并且需要访问类的内部成员是有意义的,但这不是这里的情况,因为它是内联的,甚至不需要访问成员。
What do you think? Is the "friend" useless?
你怎么看?这位“朋友”没用吗?
3 个解决方案
#1
34
friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) {
return(lhs.fVal==rhs.fVal);
}
is called friend definition
. It will define the function as a non-member function of the namespace surrounding the class it appears in. Actually, the inline there is redundant: It's implicitly declared inline if it's a friend definition. Some pros and cons of it:
被称为朋友定义。它将函数定义为它所出现的类周围的命名空间的非成员函数。实际上,内联存在冗余:如果它是朋友定义,则隐式声明内联。它的一些优点和缺点:
- It makes the operator not visible to normal lookup. The only way you can call it is using argument dependent look-up. This will keep the namespace free of lots of operator declarations visible normally. Note that this will also disable the ability of calling it using implicit conversions to MonitorObjectString (because if both argument types do not match at the time of looking for candidates to be called, argument dependent look-up won't find the function).
- The lookup for names starts in the scope of the class the friend definition appears in. This means that no long type-names or other names need to be written out. Just refer them as you would in a normal member function of the class.
- As it is a friend, the function sees the internals of
MonitorObjectString
. But that's neither good nor bad. It depends on the situation. For example if there are functionsgetFVal()
making the function friend is pretty pointless. Could usegetFVal
as-well then.
它使操作员对正常查找不可见。您可以调用它的唯一方法是使用参数相关的查找。这将使命名空间无法正常显示许多操作员声明。请注意,这也将禁用使用对MonitorObjectString的隐式转换来调用它的能力(因为如果在查找候选者被调用时两个参数类型都不匹配,则参数相关的查找将找不到该函数)。
名称的查找从朋友定义出现的类的范围开始。这意味着不需要写出长的类型名称或其他名称。只需像在类的普通成员函数中那样引用它们。
由于它是朋友,该函数可以看到MonitorObjectString的内部。但这既不好也不坏。这取决于实际情况。例如,如果有函数getFVal()使得函数朋友是毫无意义的。那么可以使用getFVal。
I used to like this friend definition style of operators, because they have direct access to class members, and appear within the class definition - so I could have "everything with one sight". Recently, however, I came to the conclusion that it's not always a good idea. If you can (and you should) implement the operator purely using public member functions of the class, you should make it a non-friend (and non-member) operator, defined in the same namespace of the class. It makes sure that if you change some implementation - but keep the interface of the class the same - the operator will still work and you have less cascading changes, because you know it can't access implementation details.
我曾经喜欢这种朋友定义的运算符风格,因为它们可以直接访问类成员,并且出现在类定义中 - 所以我可以拥有“一见钟情”。然而,最近我得出的结论是,这并不总是一个好主意。如果你可以(并且你应该)纯粹使用类的公共成员函数来实现运算符,那么你应该使它成为非朋友(和非成员)运算符,在类的同一名称空间中定义。它确保如果您更改某些实现 - 但保持类的接口相同 - 操作员仍然可以工作,并且您的级联更改较少,因为您知道它无法访问实现细节。
However, I prefer this style over writing member operators, because operator functions at namespace scope have the added features of being symmetric with their arguments: They don't treat the left side special, because both sides are just normal arguments and not object arguments that are bound to *this
. If either the left or the right side is of the type of your class, the other side can be implicitly converted - regardless of whether it's left or right. For functions that are also defined without the friend definition syntax (traditionally, at namespace scope), you will have the feature of selectively including headers that make those operators available or not.
但是,我更喜欢这种风格而不是编写成员运算符,因为命名空间范围内的运算符函数具有与其参数对称的附加功能:它们不会将左侧特殊处理,因为双方都只是普通参数而不是对象参数必须*这个。如果左侧或右侧属于您的类的类型,则可以隐式转换另一侧 - 无论是左侧还是右侧。对于也没有使用友元定义语法定义的函数(传统上,在命名空间范围内),您将具有选择性地包含使这些运算符可用或不可用的标头的功能。
#2
7
They aren't mutually exclusive. "friend" means the non-member function can access the private members of the class. "inline" means there is no function call invocation, the body of the function is duplicated (in assembly) at every call site.
它们不是相互排斥的。 “friend”表示非成员函数可以访问该类的私有成员。 “inline”表示没有函数调用调用,函数体在每个调用站点都是重复的(在汇编中)。
#3
7
Grammatically speaking...
The friend
keyword is still needed to tell the compiler that this function is not a member of a class, EDIT: but instead a non-member function that can see the private members of the class.
还需要friend关键字来告诉编译器该函数不是类的成员,EDIT:而是一个非成员函数,可以看到该类的私有成员。
However, this could have been implemented more cleanly like this:
但是,这可以更加干净地实现,如下所示:
/* friend */ inline bool operator ==(const MonitorObjectString& rhs) const
{ return fVal == rhs.fVal; }
(Of course, I'm assuming fVal
is of a suitable type that can be compared without affecting its const-ness.)
(当然,我假设fVal是一种合适的类型,可以在不影响其常数的情况下进行比较。)
#1
34
friend inline bool operator==(MonitorObjectString& lhs, MonitorObjectString& rhs) {
return(lhs.fVal==rhs.fVal);
}
is called friend definition
. It will define the function as a non-member function of the namespace surrounding the class it appears in. Actually, the inline there is redundant: It's implicitly declared inline if it's a friend definition. Some pros and cons of it:
被称为朋友定义。它将函数定义为它所出现的类周围的命名空间的非成员函数。实际上,内联存在冗余:如果它是朋友定义,则隐式声明内联。它的一些优点和缺点:
- It makes the operator not visible to normal lookup. The only way you can call it is using argument dependent look-up. This will keep the namespace free of lots of operator declarations visible normally. Note that this will also disable the ability of calling it using implicit conversions to MonitorObjectString (because if both argument types do not match at the time of looking for candidates to be called, argument dependent look-up won't find the function).
- The lookup for names starts in the scope of the class the friend definition appears in. This means that no long type-names or other names need to be written out. Just refer them as you would in a normal member function of the class.
- As it is a friend, the function sees the internals of
MonitorObjectString
. But that's neither good nor bad. It depends on the situation. For example if there are functionsgetFVal()
making the function friend is pretty pointless. Could usegetFVal
as-well then.
它使操作员对正常查找不可见。您可以调用它的唯一方法是使用参数相关的查找。这将使命名空间无法正常显示许多操作员声明。请注意,这也将禁用使用对MonitorObjectString的隐式转换来调用它的能力(因为如果在查找候选者被调用时两个参数类型都不匹配,则参数相关的查找将找不到该函数)。
名称的查找从朋友定义出现的类的范围开始。这意味着不需要写出长的类型名称或其他名称。只需像在类的普通成员函数中那样引用它们。
由于它是朋友,该函数可以看到MonitorObjectString的内部。但这既不好也不坏。这取决于实际情况。例如,如果有函数getFVal()使得函数朋友是毫无意义的。那么可以使用getFVal。
I used to like this friend definition style of operators, because they have direct access to class members, and appear within the class definition - so I could have "everything with one sight". Recently, however, I came to the conclusion that it's not always a good idea. If you can (and you should) implement the operator purely using public member functions of the class, you should make it a non-friend (and non-member) operator, defined in the same namespace of the class. It makes sure that if you change some implementation - but keep the interface of the class the same - the operator will still work and you have less cascading changes, because you know it can't access implementation details.
我曾经喜欢这种朋友定义的运算符风格,因为它们可以直接访问类成员,并且出现在类定义中 - 所以我可以拥有“一见钟情”。然而,最近我得出的结论是,这并不总是一个好主意。如果你可以(并且你应该)纯粹使用类的公共成员函数来实现运算符,那么你应该使它成为非朋友(和非成员)运算符,在类的同一名称空间中定义。它确保如果您更改某些实现 - 但保持类的接口相同 - 操作员仍然可以工作,并且您的级联更改较少,因为您知道它无法访问实现细节。
However, I prefer this style over writing member operators, because operator functions at namespace scope have the added features of being symmetric with their arguments: They don't treat the left side special, because both sides are just normal arguments and not object arguments that are bound to *this
. If either the left or the right side is of the type of your class, the other side can be implicitly converted - regardless of whether it's left or right. For functions that are also defined without the friend definition syntax (traditionally, at namespace scope), you will have the feature of selectively including headers that make those operators available or not.
但是,我更喜欢这种风格而不是编写成员运算符,因为命名空间范围内的运算符函数具有与其参数对称的附加功能:它们不会将左侧特殊处理,因为双方都只是普通参数而不是对象参数必须*这个。如果左侧或右侧属于您的类的类型,则可以隐式转换另一侧 - 无论是左侧还是右侧。对于也没有使用友元定义语法定义的函数(传统上,在命名空间范围内),您将具有选择性地包含使这些运算符可用或不可用的标头的功能。
#2
7
They aren't mutually exclusive. "friend" means the non-member function can access the private members of the class. "inline" means there is no function call invocation, the body of the function is duplicated (in assembly) at every call site.
它们不是相互排斥的。 “friend”表示非成员函数可以访问该类的私有成员。 “inline”表示没有函数调用调用,函数体在每个调用站点都是重复的(在汇编中)。
#3
7
Grammatically speaking...
The friend
keyword is still needed to tell the compiler that this function is not a member of a class, EDIT: but instead a non-member function that can see the private members of the class.
还需要friend关键字来告诉编译器该函数不是类的成员,EDIT:而是一个非成员函数,可以看到该类的私有成员。
However, this could have been implemented more cleanly like this:
但是,这可以更加干净地实现,如下所示:
/* friend */ inline bool operator ==(const MonitorObjectString& rhs) const
{ return fVal == rhs.fVal; }
(Of course, I'm assuming fVal
is of a suitable type that can be compared without affecting its const-ness.)
(当然,我假设fVal是一种合适的类型,可以在不影响其常数的情况下进行比较。)