c++inheritancebinaryoutputfstream

How is this implementation of inheritance of C++ fstream for convienient binary output causing failure opening the file?


Code outputs, "file not open."

union converter_t {
  char byte[4];
  short int word[2];
  int dword[1];
} converter;

class enhancedfstream: public fstream {
  public:
    enhancedfstream(string s, _Ios_Openmode iosom) {
     fstream(s, iosom);
    }
    void write(int i) {
      converter.dword[0] = i;
      fstream::write(converter.byte, 4);
    }
    void write(short int si) {
      converter.word[0] = si;
      fstream::write(converter.byte, 2);
    }
    void write(string s) {
      char* tca = &s[0];
      fstream::write(tca, s.length());
    }
    void write(char c) {
      // intended correction:
      converter.byte[0] = c;
      fstream::write(converter.byte, 1);
      // as original, before correction:
      // fstream::write(new char[1] {c}, 1);
    }
    void write(char* cp, int i) {
      fstream::write(cp, i);
    }
};

  enhancedfstream fs(fn, fstream::out | fstream::binary | fstream::trunc);
  if (fs.is_open()) {} else cout << "file not open\n";

Linux filesystem review from shell shows empty file creation succeeds, but programatically, the file appears as unopened and subsequent writes are of no effect. Compilation and execution are done as root within a subdirectory of the root directory. Compiled with emulated g++ (Alpine 10.3.1_git20210424) 10.3.1 20210424 (C++14) (copyright 2020) in ipadOs iSH 1.3.2 (build 494).

Is the inheritance as implemented above done improperly, or is fstream peculiar in how it can successfully be subclassed? Is a buffer setup going unattended to? Standard reported fstream opening failure causes seem to be absent, unless a null buffer is causing the opening failure. Non-subclassed fstream with the same specs opens fine.


Solution

  • You construct a temporary fstream in your constructor. That temporary fstream is closed at the end of the full expression.

    fstream(s, iosom); // opened and closed immediately
    

    Also, _Ios_Openmode is an internal implementation specific type. Do not use those.

    Use the member initializer list to initialize the base class:

    enhancedfstream(const std::string& s, std::ios_base::openmode iosom)
        : std::fstream(s, iosom) // now opened correctly
    {
        // empty constructor body
    }
    

    Demo


    Sidenote:s