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

蓝咒 提交于 2019-12-04 10:11:40

问题


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).

Then, I tested this code:

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

I just wanted the fB() to be friend of class A, not the entire class B. But the about code produced an error: 'B' : is not a class or namespace name. (I am using Visual C++ 2005)


回答1:


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.




回答2:


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(){}
};



回答3:


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;
}



回答4:


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.




回答5:


firstly forward declare class A, so that its visible in class B definition. then define class A containing a friend function from class B.




回答6:


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;
}



回答7:


@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.



来源:https://stackoverflow.com/questions/10546391/specify-a-class-member-function-as-a-friend-of-another-class

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!