我在大学这个学期的C ++课程中有一个面向对象的编程,我们正在学习有关朋友函数的知识。
我本能地讨厌它们绕过封装和数据隐藏所提供的安全性的能力,我在互联网上读了几篇文章,有些人认为这是一个合法使用的好主意。
OOP专家会对C ++中的好友功能怎么说?我应该浏览一下还是应该了解更多?
我在大学这个学期的C ++课程中有一个面向对象的编程,我们正在学习有关朋友函数的知识。
我本能地讨厌它们绕过封装和数据隐藏所提供的安全性的能力,我在互联网上读了几篇文章,有些人认为这是一个合法使用的好主意。
OOP专家会对C ++中的好友功能怎么说?我应该浏览一下还是应该了解更多?
Answers:
使与该类的C ++类成员相关的所有功能并不总是很方便。例如,想象一下带有标量乘法的矢量代数的实现。我们要写:
double a;
Vector v, w;
w = v * a;
我们可以使用成员函数来做到这一点:
public class Vector {
...
Vector operator*(double a);
}
但是我们还要写:
w = a * v
这需要一个免费功能:
Vector operator*(double a, Vector v)
的friend
关键字加入到C ++来支持这种用法。free函数是Vector类实现的一部分,应在同一标头中声明,并在同一源文件中实现。
类似地,我们可以friend
用来简化紧密耦合类的实现,例如集合和迭代器。同样,我将在同一标头中声明两个类,并在同一源文件中实现它们。
inline Vector operator*(double a, Vector v) { return v*a; }
。实际上是规范的解决方案。
inline Vector operator*(double a, Vector v) { return -v*a; }
并且仍然不需要友谊。
在封装方面,Friend函数与成员函数没有什么不同。但是,它们可以提供其他优点-例如更通用,尤其是在涉及模板的情况下。另外,只能将某些运算符指定为自由函数,因此,如果希望它们具有成员访问权限,则必须friend
。
相对于friend
被迫制作您不想公开的功能,单个功能要好。这意味着整个世界都可以使用它,而不仅仅是一个功能。
friend
一个也是“私有”的函数,例如仅在单个TU中声明的函数。
“ OOPs专家会说什么…… ”这主要取决于他在C ++中的专业程度,按照其自己的规范,该专家不是(也不想成为)纯粹主义者的语言。
OOP狂热者不使用C ++(他们更喜欢Smalltalk,并且喜欢Java)。
函数式编程Zelot不使用C ++(他们更喜欢LISP及其后续产品)
大多数OOP专家不喜欢朋友功能仅仅是因为他们希望C ++的OOP部分表现得像Smalltalk。但是C ++并不是Smalltalk,他们甚至无法理解,朋友不会破坏封装,这是非常简单的原因,即没有您的类需要它,函数就不能成为您的类的朋友。
并从“功能”立点之间,a.fn(b)
并fn(a,b)
没有什么区别(这里fn
是朋友):当事人是相同的。简而言之,一种语法可能比另一种语法更合适:如果fn关于a
和可以互换b
,fn(a,b)
则可能更适合a.fn(b)
(其中看起来具有“特殊作用”,而实际上不适合)。
不,不是的。就像成员身份一样,“朋友”是授予访问权限的明确机制。您不能(在符合标准的程序中)在不修改类源的情况下授予自己访问类的权限。
在C ++ FAQ简洁:
如果可以,请使用成员,如果需要,请使用朋友。
常见问题解答提供了一种思考友谊的更有用的方法:
许多人认为朋友功能是课堂之外的东西。相反,请尝试将朋友功能视为类的公共接口的一部分。类声明中的friend函数不会违反封装,就像public成员函数违反封装一样:就访问类的非公共部分而言,两者都具有完全相同的权限。
C ++朋友功能与以下功能密切相关:
这意味着它们没有此指针,因此不在类/对象的范围内。另一方面,它们通常采用使它们再次属于该类的参数。这是一些示例,阐明了链接:
class B;
class A {
public:
friend void f(A &a, B &b);
private:
int m_a;
};
class B {
public:
friend void f(A &a, B &b);
private:
int m_b;
};
void f(A &a, B &b) { /* uses both A's and B's private data */ }
静态函数和朋友函数之间的唯一区别是,朋友函数可以使用多个类。
在c ++中使用友善机制需要程序员具有大约10-15年的c ++编程经验,因此一开始您应该避免使用它。它的高级功能。