Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么时候我必须使用朋友函数而不是成员函数?_C++_Class_Friend - Fatal编程技术网

C++ 什么时候我必须使用朋友函数而不是成员函数?

C++ 什么时候我必须使用朋友函数而不是成员函数?,c++,class,friend,C++,Class,Friend,当朋友函数肯定比成员函数好时,有谁能给我一个条件吗?或者仅仅是一些我们可能使用友元函数而不是成员函数的原因。非常感谢。流式操作。 友元函数非常适合运算符重载 对于插入器之类的运算符,流对象显示在左侧,因此它不能是成员。但是,可以说这样一个函数不应该是朋友,因为它应该建立在公共检查或初始化接口上 二进制操作。 二进制运算符,特别是交换运算符提供了一个更有趣的例子。如果作为成员函数实现,则使用LHS根据成员查找分派重载。friend函数将使用参数相关的查找,同时将LHS和RH同等对待 如果允许转换

当朋友函数肯定比成员函数好时,有谁能给我一个条件吗?或者仅仅是一些我们可能使用友元函数而不是成员函数的原因。非常感谢。

流式操作。 友元函数非常适合运算符重载

对于插入器
之类的运算符,流对象显示在左侧,因此它不能是成员。但是,可以说这样一个函数不应该是朋友,因为它应该建立在公共检查或初始化接口上


二进制操作。 二进制运算符,特别是交换运算符提供了一个更有趣的例子。如果作为成员函数实现,则使用LHS根据成员查找分派重载。friend函数将使用参数相关的查找,同时将LHS和RH同等对待

如果允许转换,这一点很重要。如果我有一个
string
类,它隐式地从
char const*
C样式的字符串转换而来,那么
string string::operator+(string)
表达式将找不到
“x”+str
,但
友元字符串operator+(string,string)
会找到。顺便说一下,
std::string
符合此示例,这就是它使用非成员运算符的原因


跨多个类的接口。 另一种情况是,当您想要一些不能成为成员的东西时,因为它是在您不控制的类或非类类型上定义的。当应用于“随机的东西”时,它可能只是一个不可操作的选项,但仍然是有意义的。例如,我定义了这样一个函数
flush
,它表示输入结束并通过解析器传播。在我没有实现的许多事情中,其含义都有很好的定义。

流操作。 友元函数非常适合运算符重载

对于插入器
之类的运算符,流对象显示在左侧,因此它不能是成员。但是,可以说这样一个函数不应该是朋友,因为它应该建立在公共检查或初始化接口上


二进制操作。 二进制运算符,特别是交换运算符提供了一个更有趣的例子。如果作为成员函数实现,则使用LHS根据成员查找分派重载。friend函数将使用参数相关的查找,同时将LHS和RH同等对待

如果允许转换,这一点很重要。如果我有一个
string
类,它隐式地从
char const*
C样式的字符串转换而来,那么
string string::operator+(string)
表达式将找不到
“x”+str
,但
友元字符串operator+(string,string)
会找到。顺便说一下,
std::string
符合此示例,这就是它使用非成员运算符的原因


跨多个类的接口。
另一种情况是,当您想要一些不能成为成员的东西时,因为它是在您不控制的类或非类类型上定义的。当应用于“随机的东西”时,它可能只是一个不可操作的选项,但仍然是有意义的。例如,我定义了这样一个函数
flush
,它表示输入结束并通过解析器传播。在我没有实现的许多事情中,其含义是明确的。

一种情况(可能是典型情况)是当您试图重载
时,一种情况(可能是典型情况)是当您试图重载
时,当您重载使用同一类参数的运算符时,您使用成员函数。此外,为了定义类的行为,u使用成员函数。
Friend函数用于重载使用不同类的参数的运算符

例如流操作符,
cout当重载使用同一类参数的运算符时,则使用成员函数。此外,为了定义类的行为,u使用成员函数。
Friend函数用于重载使用不同类的参数的运算符

例如流操作符,
cout面向对象设计的基石之一是通过发送消息进行对象交互。为了发送消息(在本例中,调用成员函数),对象必须具有到目标对象的“链接”。该链接是通过在两个类之间建立关联形成的,作为类型定义的一部分

在对等关系中,任何一个对象都可以调用另一个对象上的操作。也就是说,这种关系是双向的

如果关联是双向的,那么两个类都需要指针。当您必须将对象绑定在一起时,问题就会出现。问题是先生成哪个对象?如果两个类都需要在其构造函数中引用另一个类才能工作,则存在循环依赖关系

可能最优雅的方法是创建一个将两个对象绑定在一起的自由函数。“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);
}