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;
}
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 B
would 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
but 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
.