当朋友的功能肯定比成员函数更好时,任何身体都可以给我一个条件吗?或者仅仅是为什么我们可以使用友元函数而不是成员函数的一些原因。非常感谢你。
答案 0 :(得分:2)
友方函数非常适合运算符重载。
对于像插入器<<
或提取器>>
这样的运算符,流对象显示在左侧,因此它不能是成员。但是,可以说这样的功能很少应该是朋友,因为它应该建立在公共检查或初始化界面上。
二元运算符,尤其是可交换运算符,提供了一个更有趣的案例。如果实现为成员函数,则使用LHS根据成员查找调度重载。友元函数将使用与参数相关的查找,同时对待LHS和RHS。
如果允许转换,这很重要。如果我有一个string
类隐式转换为char const *
C风格的字符串,则找不到表达式string string::operator+(string)
的{{1}},而"x" + str
} 将。顺便说一句,friend string operator+(string, string)
符合这个例子,这就是它使用非成员运算符的原因。
另一种情况是,当你想要一些不能成为成员的东西时,因为它是在你无法控制的类或非类类型上定义的。也许它只是一个无操作应用于“随机的东西”,但仍然有意义。例如,我定义了一个函数std::string
,它表示输入结束并通过解析器传播。对于我没有实现的许多事情,这个含义是明确定义的。
答案 1 :(得分:1)
一种情况(可能是典型情况)是当您尝试重载<<
运算符以打印类的成员时。您根本无法将其重载为member function
,因为第一个参数必须是ostream
的对象。您必须使用friend
功能。
根据Scott Myers的Effective C ++ Item23:
首选非会员非朋友功能到会员功能。这样做可以提高封装,封装灵活性和功能扩展性。
答案 2 :(得分:0)
当您重载使用同一类中的参数的运算符时,则使用成员函数。另外,为了定义类的行为,你使用成员函数。 Friend函数用于重载使用不同类参数的运算符
例如流操作符,
cout << 2
在这种情况下,cout是ostream类的对象,2是int类的成员。
在这种情况下,您将使用非成员函数的友元函数,这些函数允许您在使用运算符时也使用其他类的对象。 流插入运算符和流提取运算符是示例。
答案 3 :(得分:0)
面向对象设计的基石之一是通过发送消息进行交互的对象。为了发送消息(在这种情况下,调用成员函数),对象必须具有到目标对象的“链接”。该链接是通过在两个类之间建立关联而形成的,作为类型定义的一部分。
在对等关系中,任一对象都可以在另一个对象上调用操作。也就是说,这种关系是双向的。
如果关联是双向的,那么这两个类都需要指针。当你必须将对象绑定在一起时会出现问题。问题是首先构建哪个对象?如果两个类都需要在其构造函数中引用另一个类来工作,则存在循环依赖。
最优雅的方法可能是创建一个将两个对象绑定在一起的自由函数。 'bind'函数是两个类的朋友,允许连接他们的指针(不用暴露它们):
class CameraStabiliser;
class UI
{
private:
CameraStabiliser* pStabiliser;
public:
UI() : pStabiliser(NULL) {}
void inPosition();
friend void bind(UI& ui, CameraStabiliser& cs);
};
class CameraStabiliser
{
private:
UI* pUI;
public:
CameraStabiliser() : pUI(NULL) {}
void moveTo(Position pos);
friend void bind(UI& ui, CameraStabiliser& cs);
};
void bind(UI& ui, CameraStabiliser& cs)
{
ui.pStabiliser = &cs;
cs.pUI = &ui;
}
int main()
{
UI console;
CameraStabiliser stabiliser;
bind(console, stabiliser);
}