#include <string>
#include <iostream>
#include <fstream>


using namespace std;

//NVI - klasa bazowa
class SafeOut {
public:
    SafeOut(std::ostream& out) : out_(out) {}
 virtual ~SafeOut() = default;
 void store(const std::string& s) {
     if(!s.empty() && out_.good() ) {
         out_ << s << std::flush;
     }
 }
private:
 std::ostream& out_;
};

class FileOut : public SafeOut {
public:
 FileOut(const std::string& filename) : SafeOut(file_), file_(filename) { }
 ~FileOut() { file_.close(); }
private:
 std::ofstream file_;
};

class StdOut : public SafeOut {
public:
    StdOut() : SafeOut(std::cout) {}

};


// class SafeOut {
// public:
//     SafeOut(std::ostream& out) : out_(out) {}
//     virtual ~SafeOut() = default;
//     virtual void store(const std::string& s) = 0;
// private:
//     std::ostream& out_;
// };

// class FileOut : public SafeOut {
// public:
//     FileOut(const std::string& filename) : SafeOut(file_), file_(filename) { }
//     ~FileOut() { file_.close(); }

//     void store(const std::string& s) override {
//         if(!s.empty() && file_.good() ) {
//             file_ << s << std::flush;
//         }
//     }
// private:
//     std::ofstream file_;
// };

// class StdOut : public SafeOut {
// public:
//     StdOut() : SafeOut(std::cout) {}

//     void store(const std::string& s) override {
//         if(!s.empty() && cout.good() ) {
//             cout << s << std::flush;
//         }
//     }
// };



int main() {
    FileOut out1("filename.txt");
    StdOut out2;

    out1.store("hello");
    out2.store("hello\n");
    return 0;
}
