Должна ли функция друга быть в одном файле?

Я на самом деле тестирую файл, и у меня возникает ситуация, когда мне нужно получить доступ к некоторым защищенным членам класса из main.cpp. Я пытался добавить, main() как друг, не получилось и узнал, что это не будет работать, поэтому я переместил все в main() к test () и сделал test() как друг. все же это показывает ошибку.

Пример будет

 //--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;
  }

// в строке 34 говорится об ошибке: Base::value защищено. Пожалуйста посоветуй.

    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

4 ответа

Решение

Нет, он определенно не обязательно должен находиться в том же файле, но он, очевидно, должен "знать", что такое класс, то есть: заголовок, который имеет определение класса, должен быть включен в файл, в котором реализована функция. Ваш код должен быть в порядке, как прокомментировано.

после того, как вы добавили некоторый контекст

Ваш test функция не в Files Пространство имен. Если вы хотите, чтобы это было в глобальном контексте, вы должны рассматривать это как "::test"внутри пространства имен, иначе компилятор может ожидать"Files::test"быть другом, а не функцией"::test"как в вашем случае. Не могу найти формальную стандартную ссылку, но я почти уверен, что это так. Обратите внимание, что вы выполняете предварительное объявление здесь, поэтому по умолчанию нет возврата к верхнему уровню области действия для разрешение имен.

Может быть, вы пропустили декларацию наследования в производном классе?

 class Derived : public Base {

Я проверил ваш код (с включенным объявлением наследования), и он не выдал ошибку

Литтедев прав!! Обновлен код в соответствии с комментариями Литтедев..

//--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    

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

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

Я предполагаю, что вы пытаетесь получить доступ к защищенной переменной вне области определения класса Files. Я бы порекомендовал функцию, которая возвращает переменное слово при его вызове, и использовал бы ее вместо попытки доступа к защищенной переменной вне определения класса. Я могу ошибаться в том, что я не совсем уверен, какова область действия защищенной переменной (независимо от того, ограничена ли она только объявлениями класса или доступ к ней возможен вне определения класса), но я почти уверен, что я прав, потому что защищенные переменные похожи на частные переменные. Они доступны только в пределах класса. Поправь меня, если я ошибаюсь.

РЕДАКТИРОВАТЬ: О, мне жаль, я не понял, что ты делал. littleadv прав, ваше объявление функции не находится в пространстве имен файлов.

Другие вопросы по тегам