Specify a class member function as a friend of another class?

后端 未结 7 751
小蘑菇
小蘑菇 2020-12-08 21:43

According to the C++ Primer book, the author mentioned that We can specify a class member function as a friend of another class, instead of the entire class (page 634).

相关标签:
7条回答
  • 2020-12-08 22:04

    When the compiler starts reading the code( usually from top ) and it encounters this line:

    friend void B::fB(A& a);

    Then compiler doesn't understand what do you mean by this B::. Even if you have defined this class later in the code but compiler doesn't know that. So it's usually a good to practice to do forward declaration of class( class Name; ) if the definition resides later in the code.

    0 讨论(0)
  • 2020-12-08 22:05

    @juanchopanza @ipkiss Regarding the problem that you can't access data members of A inside fB(A& a) because A is not defined yet. Instead of defining it in a separate file and including it, you can just define the function fB(A& a) after the definition of class A so that fB(A& a) is able to see data members of A.

    0 讨论(0)
  • 2020-12-08 22:09

    When the compiler starts compiling the code( usually from top ) and it encounters this line:

    friend void B::fB(A& a);
    
    1. at this point, compiler has no idea about type info of B so it throws an error ( 'B' : is not a class or namespace name ).
    2. by forward declaration of class B, compiler knows about type of B is Class in advance to its actual declaration with all members.

    3. run below code after forward declaration of class B.

    ///////////////

    class B;
    class A
    {
    public:
        friend void B::fB(A& a); 
        void fA(){};
    };
    class B
    {
    public:
        void fB(A& a){};
        void fB2(A& a){};
    };
    

    Still error !!!

    because forward declaration is just a declaration of an identifier for which the programmer has not yet given a complete definition. so compiler needs full definition of B before class A.

    Note: class A definition dependents on type of B and also definition of B (i.e B::fB) so that forward declaration alone can not resolve, complete definition of class B needs to define before class A.

    4 run this code

    ////////

    class B
    {
    public:
        void fB(A& a){};
        void fB2(A& a){};
    };
    class A
    {
    public:
        friend void B::fB(A& a); 
        void fA(){}
    };
    

    Still error !!!

    because class B member functions fB & fB2 having arguments of type A but compiler has no idea about type info of A so by forward declaration of class A, we can let compiler knows about type info of A. Note: class B definition only dependent on type of A not the members of A so that forward declaration of A resolve step 4.

    1. final code

    ////////////////////////

    class A;  // forward declaration of A needed by B
    class B
    {
    public:
        void fB(A& a);
    };
    
    class A
    {
        int i;
    public:
        friend void fA(A& a);    //specifying function fA as a friend of A, fA is not member function of A
        friend void B::fB(A& a); //specifying B class member function fB as a friend of A
    };
    
    // fA is Friend function of A
    void fA(A& a)
    {
        a.i  = 11; // accessing and modifying Class A private member i
        cout<<a.i<<endl;
    }
    
    // B::fB should be defined after class A definition only because this member function can access Class A members
    void B::fB(A& a)
    {
        a.i  = 22; // accessing and modifying Class A private member i in Class B member function fB
        cout<<a.i<<endl;
    }
    
    int main()
    {
        A a;
        fA(a);    // calling friend function of class A
    
        B b;
        b.fB(a);  // calling B class member function fB, B:fB is friend of class A
    
        return 0;
    }
    

    6 Exercise:

    // Cyclic dependency 
    #include<iostream>
    using namespace std;
    
    class A;
    
    class B
    {
    public:
        void fB(A& a);
        friend void A::fA(B& b); //specifying class A's member function fA as a friend of B
    };
    
    class A
    {
        int i;
    public:
        void fA(B& b);  
        friend void B::fB(A& a); //specifying class B's member function fB as a friend of A
    };
    
    int main()
    {
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-08 22:09

    First of all before using a particular class name you will have to declare it first. So you will need a forward declaration of the Class B as you are using it in Class A before the Class B has been originally declared.

    Secondly you will need to define the functions (that are using variables from both the classes- here the friend functions ) after both the classes have been defined. Or else we may face errors.

    For example

    #include<iostream>
    
    using namespace std;
    
    class alpha1;
    
    class alpha2
    {
        public:
    
            void put_bata(int a,int b);
    };
    
    void alpha2 :: put_bata(int a,int b)
    {
        alpha1 net;
    
        net.roll=a;
    
        net.id=b;
    
        net.get_data();
    }
    
    class alpha1
    {
        int roll;
    
        int id;
    
        public:
    
            void get_data(void)
            {
                cout<<roll<<endl<<id<<endl;
            }
    
            friend void alpha2 :: put_bata(int a,int b);
    };
    
    int main()
    {
        alpha2 gamma;
    
        gamma.put_bata(5,6);
    
        return 0;
    }
    

    Will show us errors as put_bata tries to access roll and id before they are defined even if we had a forward declaration of the class but the code given below will just work fine.

    #include<iostream>
    
    using namespace std;
    
    class alpha1;
    
    class alpha2
    {
        public:
    
            void put_bata(int a,int b);
    };
    
    class alpha1
    {
        int roll;
    
        int id;
    
        public:
    
            void get_data(void)
            {
                cout<<roll<<endl<<id<<endl;
            }
    
            friend void alpha2 :: put_bata(int a,int b);
    };
    
    void alpha2 :: put_bata(int a,int b)
    {
        alpha1 net;
    
        net.roll=a;
    
        net.id=b;
    
        net.get_data();
    }
    
    
    int main()
    {
        alpha2 gamma;
    
        gamma.put_bata(5,6);
    
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-08 22:18

    Try putting the B definition before A's:

    class A; // forward declaration of A needed by B
    
    class B
    {
    public:
        // if these require full definition of A, then put body in implementation file
        void fB(A& a); // Note: no body, unlike original.
        void fB2(A& a); // no body.
    };
    
    class A
    {
    public:
        friend void B::fB(A& a);
        void fA(){}
    };
    

    A needs the full definition of B. However, B needs to know about A, but does not need the full definition, so you need the forward declaration of A.

    0 讨论(0)
  • 2020-12-08 22:21

    For this to work, the full definition of B needs to be known before the definition of A.

    So forward declare A, since B doesn't need the full type, and switch the definitions around:

    class A;
    class B
    {
    public:
        void fB(A& a){};
        void fB2(A& a){};
    };
    class A
    {
    public:
        friend void B::fB(A& a);
        void fA(){}
    };
    
    0 讨论(0)
提交回复
热议问题