0

I want to define two classes, A and B. A has a data member which is a Class B object and is in-class initialised. A also has a method to retrieve the value in this B type data member and this method would be declared as a friend method in B. Here is my code:

class A{
public:
    int getBValue();
private:
    B b=B(1);
};

class B{
public:
    friend int A::getBValue();
    B(int i):value(i){}
private:
    int value;
};

int A::getBValue(){
    return b.value;
}

And unsurprisingly the compilation had failed because of unknown type B in class A definition. I had tried to swap the definitions of A and B in the source and the result was even worse. Is there a possible way to resolve this cross reference issue between A and B?

God_of_Thunder
  • 753
  • 3
  • 20
  • 46
  • What was the error when you declared B first? What happens if you only make the class 'A' as friend when switching the order? Anyway, why not have a public getter? – László Papp Dec 25 '13 at 12:21
  • You can't make this without a compromise - either store a pointer to B instead of an instance and forward declare it, or give up on `friend` requirement and provide a getter instead. – jrok Dec 25 '13 at 12:27
  • @LaszloPapp Two errors. One is "use of undeclared identifier 'A'", the other is "'value' is a private member of 'B'". – God_of_Thunder Dec 25 '13 at 13:10

2 Answers2

3

If this is the complete code as you have it, then the problem is that the compiler doesn't know what a B is at the time it is compiling class A. One way to solve it is by creating a pointer to B instead of having a B itself:

A.h

#ifndef CLASS_A
#define CLASS_A

class B;

class A{
public:
    int getBValue();
private:
    B *b;
};

#endif

B.h

#ifndef CLASS_B
#define CLASS_B

#include "A.h"

class B{
public:
    friend int A::getBValue();
    B(int i):value(i){}
private:
    int value;
};

#endif

A.cpp

#include "A.h"
#include "B.h"

int A::getBValue(){
    return b->value;
}
Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
0

Replacing an embedded member of type B with a pointer (or reference) to a B changes the way your class works and needs additional care when copying objects of class A.

When you reverse the definitions, you cannot make a member function of class A a friend of class B, because the type of A is incomplete at the time of the friend declaration. But you can make the entire class A a friend.

A solution with class A having an embedded member of class B could look like this:

class A;

class B{
public:
    friend class A;
    B(int i):value(i){}
private:
    int value;
};

class A{
public:
    int getBValue();
private:
    B b=B(1);
};

int A::getBValue(){
    return b.value;
}

Changes made:

  1. Declared B before A. A forward declaration for A is used.
  2. Made the class A a friend of B. This works even when A is not yet fully defined.

Compiles with g++ version 4.7.2 (-std=c++11 needed for B b=B(1);)

Anyway, having a member of class A accessing a private member of class B is something which can (and should) almost always be avoided (see Laszlo Papp's comment on your post).

Adrian W
  • 4,563
  • 11
  • 38
  • 52