Проблемы с использованием fstream в классе - PullRequest
2 голосов
/ 25 октября 2019

Я получаю следующую ошибку при компиляции:

1>c:\users\ra\source\repos\sandbox\game\gamesetup_1\gamesetup_1\main.cpp(15): error C2280: 'DebugLib::DebugLib(const DebugLib &)': attempting to reference a deleted function
1>c:\users\ra\source\commonincludes\tannic\debuglib\debuglib.h(41): note: compiler has generated 'DebugLib::DebugLib' here
1>c:\users\ra\source\commonincludes\tannic\debuglib\debuglib.h(41): note: 'DebugLib::DebugLib(const DebugLib &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::basic_fstream<char,std::char_traits<char>>::basic_fstream(const std::basic_fstream<char,std::char_traits<char>> &)'
1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.16.27023\include\fstream(1421): note: 'std::basic_fstream<char,std::char_traits<char>>::basic_fstream(const std::basic_fstream<char,std::char_traits<char>> &)': function was explicitly deleted
1>Done building project "GameSetup_1.vcxproj" -- FAILED.

Код выглядит следующим образом:

DebugLib.h:

#include <string>
#include <fstream>

class DebugLib
{
public:
    DebugLib();             // Reset timestamp etc. 
    ~DebugLib();            // Flush output buffer
    void Init(uint8_t output, std::string fileName = "debug.log");  // Initializes Log
    void Log(int category, std::string msg);    // Add a line to the log
    void Flush();           // Output the remains of the Debug buffer
    void Shutdown();        // Shut it down

private:
    unsigned int m_initTime;

    unsigned int m_bufferPos;
    std::string m_outputBuffer[DEBUG_MAXSIZE];

    std::fstream m_fileStream;

    uint8_t m_output;
    bool m_running;
};

main.cpp:

#include <iostream>
#include <DebugLib.h>

using namespace std;

int main()
{
    DebugLib gDebugger = DebugLib();

    gDebugger.Init(DEBUG_LOG_TO_SCREEN);

    cout << "Running!" << endl;
    gDebugger.Shutdown(); 
    cin.get();
    return 0;
}

Как только я объявляю m_fileStream, я получаю сообщение об ошибке. У меня неправильная декларация? Когда я удаляю все использование m_fileStream в DebugLib.cpp, код прекрасно компилируется и запускается (но, конечно, не так, как требуется)

1 Ответ

2 голосов
/ 25 октября 2019

Я не смог найти дубликат, хотя я уже видел этот вопрос, поэтому:

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

'DebugLib::DebugLib(const DebugLib &)': attempting to reference a deleted function

Это главная ошибка: попытка использовать удаленную функцию, а именно конструктор копирования для DebugLib. Поскольку вы не указали явно конструктор копирования, именно компилятор определит его для вас. Компилятор определит наивную копию, если это возможно. Если это определение невозможно, оно удалит для вас конструктор копирования.

Как вы заметили, компилятор может определить простую копию, пока вы не добавите поле, которое не может быть скопировано (например, std::fstream).

note: compiler has generated 'DebugLib::DebugLib' here

Это уточняющее примечание, которое помогает ошибке ссылаться на две строки в вашей программе. Номер строки, который идет вместе с основным сообщением об ошибке, - это место, где вы пытались выполнить копирование, а номер строки, который идет с этим примечанием, - это то, где генерируется конструктор копирования. Компилятор пытается помочь, потому что он не знает, какое местоположение вы хотите изменить, чтобы устранить эту ошибку.

note: 'DebugLib::DebugLib(const DebugLib &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'std::basic_fstream<char,std::char_traits<char>>::basic_fstream(const std::basic_fstream<char,std::char_traits<char>> &)'

В этой заметке объясняется то, что вы заметили: копированиеваш класс запрещен, потому что элемент std::fstream не может быть скопирован. Это сообщение использует имя basic_fstream на данный момент, поэтому полезно знать, что fstream является экземпляром шаблона basic_fstream. Так что этот беспорядок кода в конце этой заметки просто называет конструктор копирования std::fstream.

note: 'std::basic_fstream<char,std::char_traits<char>>::basic_fstream(const std::basic_fstream<char,std::char_traits<char>> &)': function was explicitly deleted

Это дальнейшее пояснение. В строке перед этим говорилось "удалено или недоступно". Эта строка поясняет, что нужно «явно удалить».

Теперь, когда мы прочитали ошибку, мы можем перейти к строкам, на которые она ссылается. Проблемная строка -

  DebugLib gDebugger = DebugLib();

Эта строка требует, чтобы объект DebugLib был построен по умолчанию, а затем скопирован в gDebugger. И есть проблема: это не может быть скопировано! Решение состоит в том, чтобы упростить вашу логику, удалив копию. Вы можете вызвать конструктор по умолчанию непосредственно в gDebugger. (Это работает и для других конструкторов, если они нужны вашему коду.)

    DebugLib gDebugger{};

В качестве бонуса ваш код короче.

...