Viku
Viku

Reputation: 2973

confused with friend function

Inside FileTwo.h

#ifndef FILETWO
#define FILETWO
#include"FileOne.h"
class FileOne ;
class FileTwo
{
public:
    int Test(FileOne One){
        return (One.var1+One.var2);}

    FileTwo(void);
    ~FileTwo(void);
};
#endif

Inside FileOne.h

#ifndef FILEONE
#define FILEONE
#include"FileTwo.h"
class FileTwo ;
class FileOne
{
private:
     int var1 , var2 , var3 ;
public :
    friend int FileTwo::Test(FileOne One);
    FileOne(){
        var1= 12;var2 = 24;
    }

};
#endif

Inside main.cpp

#include<iostream>
using namespace std ;
#include"FileOne.h"
#include"FileTwo.h"

int main(){
FileOne one ;
FileTo two ;
cout<<two.Test(one);
}

During compilation i got the following error

   1-- error C2027: use of undefined type 'FileOne' c:\users\e543925\documents\visual studio 2005\projects\myproject\filetwo.h
   2--error C2027: use of undefined type 'FileOne'  c:\users\e543925\documents\visual studio 2005\projects\myproject\filetwo.h  

   3--error C2228: left of '.var1' must have class/struct/union c:\users\e543925\documents\visual studio 2005\projects\myproject\filetwo.h
   4--error C2228: left of '.var2' must have class/struct/union c:\users\e543925\documents\visual studio 2005\projects\myproject\filetwo.h

I have found one workaround like definning the Test function inside FileTwo.cpp . But i want to know how the above issue can be resolved inside header file .

Upvotes: 2

Views: 618

Answers (4)

billz
billz

Reputation: 45410

Your friend declaration is fine, the issue you are having is circular include. You could break the circular include by putting one of class implementation into cpp file.

For example, break FileTwo class into FileTwo.h and FileTwo.cpp should fix your issue. Or, declare friend FileTwo; then one forward declaration is enough:

FileOne.h

#ifndef FILEONE
#define FILEONE

class FileTwo;
class FileOne
{
private:
     int var1 , var2 , var3 ;
public :
    friend FileTwo;
    FileOne(){
        var1= 12;var2 = 24;
    }

};
#endif

FileTwo.h

#ifndef FILETWO
#define FILETWO

#include "FileOne.h"
class FileTwo
{
public:
   inline int Test(FileOne One)
    {
      return (One.var1+One.var2);
    }

    FileTwo(void){}
    ~FileTwo(void){}
};
#endif

Upvotes: 1

Gorpik
Gorpik

Reputation: 11028

Your problem here is that you are including both files in each other. When your compiler goes to parse FileOne.h, it includes FileTwo.h, so it reads that, skips FileOne.h (thanks to the include guards; otherwise, you would go into an infinite loop) and tries to use class FileOne, which is not yet defined.

In practice, this is just as if you had not included FileOne.h in FileTwo.h; you cannot call methods on One because its type (FileOne) is not yet defined. Nothing to do with friend classes. Or not yet (you will get into this problem later).

From your code, it looks like you want to use class FileTwo to test FileOne. In this case, FileOne does not really need to know much about FileTwo, just allow it to look at its innards (aka make it a friend). So your code can boil down to:

FileOne.h:

#ifndef FILEONE
#define FILEONE
class FileOne
{
  friend class FileTwo; // This is all FileOne needs from FileTwo
private:
  int var1 , var2 , var3 ;
public :
  FileOne(){
    var1= 12;var2 = 24;
  }
};
#endif

FileTwo.h:

#ifndef FILETWO
#define FILETWO
#include"FileOne.h"
class FileTwo
{
public:
  int Test(FileOne One) {
    return (One.var1+One.var2);
  }

  FileTwo();
  ~FileTwo();
};
#endif

Upvotes: 2

Andrei Tita
Andrei Tita

Reputation: 1236

What you have is a circular dependency, which is solvable by using incomplete type declarations. As it stands, your code requires complete type declaration in both files:

1) in FileOne.h: friend int FileTwo::Test(FileOne One); (you're asking the compiler to find a member function of FileTwo)

2) in FileTwo.h: int Test(FileOne One){ return (One.var1+One.var2);} (you're asking the compiler to find some member variables of FileOne)

You have to use an incomplete type declaration in at least one of the files (class FileOne; class FileTwo;). You are already trying to do it, but using the #include directives undermines that. You have two options:

One is to make FileTwo a friend of FileOne as a whole class, as that is allowed by using an incomplete type. Remove #include "FileTwo.h".

The other one you have already found by yourself:

I have found one workaround like definning the Test function inside FileTwo.cpp.

Remove #include "FileOne.h" from FileTwo.h in that case.

Upvotes: 1

You don't need to include FileOne.h inside FileTwo.h, at least in this simple example. But in general, a circular include implies there is something wrong with your design.

You'll have to make the whole class a friend, not just a single method. I'd reconsider this friendship as well, since this introduces major coupling between the classes. Can you not accomplish the same with public methods?

Upvotes: 1

Related Questions