1

If the class G is in the namespace GSpace and it needs to be friends with the class M in the global namespace what do you have to do? I thought this would work:

/////////////////////M.h//////////////////////
#include "GFile.h"

class M
{
   public:
      friend class GSpace::G; // doesn't work, throws error
}

After researching on StackOverflow a bit, I found this answer https://stackoverflow.com/a/3843743/1797424

/////////////////////M.h//////////////////////

namespace GSpace 
{
   class G;
}

class M
{
   public:
      friend class GSpace::G; // works, no error
   private:
      GSpace::G gClassMember; // errors: "M uses undefined class GSpace::G"
};
// Note that G.h includes M.h so I do not include it here, 
// instead I have it included in M.cpp

That does work for getting the class friended. However, it creates an issue when I actually declare a class member using that type, because the class is not defined. GFile.h

Am I misunderstanding how #include and forward declaration behaves, or is it some kind of implementation issue on the side of the compiler (not likely, I'm assuming)?

Community
  • 1
  • 1
Josh
  • 119
  • 1
  • 10
  • Works for me: http://ideone.com/l9s72G. What is the error? Does `GFile.h` actually define `GSpace::G`? – Mike Seymour Jan 29 '14 at 13:52
  • 1
    The error is..? I'll bet either that `GFile.h` includes the file containing `class M`, or that you're missing [include guards](http://en.wikipedia.org/wiki/Include_guard) and need them. – Dark Falcon Jan 29 '14 at 13:53
  • @DarkFalcon The error I'm getting is that G is undefined when I try to create a member of it in class M. Both files have include guards, and there is no circular dependencies (that I have found). I'll update my code to include this error. – Josh Jan 29 '14 at 15:30
  • @Josh: Making a class a friend doesn't bring its name into the local scope. You still need to qualify it with the namespace. – Dark Falcon Jan 29 '14 at 15:58
  • @DarkFalcon It is (forgot to put it in the mockup code, was in a bit of a rush when writing it :/ ). Is there anything else that looks incorrect about this? – Josh Jan 29 '14 at 16:39
  • @Josh: The full definition of `G` also needs to be available, as the compiler needs to know its size. You cannot use only a forward declaration as you have it now. (Note, it would help if you can demonstrate with a [SSCCE](http://sscce.org/)) – Dark Falcon Jan 29 '14 at 16:50

2 Answers2

4
  • Because your member is not a pointer or reference, the compiler needs to know the size of G. You can't use a forward declaration.
  • As noted in the comment, you need to qualify G with the namespace.

Here is code which compiles for me:

namespace GSpace
{
   class G
   {
   };
}

class M
{
   public:
      friend class GSpace::G;
   private:
      GSpace::G gClassMember;
};

int main() {return 0;}
Dark Falcon
  • 43,592
  • 5
  • 83
  • 98
  • Makes perfect sense! Thank you. Would this be the same situation if it was a parameter for a method? Does the compiler need to know the size of those ahead of time as well? Can it figure out how much stack allocation a parameter needs at runtime? – Josh Jan 29 '14 at 17:28
  • A parameter to a method can be forward-declared, but you couldn't call that method until the parameter type is declared. This is compile-time only. C++ has no built-in reflection or metadata to allow runtime determination of a method parameter sizes. – Dark Falcon Jan 29 '14 at 17:35
1

Try the following

namespace GSpace
{
   class G;
}

class M
{
   public:
      friend class GSpace::G; 
}

namespace GSpace
{
   class G { /* definition of the class */ };
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335