0

I have some old c++ code where friend classes are all declared outside of a class in a bare include file. The include file is then shared between different classes Such as follows

IncludeFriends.h

#pragma once
friend class Friend1;// Error E0239
friend class Friend2;// Error E0239

friends.h

#pragma once
class Friend1
{
public:
    Friend1() {};
private:
    int pF1{0};
};

class Friend2
{
public:
    Friend2() {};
private:
    int pF2{0};
};

classes.h

#pragma once
#include "Friends.h"
class Class1
{
#include "IncludeFriends.h"
public:
    Class1() {};
    int getFriendInt(Friend1& f1) { return f1.pF1; };
};

class Class2
{
#include "IncludeFriends.h"
public:
    Class2() {};
    int getFriendInt(Friend2& f2) { return f2.pF2; };
};

I get the following errors:

1>------ Build started: Project: friendsTest, Configuration: Debug Win32 ------
1>classes.cpp
1>D:\friendsTest\classes.h(8,43): error C2248: 'Friend1::pF1': cannot access private member declared in class 'Friend1'
1>D:\friendsTest\Friends.h(7): message : see declaration of 'Friend1::pF1'
1>D:\friendsTest\Friends.h(2): message : see declaration of 'Friend1'
1>D:\friendsTest\classes.h(16,43): error C2248: 'Friend2::pF2': cannot access private member declared in class 'Friend2'
1>D:\friendsTest\Friends.h(15): message : see declaration of 'Friend2::pF2'
1>D:\friendsTest\friendsTest\Friends.h(10): message : see declaration of 'Friend2'
1>friendsTest.cpp
1>Generating Code...
1>Done building project "friendsTest.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

my editor also issues an additional complaint for the IncludeFiles.h file. It states: E0239 invalid specifier outside class declaration

and so on for n amount of classes and friend classes. This is no longer allowed in c++. I tried encapsulating the friend classes in another class that is itself declared as a friend in all the class definitions, but I read this will not work since there is no such thing as inheritance for friend classes, right? I was wondering if there is some workaround. I really dont want to write in all of the friends for each class since that would make my code way less readable. Thanks in advance!

EDIT: Since some have remarked that the general approach taken here is not the most sensible, maybe an alternative would be better than having to fix the actual problem.

N Strahl
  • 75
  • 8
  • What makes you think this is not allowed in C++? – Sneftel Oct 20 '20 at 07:51
  • What do you mean by "[t]his is no longer allowed in c++"? The `#include` directive basically insert the raw contents of the included file at the point of the directive. Unless you have some invalid code in the `friend.h` file it's fine (although maybe not something I would recommend). – Some programmer dude Oct 20 '20 at 07:52
  • I get error C2255: 'friend': not allowed outside of a class definition in friend.h (invalid specifier outside class definition) I am compiling with c++17 btw. – N Strahl Oct 20 '20 at 07:58
  • 1
    how do you compile it? Do you include `friend.h` also in other places? The code you posted looks ok – 463035818_is_not_an_ai Oct 20 '20 at 08:02
  • btw I would strongly recommend not to use such construct. friends bypasses encapsulation and should be used sparingly. If you consider all interdependencies you basically have one big monster class made up from `f1`,`f2`,... `Class1`,`Class2`... – 463035818_is_not_an_ai Oct 20 '20 at 08:05
  • Now is a good time to [edit] your question to show us a proper [mcve]. And copy-paste the *full* and *complete* error output into the question itself, as well as adding comments in the code where you get the errors. – Some programmer dude Oct 20 '20 at 08:07
  • @Someprogrammerdude updated the question, it's basically still the same problem. – N Strahl Oct 20 '20 at 08:45
  • 1
    Perhaps it's a `#pragma once` problem? That will inhibit multiple inclusion in a single translation unit. What happens if you remove it from `IncludeFriends.h`? It would also be nice to see `friendsTest.cpp`. – Some programmer dude Oct 20 '20 at 08:48
  • I uncommented it and the problem will not go away. friendsTest.cpp prints out a hello world statement. But the problem starts way earlier at IncludeFriends.h – N Strahl Oct 20 '20 at 09:19
  • 1
    Friendship works the other way around. If you make someone your friend, you let *them* touch *your* private parts. – n. m. could be an AI Oct 20 '20 at 09:44

3 Answers3

0

Following the suggestion from @n. 'pronouns' m. I moved the #include "IncludeFriends.h" statements into the Friend1 and Friend2 class definitions. Note, however, and this is very contradictive behaviour, that my editor still highlights the E0239 error and displays it on the error window. The project does compile successfully though.

N Strahl
  • 75
  • 8
  • E0239 is not a compiler error that the Microsoft C++ compiler produces, it must be some other tool. If you are worried about it, open a separate question. I would suggest you do **not** put your friend declarations in a header file. It is confusing and error-prone. Put them directly in classes that need them. – n. m. could be an AI Oct 20 '20 at 10:23
0

Preprocessor is just a cut/paste automation tool.

You should be able to tell your compiler to stop after pre-processing phase, or write preprocessed files to the disk (g++ -E, Visual C++, etc.), open preprocessed sources in a text editor and you will see what exactly is being compiled. I am sure you will spot the problem right away.

This is the only correct course of action here - own your build or it will own you.

Also, you should remove #pragma once from the includeFriends.h, it makes no sense in there, even if it's not the only cause of your problems.

bobah
  • 18,364
  • 2
  • 37
  • 70
0

A better way to solve this error is to use a macro. As shown below:

#define FRIENDS \
    friend class Friend1; \
    friend class Friend2;

and then replacing #include "IncludeFriends.h" with FRIENDS inside of the class declaration.

N Strahl
  • 75
  • 8