Home > Net >  C friend member function behaviour looks erratic
C friend member function behaviour looks erratic

Time:05-31

I have always tried to avoid friend concept because it beats the purpose of encapsulation. However, I was just experimenting with the concept and the following code fails to compile with the following error:

main.cpp:29:28: error: ‘int A::a’ is private within this context

On the other hand, if I just place the class B before class A with forward declaration of class A, it runs fine. Am I missing something really trivial here?

#include <iostream>

class A {
    int a;

public:
    A() { a = 0; }

    // friend function
    friend void B::showA(A& x);
};

class B
{
    public:
     void showA(A&);
    
    private:
    int b;
    
    
};

void B::showA(A& x)
{
    // Since showA() is a friend, it can access
    // private members of A
    std::cout << "A::a=" << x.a;
}

int main()
{
    A a;
    B b;
    b.showA(a);
    return 0;
}

CodePudding user response:

As it is, you are using class B within class A, but as you can see B is not declared before it is used. That is causing an error like this:

error: 'B' has not been declared

and a little further

error: int 'A::a' is private within this context

because the friendship relationship has not been linked due to the first error (as A::a is by default private)

You may try then to forward-declare B, like the following

#include<..>
class B;
class A {
    int a;

public:
    A() { a = 0; }

    // friend function
    friend void B::showA(A& x);
};
class B{
...
}
...

This would generate an error error: invalid use of incomplete type 'class B' because a forward declaration only says that a particular class (here class B) will be defined later so you can reference it or have pointers to it, but it does not say what members this class will have, so the compiler is unable to know if your future class Bwould have a B::showA method, thus the error, incomplete type error. At this time, the compiler does not know if your future class B (used in class A) would have a function B::showA.

The simplest solution would be to declare B before A and then forward declare A (with class A;) as follows. This way, you tell the compiler - here is my class B declaration (it contains a method B::showA), and it uses a class A that I will define later. As there is no need to known what would be the content of A, it will compile.

// as you use class A before it is declared, you need to forward declare it
class A;
class B
{
    public:
     void showA(A&);

    private:
    int b;


};

class A {
    int a;
...

This would compile and execute the function B::showA.

  • Related