11

我正在使用一些 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&)'<br> 在源/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 >&)'

谁能帮我解决这个问题?

4

4 回答 4

21

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

class MyDevice : public HIDDevice {
    public:
        void read(std::fstream&);
        void write(std::fstream&);
};
于 2012-09-14T22:50:48.553 回答
5

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

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

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

于 2015-07-13T14:49:35.473 回答
3

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

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

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

于 2012-09-14T22:55:09.413 回答
1

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

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

于 2012-09-14T22:51:18.783 回答