【问题标题】:Why is my fstream being implicitly deleted?为什么我的 fstream 被隐式删除?
【发布时间】:2012-09-08 02:47:43
【问题描述】:

我正在使用一些 HID 设备,所有这些设备都有派生自以下基类的类(在 main.h 中):

class HIDDevice {
    public:
        hid_device *device;

        virtual void read(std::fstream)=0;
        virtual void write(std::fstream)=0;
};

这是从它派生的设备类之一(device.h):

class MyDevice : public HIDDevice {
    public:
        void read(std::fstream);
        void write(std::fstream);
};

...以及实现示例:

void MyDevice::read(std::fstream file) {
    // Read from card and write to file
    response = send_command(READ_DEVICE);
    file.write((char *)&response[0], response.size());
}

...和调用者:

fstream file (filename, ios::binary | ios::in);
dev->read(file);

当我尝试编译时,我收到以下错误:

main.cpp:294:27:错误:使用已删除的函数‘std::basic_fstream::basic_fstream(const std::basic_fstream&)’
在 source/main.cpp:24:0 包含的文件中: /usr/include/c++/4.6/fstream:761:11: error: ‘std::basic_fstream::basic_fstream(const std::basic_fstream&)’ 被隐式删除,因为默认定义格式不正确:

...我不知道为什么,可能是因为我对 C++ 还很陌生,而且我做了一些愚蠢的事情。

将参数改回引用(使用 &),我收到以下错误:

/main.o:(.rodata._ZTV13MyDevice[vtable for MyDevice]+0x18): undefined reference to `MyDevice::write(std::basic_fstream >&)'

谁能帮我解决这个问题?

【问题讨论】:

  • 顺便说一句,我不知道如何更正它,但问题标题很糟糕:它不是被删除的流对象,“隐式删除”是指this的隐式版本.
  • @Jon:也许我们应该保持原样,以防其他人使用类似的搜索词?不过别问我,我几乎不是 C++ 专家。
  • “关闭”而不是“删除”?甚至更好; “双关”。在这和我认为你的问题主体之间。

标签: c++ class inheritance fstream


【解决方案1】:

尝试通过引用折腾那些std::fstreams。

class MyDevice : public HIDDevice {
    public:
        void read(std::fstream&);
        void write(std::fstream&);
};

【讨论】:

  • 这是我尝试的第一件事,它给了我另一个错误:/main.o:(.rodata._ZTV13MyDevice[vtable for MyDevice]+0x18): undefined reference to `MyDevice: :write(std::basic_fstream >&)'
  • @AndyE:这是一个链接器错误,您是否定义了void MyDevice::write 并添加了&?
  • 哦,我定义了read,但没有定义write。这就是为什么你不应该在晚上 10 点之后编码。
  • 拯救了我的一天。我不知道忘记通过引用传递
【解决方案2】:

仅供参考,我遇到了相同的编译器错误,但以不同的方式创建它,这对我来说并不是很明显。出于习惯,我写道:

auto stream = fstream(output, iOS::out | iOS::binary);

当然,这会创建一个临时 fstream 对象并将其复制到流中。这在 Xcode 6 中使用 clang 有效,但不适用于 GCC 4.9.2。

【讨论】:

    【解决方案3】:

    HIDDevice 方法签名意味着fstreams 是按值传递的。这反过来意味着必须在调用站点使用复制构造函数创建原始流对象的副本。正是这个复制构造函数具有规范签名std::basic_fstream::basic_fstream(const std::basic_fstream&)。

    编译器告诉你,由于某种原因(这与你的标准库使用的basic_fstream 实现的细节有关)它不能自动生成这个复制构造函数,因此它不能完成你的隐式命令来制作副本流。

    正如其他人已经说过的,通常的操作方式(这也将防止此处的错误)是通过引用而不是通过值传递参数。

    【讨论】:

    • @AndyE:看起来头文件和实现文件中的方法签名不匹配,或者您忘记定义已声明的方法。
    【解决方案4】:

    &std::fstream 作为参数将通过引用传递它,以便在任何地方用作同一个对象。这避免了实现尝试创建另一个实例,然后在函数结束时关闭流(因为复制的对象正在被破坏)。

    确保在成员函数的声明和实现中都进行了更改(即在类中和主体所在的位置)。

    【讨论】:

      猜你喜欢
      • 2015-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-05
      • 2017-05-22
      • 1970-01-01
      • 2023-01-14
      相关资源
      最近更新 更多