Общий доступ к файлу между потоком и моим основным

#c #c 11 #fstream

#c #c 11 #fstream

Вопрос:

У меня есть файл, который я хочу объявить в главном, но изменить в потоке.

Я объявляю в своем MainWindow заголовочном файле std::ofstream file; .

Затем я пытаюсь инициализировать его своим конструктором my MainWindow.cpp следующим образом : file("test.txt", std::ios::out | std::ios::trunc);

Функция в потоке статична:

     MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);

        // Constructs the new thread and runs it. Does not block execution.

        ref_bool_Server = true;
        fichier ("test.txt", std::ios::out | std::ios::trunc);
        m_t1 = std::thread(lancerServeur, std::ref(ref_bool_Server), std::ref(lancerEnregistrement));

        // Je sauvegarde ma main window
        m_psMainWindow = this;

    }

    MainWindow::~MainWindow()
    {
        delete ui;
        ref_bool_Server = false;
        m_t1.join();
    }


        void MainWindow::lancerServeur(std::atomic<bool>amp; boolServer, std::atomic<bool>amp; lancerEnregistrement){
            serveur s;//J'instancie un serveur
            StructureSupervision::T_StructureSupervision* bufferStructureRecu;
        while(boolServer){
            bufferStructureRecu = s.receiveDataUDP();
            if(bufferStructureRecu != NULL){
               m_psMainWindow->emit_signal_TrameRecu( bufferStructureRecu );
            }
            if(lancerEnregistrement){
                fichier << bufferStructureRecu->SystemData._statutGroundFlight;
            }
        }

    }
  

Определение ofstream равно false (вероятно, synthaxic), и я не знаю, как использовать этот файл в статической функции.

Комментарии:

1. Не могли бы вы подкинуть нам какой-нибудь код?

2. вы имеете в виду file.open (те же аргументы)? Я думаю, что конструктор принимает только буфер файла, а не те же аргументы, что и file.open

3. @Mayerz Я даю вам все, что есть, там всего 2 строки…

4. Где вы объявляете (или определяете) file объект? В глобальном пространстве имен, другом пространстве имен или как член класса?

5. static std::ofstream file; amp;amp; file = std::ofstream ("test.txt", std::ios::out | std::ios::trunc);

Ответ №1:

Технически говоря, вы не можете вызвать конструктор, по крайней мере, не в том смысле, который вы имеете в виду. (Такое выражение, как std::ofstream( "test.txt" ) выглядит так, как будто вы вызываете конструктор, но стандарт называет это явным преобразованием типов.) Конструктор вызывается, когда вы определяете переменную, например, в инструкции std::ofstream file; (которая вызывает конструктор по умолчанию). Когда вы пишете file(...) , компилятор ищет перегруженный operator() тип file ; его нет, так что это ошибка.

Неясно, что вы на самом деле хотите сделать, поэтому трудно дать точный совет. Однако одно можно сказать наверняка: вам не нужно определение переменной (например, std::ofstream file; в области пространства имен) в заголовке. Если вы это сделаете, этот заголовок может быть включен только в один источник, иначе в итоге вы получите несколько определений. (Такое определение было бы разумным в определении класса в заголовке.) В лучшем случае вы хотели бы, extern std::ofstream file; чтобы в заголовке было указано определение в одном (и только одном) из исходных файлов, которые включают этот заголовок; в определении вы можете указать аргументы, которые будут использоваться для построения. За исключением того, что я не могу придумать контекст, в котором имело бы смысл иметь std::ofstream область пространства имен at.

Редактировать:

Из вашего обновления вопроса, из сообщения об ошибке, похоже, что file это переменная-член. В этом случае вы предоставляете конструктору любые аргументы в списке инициализаторов конструктора:

 MainWindow::MainWindow()
    : file( "test.txt" )
{
}
  

И, конечно, если это участник, вы не сможете получить к нему доступ без
наличие экземпляра класса. Обычно это не так
в статической функции-члене.

Редактировать:

После вашего обновления: все еще не ясно, хотите fichier ли вы быть статическим участником или нет. Обычно будет только один MainWindow объект; имеют ли к нему доступ оба пользователя? (Обычно это было бы предпочтительным решением.) Если это так, нет проблем с тем, чтобы сделать его нестатическим и инициализировать его, как указано выше. Или вы могли бы передать ссылку на него ( fichier элемент) непосредственно в поток. Это решение, которое я бы предпочел. В качестве альтернативы, вы могли бы объявить его статическим. В этом случае вам нужно будет явно определить его в одном и только одном исходном файле:

 std::ofstream MainWindow::fichier;
  

И затем вы бы открыли его в конструкторе:

 fichier.open( "test.txt" );
  

Однако это может вызвать проблемы, если несколько экземпляров
MainWindow создается.

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

Комментарии:

1. Я обновлю свой пост, чтобы предоставить больше информации, спасибо за вашу помощь.

2. Существует только 1 экземпляр MainWindow, мне нужно объявить свой файл в моем главном, а не локальном на моем сервере, потому что в деструкторе моего основного я хочу удалить файл, если в нем ничего не записано. Я попытаюсь передать экземпляр моего файла таким образом…

3. @EvansBelloeil Все, что вы делаете после объединения, вы могли бы сделать в основной функции потока. Но для удаления не требуется ofstream только имя, поэтому вы все равно можете удалить после объединения в главном потоке, даже если ofstream объект был в потоке. (Если вы используете Windows, конечно, вам нужно убедиться, что файл закрыт перед удалением.)