6

I was wondering if you have to #include "Class1.h" in a class that is using that as a friend. For example the .h file for the class that is granting permission to Class1 class.

class Class2 {
   friend class Class1;
}

would you need to #include "Class1.h" or is it not necessary? Also in the Class2 class, Class1 objects are never created or used. Class1 just manipulates Class2 never the other way around.

JDN
  • 509
  • 3
  • 8
  • 14

2 Answers2

12

The syntax is:

friend class Class1;

And no, you don't include the header.

More generally, you don't need to include the header unless you are actually making use of the class definition in some way (e.g. you use an instance of the class and the compiler needs to know what's in it). If you're just referring to the class by name, e.g. you only have a pointer to an instance of the class and you're passing it around, then the compiler doesn't need to see the class definition - it suffices to tell it about the class by declaring it:

class Class1;

This is important for two reasons: the minor one is that it allows you to define types which refer to each other (but you shouldn't!); the major one is that it allows you to reduce the physical coupling in your code base, which can help reduce compile times.


To answer Gary's comment, observe that this compiles and links fine:

class X;

class Y
{
    X *x;
};

int main()
{
    Y y;
    return 0;
}

There is no need to provide the definition of X unless you actually use something from X.

Stuart Golodetz
  • 20,238
  • 4
  • 51
  • 80
  • As long as the class is eventually included in the same binary (else you'll get a error during linking) – Gary Robinson Apr 11 '12 at 20:33
  • 1
    @GaryRobinson: You only get a link error if you try and do something that requires the class definition actually. Try it and see. – Stuart Golodetz Apr 11 '12 at 20:35
  • 1
    What like an imaginary friend :) I'd never tried that no, and it's maybe a good pointed theory but I'm assuming the questioner is going to actually use a friend class in some way – Gary Robinson Apr 11 '12 at 21:04
  • Lol :) For the record, there are actually occasions when it makes a lot of sense to declare a type but not define it - for example, see `NullType` in this article I wrote a while back about template metaprogramming: http://accu.org/index.php/journals/1422 – Stuart Golodetz Apr 11 '12 at 21:20
  • `it suffices to tell it about the class by declaring it: \`class Class1;\` `. That's not true. You don't even have to do that much. See and run my answer here: https://stackoverflow.com/questions/10113374/including-header-file-in-class-that-is-a-friend/60961619#60961619. – Gabriel Staples Mar 31 '20 at 23:52
  • 1
    @GabrielStaples As mentioned below, I think you may have misinterpreted what I meant by "more generally" - I meant that there are additional situations, other than when you are declaring a class as a friend, in which you similarly may not be making use of the class definition, but still need to declare the class to the compiler. The friend declaration indeed acts as a declaration of the class (and you don't need another separate one), but that wasn't the point I was trying to make. – Stuart Golodetz Apr 01 '20 at 16:12
  • 1
    I see. That makes sense now. Thanks. – Gabriel Staples Apr 01 '20 at 16:59
1

No, you do not have to "#include "Class1.h" in a class that is using that as a friend." You don't even have to forward declare the existence of class Class1 either. You just have to declare Class1 as a friend inside Class2's definition and that's it! (I suppose the friend class Class1 statement alone acts as a kind of "forward declaration" of Class1 all by itself):

// Inside the definition of Class2, place this (usually
// at the very bottom inside the `private:` section)
friend class Class1;

Here's a full, working example. You can run and test it here (notice there are 2 tabs when running this example--one per file).

Class2.h:

#pragma once 

class Class2
{
private:
    int _myInt = 123;

    // Declare Class1 as a friend class to Class2 so that Class1 can access all of Class2's private
    // and protected members (as though Class2's members were part of Class1)
    friend class Class1;
};

main.cpp:

#include "Class2.h"

#include <stdio.h>

class Class1
{
public:
    int getClass2Int()
    {
        return _class2._myInt;
    }

    void setClass2Int(int val)
    {
        _class2._myInt = val;
    }

private:
    Class2 _class2;
};

int main()
{
    printf("Hello World\n");

    Class1 class1;

    printf("class1.getClass2Int() = %i\n", class1.getClass2Int());
    class1.setClass2Int(700);
    printf("class1.getClass2Int() = %i\n", class1.getClass2Int());

    return 0;
}

Output:

Hello World
class1.getClass2Int() = 123
class1.getClass2Int() = 700

References:

  1. https://www.geeksforgeeks.org/friend-class-function-cpp/
  2. Google search for "do you need to include header file to declare friend class?"
  3. Including header file in class that is a friend
Gabriel Staples
  • 36,492
  • 15
  • 194
  • 265
  • 1
    Just to clarify, the "more generally" was referring to "even when you're not making the class a friend" - i.e. in any situation in which you aren't making use of the class definition, including this one. That wasn't intended to imply that you need to forward declare the class *in addition to* doing so when you declare it to be a friend. – Stuart Golodetz Apr 01 '20 at 16:07
  • 1
    I see. I've modified my answer to remove mention of your answer. I think my answer is still very useful as a full example of how to do it all. – Gabriel Staples Apr 01 '20 at 16:59