Search code examples
c++inheritancefriendprotectedaccess-specifier

Does the friend function have to be in the same file?


I am actually testing a file and I have a situation, where I need to access some of the protected members of the class from main.cpp. I tried to add, main() as friend, didn't work out and learned that it wont work, so I moved everything in the main() to a test () and made the test() as friend. still it shows the error.

Example would be

 //--File.hpp

 namespace Files {

 class File {
          public:
                File(long word_):word(word_) {}
          protected:
                long word;
          private:
                friend int test();
 };
 }//ns:Files


 //--List_File.hpp

 namespace Files {
 class List_File :public File {
         public:
               List_File() : File(sizeof(int) + sizeof(long)) {}
         private:
              friend int test();
 };  
 }//ns:Files 



//--main.cpp

  using namespace Files;

  int test() {

       File *pd = new List_File();
       assert(pd->word == 12); //LINE 34
       return 0;
  }

  int main() {
       test();
       return 0;
  }

//it says error on Line 34: Base::value is protected. Please advice.

    g++ -O -Wall -Wno-unused -o a.out File.cpp List_File.cpp Data_File.cpp               
    Free_List_File.cpp main.cpp
    File.hpp: In function ‘int test()’:
    File.hpp:30:7: error: ‘long int Files::File::word’ is protected
    main.cpp:34:16: error: within this context
    make: *** [a.out] Error 1

Solution

  • No, it definitely doesn't have to be in the same file, but it obviously has to "know" what the class is, i.e.: the header that has the class definition should be included in the file where the function is implemented. Your code should be fine, as commented.

    after you added some context

    Your test function is not in the Files namespace. If you want it to be in the global context, you should treat it as "::test" within the namespace, otherwise the compiler might expect the "Files::test" to be the friend function, and not the "::test" as in your case. Can't find the formal standard reference, but I'm pretty sure that's the case. Note that you're performing a forward declaration here, so there's no default fall-back to the upper level of scope for name resolution.