C++中的成员函数作为另一个类的友元函数问题

C++中的成员函数作为另一个类的友元函数,为什么c1.a1 = 1还是报错,访问不了对方私有成员?

class Class1
{
         friend void Class2::test();
public:
         int a;
private:
         int a1;
};
class Class2
{
public:
         void test()
         {
                   Class1 c1;
                   c1.a = 1;
                   c1.a1 = 1;      //这句话会报错,说对a1没有访问权限
         }
};

因为c++,要用到一个类型,必须在这个类型完整声明后才能使用。你在class1声明class2的成员函数是自己的友元,就必须要求class2的声明必须在class1之前.而class2的成员函数是class1的友元且要访问class1的成员,则class2 的成员函数必须声明在class1之后
所以代码应该如此

class Class2
{
public:
         void test();
};

class Class1
{
         friend void Class2::test();
public:
         int a;
private:
         int a1;
};
void Class2::test()
         {
                   Class1 c1;
                   c1.a = 1;
                   c1.a1 = 1;      //这句话会报错,说对a1没有访问权限
         }


  • 这个问题的回答你可以参考下: https://ask.csdn.net/questions/7488725
  • 以下回答由chatgpt基于相关博客总结生成:

    该问题出现的原因是:友元关系不具有传递性,即如果A是B的友元,B是C的友元,那么A不一定是C的友元。在这种情况下,子类对父类的友元不具有访问父类私有成员的权限。

    解决该问题的方法可以通过修改代码,将成员变量的访问权限进行改变,或者通过添加新的友元来解决。

    一种可能的解决方案是,将父类中需要访问的成员变量改为protected类型,这样子类就可以直接访问父类中的这些成员变量。另外,如果子类需要访问其他类的成员变量,可以在其他类中添加一个新的友元函数来实现。

    举一个具体的例子,假设我们有以下的代码:

    class ClassA {
    private:
        int a1;
        int a2;
    public:
        friend void ClassB::modifyA(ClassA& obj);
    };
    
    class ClassB {
    private:
        int b1;
        int b2;
    public:
        void modifyA(ClassA& obj) {
            obj.a1 = 1; // 在这里访问a1,会报错
        }
    };
    
    class ClassC : public ClassA {
    private:
        int c1;
    public:
        friend void ClassD::modifyC(ClassC& obj);
    };
    
    class ClassD {
    private:
        int d1;
        int d2;
    public:
        void modifyC(ClassC& obj) {
            obj.a2 = 2; // 在这里访问a2,不会报错
        }
    };
    

    在这个例子中,ClassB是ClassA的友元类,可以访问ClassA中的私有成员;ClassD是ClassC的友元类,可以访问ClassC中的私有成员。但是,当我们尝试在ClassB中修改ClassA中的成员变量时,会报错提示无法访问私有成员。

    为了解决这个问题,我们可以将ClassA中的成员变量改为protected类型,以便能够在子类中访问:

    class ClassA {
    protected: // 将私有成员改为protected
        int a1;
        int a2;
    public:
        friend void ClassB::modifyA(ClassA& obj);
    };
    
    class ClassB {
    private:
        int b1;
        int b2;
    public:
        void modifyA(ClassA& obj) {
            obj.a1 = 1; // 在这里访问a1,不会报错
        }
    };
    
    class ClassC : public ClassA {
    private:
        int c1;
    public:
        friend void ClassD::modifyC(ClassC& obj);
    };
    
    class ClassD {
    private:
        int d1;
        int d2;
    public:
        void modifyC(ClassC& obj) {
            obj.a2 = 2; // 在这里访问a2,不会报错
        }
    };
    

    这样,我们就可以成功地访问ClassA的私有成员了。不过,需要注意的是,将私有成员改为protected类型会破坏封装性,增加代码的耦合性和安全性风险,因此需要根据具体情况进行权衡。

你试试看把a1放在public中

a1是个局部变量,这跟友元函数哪有一毛钱关系