C 阶级友谊

C++ class friendship

本文关键字:友谊      更新时间:2023-10-16

我正在编写代码以通过另一个朋友类访问类的私人成员。以下代码工作

// Example program
#include <iostream>
#include <string>
using namespace std;
class Foo
{
    private:
    int a;
    protected:
    public:
    friend class Bar;

    Foo(int x)
    {
        a = x ;
    }
};
class Bar
{
    private:
    protected:
    public:
    int b;
    Bar(Foo& f)
    {
        b = f.a;
        cout << "f.a is " << f.a << endl;
    }
};
int main()
{
    Foo foo(5);
    Bar bar(foo);
    cout << "Value of variable b is " << bar.b << endl;
}

上面的代码正常工作。但是,如果我想通过朋友类Bar中的函数访问Foo的私有变量,我将无法。请参阅下面的代码

#include <iostream>
#include <string>
using namespace std;
class Foo
{
    private:
    int a;
    protected:
    public:
    friend class Bar;

    Foo(int x)
    {
        a = x ;
    }
};
class Bar
{
    private:
    protected:
    public:
    int b;
    Bar(Foo& f)
    {
        b = f.a;
    }
    void printvariable(void)
    {
        cout << "f.a is " << f.a << endl;
    }
};
int main()
{
    Foo foo(5);
    Bar bar(foo);
    cout << "Value of variable b is " << bar.b << endl;
}

我完全理解为什么执行失败

void printvariable(void)
    {
        cout << "f.a is " << f.a << endl;
    }

函数由于f不在函数范围内。但是,由于我在Bar b的构造函数中传递了Foo f,因此我希望编写代码,使我能够访问Foo中的成员,而无需将Foo f再次传递给函数printvariable()

编写此代码的最有效方法是什么?

您可以保留对f的引用。代码应为:

class Bar
{
    private:
    protected:
    public:
    int b;
    Foo& f_ref;
    Bar(Foo& f)
    :f_ref(f)
    {
        b = f.a;
    }
    void printvariable(void)
    {
        cout << "f.a is " << f_ref.a << endl;
    }
};

测试!

您可以这样做,但是如果我是您,您也会写一些Getters,也不是真正推荐的班级友谊。

class Bar {
public:
    Foo& ref;
    Bar(Foo& f)
        : ref { f }
    { }
    void printvariable() {
        cout << "f.a is " << ref.a << endl;
    }
};

顺便说一句,没有理由在C 的括号中添加void,它失去了C的含义,现在没有效果。

您在某个点上错了。您确实在CTOR中传递了对f的引用,但是构造函数和整个class Bar 不记得 a f的整个整个对象。在您的原始代码中,构造函数仅使栏对象记住对象的int a部分,因此后来可以访问一点点:

class Foo
{
    ...
    friend class Bar;
    ...
};
class Bar
{
    ...
    int b;
    Bar(Foo& f)
    {
        b = f.a;    // <=--- HERE
    }
    void printvariable(void)
    {
        cout << "f.a is " << b << endl;  // <-- now it refers B
    }

请注意,您的bar的CTOR如何仅读取f.a并将其存储在b中。从现在开始,条对象只会记住b,仅此而已。您可以在printvariable中自由访问b。但是,它不会是 a -taken-from- f。它将是b,将其设置为与构造函数期间F.A相同的值。由于那个时间点,bf.a是完全分开的。这就是价值复制的工作方式。

要使酒吧记住整个 f,您必须,请记住整个 f:

class Bar
{
    ...
    Foo wholeThing;
    Bar(Foo& f)
    {
        wholeThing = f;    // <=--- HERE
    }
    void printvariable(void)
    {
        cout << "f.a is " << wholeThing.a << endl;
    }

但是,同样,有一个捕获:现在,由于wholeThingFoo类型,因此构造函数实际上将在wholeThing=f期间复制该对象。与b=f.a时一样,但现在它记得整个f。

当然,这只是类型问题。您可以存储一个参考而不是全面的参考,但是它需要一些不同的初始化语法:

class Bar
{
    ...
    Foo& wholeThing;
    Bar(Foo& f) :
        wholeThing(f)      // <=--- HERE
    {
                           // <=--- empty
    }
    void printvariable(void)
    {
        cout << "f.a is " << wholeThing.a << endl;
    }