【问题标题】:Passing std::ofstream object as argument to class method将 std::ofstream 对象作为参数传递给类方法
【发布时间】:2019-11-27 07:19:27
【问题描述】:

正如前面的问题已经回答,将std::ofstream 对象作为函数参数传递的方法似乎是传递一个引用:std::ofstream&

虽然此解决方案可以编译,但生成的输出并不等同于在方法中创建 std::ofstream 对象然后调用 write()。

下面的代码没有给出正确的输出:

ma​​in.cpp中:

std::ofstream file(path + "output.stubs");
stub->writeRaw(file); //stub is a pointer to an object of class Stub
file.close();

Stub.cpp 中:

void Stub::writeRaw(std::ofstream& file) {
    file.write((char*)this, sizeof(*this));
}

正确的输出是通过将 Stub.cpp 更改为:

void Stub::writeRaw(void) {
    std::ofstream file(path + "output.stubs");
    file.write((char*)this, sizeof(*this));
    file.close();
}

或将对象写入 main 中的文件,而不是调用类方法。

任何有关此行为的帮助将不胜感激!

编辑

类 Stub 的一些上下文:

Stub.hpp

#pragma once

#include <iostream>
#include <ios>
#include <fstream>

#include "constants.hpp"
#include "DataTypes.hpp"


class Stub {
private:
    StubHeader header;
    StubIntrinsicCoordinates intrinsic;
    StubPayload payload;

public:
    Stub(void);
    virtual ~Stub(void);

    StubHeader getHeader(void);
    StubIntrinsicCoordinates getIntrinsicCoordinates(void);
    StubPayload getPayload(void);

    void setHeader(StubHeader stub_header);
    void setIntrinsicCoordinates(StubIntrinsicCoordinates stub_intrinsic);
    void setPayload(StubPayload stub_payload);

    void print(void);
    void writeRaw(std::ofstream& file);
};

相关数据类型定义如下:

struct StubHeader {
    uint8_t bx;
    uint8_t nonant;
};

struct StubIntrinsicCoordinates {
    uint8_t strip;
    uint8_t column;
    int crossterm;
};

struct StubPayload {
    bool valid;
    int r;
    int z;
    int phi;
    int8_t alpha;
    int8_t bend;
    uint8_t layer;
    bool barrel;
    bool module;
};

编辑 2

读取存根的(玩具)代码如下:

std::ifstream r(path + "output.stubs");
Stub s;
r.read((char*)&s, sizeof(s));
s.print();

只有一个存根写入文件,因为这是对功能的测试。 Stub类的打印函数如下:

void Stub::print(void) {
    std::cout << "----- Header -----" << '\n';
    std::cout << "bx: " << std::dec << (int)header.bx << '\n';
    std::cout << "nonant: " << std::dec << (int)header.nonant << '\n';
    std::cout << "----- Intrinsic Coordinates -----" << '\n';
    std::cout << "strip: " << std::dec << (int)intrinsic.strip << '\n';
    std::cout << "column: " << std::dec << (int)intrinsic.column << '\n';
    std::cout << "crossterm: " << std::dec << (int)intrinsic.crossterm << '\n';
    std::cout << "----- Payload -----" << '\n';
    std::cout << "valid: " << std::boolalpha << payload.valid << '\n';
    std::cout << "r: " << std::dec << (int)payload.r << '\n';
    std::cout << "z: " << std::dec << (int)payload.z << '\n';
    std::cout << "phi: " << std::dec << (int)payload.phi << '\n';
    std::cout << "alpha: " << std::dec << (int)payload.alpha << '\n';
    std::cout << "bend: " << std::dec << (int)payload.bend << '\n';
    std::cout << "layer: " << std::dec << (int)payload.layer << '\n';
    std::cout << "barrel: " << std::boolalpha << payload.barrel << '\n';
    std::cout << "module: " << std::boolalpha << payload.module << "\n\n";
}

编辑 3

为了完整和透明,请在下面找到 ma​​in.cpp 的确切代码:

int main(int argc, char const *argv[]) {
    Geometry g;
    g.generateModuleLUTs();
    g.generateCorrectionLUTs();
    std::vector<std::array<Stub*, PAYLOAD_WIDTH> > all_stubs;
    std::vector<Module> modules = g.getData(); 
    for (int i = 0; i < LINK_NUMBER; i++) {
        LinkGenerator link_gen;
        LinkFormatter link_formatter(link_gen.run());
        StubFormatter stub_formatter(link_formatter.run(), i);
        std::array<Stub*, PAYLOAD_WIDTH> stubs = stub_formatter.run(modules);
        CoordinateCorrector coordinate_corrector(stubs);
        all_stubs.push_back(coordinate_corrector.run());
    }
    std::ofstream f(path + "output.stubs");
    all_stubs[0][0]->writeRaw(f);
    all_stubs[0][0]->print();
    std::ifstream r(path + "output.stubs");
    Stub s;
    r.read((char*)&s, sizeof(s));
    s.print();
    return 0;
}

【问题讨论】:

  • 在什么意义上输出不正确?
  • 嗨,你有什么预期的输出?
  • 这没有意义。您是否有可能一开始就不应该像这样进行序列化,因此会遇到未定义的行为? this的内容是什么?提交minimal reproducible example。我们已经可以看到这不是您的真实代码,因为您缺少 ;,因此代码无法编译。
  • 抱歉,仍然不是我们可以用来复制的minimal reproducible example。但您可以放心,传递对 std::ofstream 的引用不会改变 std::ofstream 的行为。
  • 再一次,这不是 C++ 的工作方式,所以你在某处有未定义的行为,应该专注于定位它。例如你如何观察这种行为?我们看不到阅读代码。

标签: c++ ofstream


【解决方案1】:

代码中的错误是我在构造std::ifstream 对象以再次读取文件之前没有调用file.close()。这是意外行为的原因。

使用this 将类写入文件似乎是有效的,但重要的是要小心并确切地知道要写入文件的内容。

感谢所有评论并帮助回答这个问题的人!

【讨论】:

  • 我会接受这个作为答案。
  • 重申一下,您的代码安全,因为您使用虚拟成员函数对某些内容进行字节序列化,并且由于填充和字节序,您的结果无法移植,并且由于以文本模式打开文件,否则您的结果很容易出错。
猜你喜欢
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
相关资源
最近更新 更多