将函数指定为Friend C++

5n0oy7gb  于 2023-01-18  发布在  其他
关注(0)|答案(1)|浏览(110)

我正在查看以下文档
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的私有成员。
是否存在此示例可能有用的用例?

z9gpfhce

z9gpfhce1#

我想首先指出的是,并非C++标准所允许的所有东西都是有用的。有时候,允许某些东西是因为它们不会造成伤害,而禁止它们会使标准变得更加复杂。在这些情况下,标准倾向于简单,这意味着允许。
有时候,这种宽容本身是有用的,因为最终有人会发现被允许的东西似乎是无用的。所以询问有用性可以是富有成效的。像这样的问题对知识的增长是有益的,只要一个人不太沉迷于它们。有时候例子只是什么是可能的,而不是什么是(已知的)有用的例子。
现在说说手头的案子。
让我们假设X有一个Y类型的成员,那么给予X访问Ydata可能是合理的。X的定义可能看起来如下。(使用unique_ptr是为了避免循环依赖问题-X的定义需要在Y的定义之前发生。)

class Y; // Forward declaration
class X
{
    std::unique_ptr<Y> token;

  public:
    X(char);
    ~X();

    char* foo(int);

    Y getToken();
    void giveToken(Y);
};

在这个设置中,有了友谊,构造函数就可以将token->data设置为所需的任何值,foo()就可以更改该值,析构函数就可以读取该值。
尽管这为friend声明提供了一个理由,到目前为止,用私有嵌套类替换Y也可以。这就是为什么我添加了getToken()giveToken()成员。我可以看到这个类将*token的副本提供给消费者持有。可以将此视为拍摄快照。由于消费者不是Y的朋友,令牌实际上是不可变的,他们可以复制、移动、丢弃它,但不能修改它(如果Y构造函数是私有的,消费者也不能创建新的令牌)。
稍后,可以将令牌提供给某个对象(不一定是同一个对象,* 不一定是X对象 *),可能是为了将其内部状态重置为快照。(如果可以通过*pimpl = y;完成,则可以在没有友谊的情况下完成此操作。)如果存在多个可以处理这些令牌的类,有理由使X1 M20 N1 X成为独立类而不是嵌套类。

  • 我不认为这是一个好的设计,但它是一个有效的设计。*

相关问题