我正在查看以下文档
https://en.cppreference.com/w/cpp/language/friend
第一个语法示例(友元函数声明)让我感到困惑
上面写着:
1.将一个或多个函数指定为该类的友元
class Y
{
int data; // private member
// the non-member function operator<< will have access to Y's private members
friend std::ostream& operator<<(std::ostream& out, const Y& o);
friend char* X::foo(int); // members of other classes can be friends too
friend X::X(char), X::~X(); // constructors and destructors can be friends
};
// friend declaration does not declare a member function
// this operator<< still needs to be defined, as a non-member
std::ostream& operator<<(std::ostream& out, const Y& y)
{
return out << y.data; // can access private member Y::data
}
我的困惑来自下面的代码行friend char* X::foo(int); // members of other classes can be friends too
,我不知道为什么要声明这样一个函数,因为我看不出给另一个类的成员函数友谊有什么用(在本例中为类X
)由于我们没有将class Y
引用对象作为参数传递,所以我们不能通过foo
函数访问Y
的私有成员。
是否存在此示例可能有用的用例?
1条答案
按热度按时间z9gpfhce1#
我想首先指出的是,并非C++标准所允许的所有东西都是有用的。有时候,允许某些东西是因为它们不会造成伤害,而禁止它们会使标准变得更加复杂。在这些情况下,标准倾向于简单,这意味着允许。
有时候,这种宽容本身是有用的,因为最终有人会发现被允许的东西似乎是无用的。所以询问有用性可以是富有成效的。像这样的问题对知识的增长是有益的,只要一个人不太沉迷于它们。有时候例子只是什么是可能的,而不是什么是(已知的)有用的例子。
现在说说手头的案子。
让我们假设
X
有一个Y
类型的成员,那么给予X
访问Y
的data
可能是合理的。X
的定义可能看起来如下。(使用unique_ptr
是为了避免循环依赖问题-X
的定义需要在Y
的定义之前发生。)在这个设置中,有了友谊,构造函数就可以将
token->data
设置为所需的任何值,foo()
就可以更改该值,析构函数就可以读取该值。尽管这为
friend
声明提供了一个理由,到目前为止,用私有嵌套类替换Y
也可以。这就是为什么我添加了getToken()
和giveToken()
成员。我可以看到这个类将*token
的副本提供给消费者持有。可以将此视为拍摄快照。由于消费者不是Y
的朋友,令牌实际上是不可变的,他们可以复制、移动、丢弃它,但不能修改它(如果Y
构造函数是私有的,消费者也不能创建新的令牌)。稍后,可以将令牌提供给某个对象(不一定是同一个对象,* 不一定是
X
对象 *),可能是为了将其内部状态重置为快照。(如果可以通过*pimpl = y;
完成,则可以在没有友谊的情况下完成此操作。)如果存在多个可以处理这些令牌的类,有理由使X1 M20 N1 X成为独立类而不是嵌套类。