是什么导致 fstream::open 在这里失败?

What is causing fstream::open to fail here?

问题

我正在 Win32 C++ 中开发一个简单的记事本应用程序。但是我 运行 在打开要保存的文件时遇到了问题。有相当多的代码(您可以找到 here)但是导致错误的行在文件 Event Handlers.cpp.

具体来说,第 25 行

wnd.file.open(wnd.filePath, std::ios_base::out);

抛出异常。这是调试输出:

Exception thrown: read access violation.
this->**_Ptr** was nullptr.

尽管 _Ptr 并不总是值 nullptr


我试过的

这就是问题的要点。现在这是我到目前为止尝试过的方法。


我的理论

但是,我认为问题出在我的代码设计和 std::fstream class。

Main.cpp 中的第 34 行:

mainWnd = TopLevelWnd(wr.left, wr.right, wr.left, wr.top, 1280, 720, wr.right - wr.left,
   wr.bottom - wr.top, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
   0, L"Main Window Class", L"Main Window", hInstance);

构造一个TopLevelWnd,然后复制到全局向量windows中默认构造的TopLevelWnd。据我所知,class std::fstream 已删除其复制成员,无法复制。这应该会产生编译器错误,因为它是 TopLevelWnd 的成员,但它不会。无论如何,我决定删除 TopLevelWnd 的复制成员并编写移动构造函数和移动赋值运算符函数并使用 std::move:

显式调用它们
    // delete copy members because fstream cannot be copied
    TopLevelWnd& operator=(const TopLevelWnd&) = delete;
    TopLevelWnd(const TopLevelWnd&) = delete;
    
    // move members
    TopLevelWnd(TopLevelWnd&& source)
        : Wnd(std::move(source)),
        file(std::move(source.file))
    {}
    TopLevelWnd& operator=(TopLevelWnd&& right)
    {
        Wnd::operator=(std::move(right));
        file = std::move(right.file);
        return *this;
    }

这也没有解决问题,所以我完全不知所措。有人可以帮我理解吗?

P.S。顺便说一句,要重现问题,您只需 运行 程序,然后在菜单中转到文件 -> 保存并选择一个文件来保存。

经过大量的挖掘和试验,我终于找到了答案。问题出在 TopLevelWnd 构造函数中。

TopLevelWnd(int x, int y, int ncX, int ncY, int width, int height, int ncWidth, int ncHeight, DWORD styles, DWORD exStyles, const wchar_t* className, const wchar_t* name, HINSTANCE hInstance = GetModuleHandleW(nullptr), HWND hWnd = nullptr, HWND hWndParent = nullptr, HMENU hMenu = nullptr)
        : Wnd(x, y, ncX, ncY, width, height, ncWidth, ncHeight, styles, exStyles, className, name, hInstance ,hWnd, hWndParent),
        hMenu(hMenu)

它有两个参数,名为 hWndhMenu。 class 还有两个数据成员 hWndhMenu。在正文中,我写的行如下:

hWnd = CreateWindowExW(...);
hMenu = CreateMenu();

当我需要写作时

this->hWnd = CreateWindowExW(...)
this->hMenu = CreateMenu();