Since the implementation of the doing method can perform both writing and reading, passing a reference to std::ofstream not suitable. The standard library provides the std::fstream class, which is a merge of std::ifstream and std::ofstream , what you need.
Further, the semantics of the doing methods (from Writer -a):
a.write((char*)&it, sizeof(it));
This code does not do what you expect. You take the iterator address it , which has nothing to do with the data pointed to by the iterator. It is necessary to record not the address of the iterator, but the data it stores.
The iterator is fine, but you need to work with the sequence. An iterator must be passed to the beginning and end of the sequence.
Because std::fstream works with both input streams and output streams; you need to explicitly specify for what purpose the stream opens: for input ( std::ios::in ) or for output ( std::ios::out ).
Base *arr[]{ &Writer(),&Reader() };
In this segment of the code: an object of type Writer (everything said also applies to the Reader ). The operation of taking the address is performed, the address is written to the arr array, and then the object whose address we memorized is destroyed. As a result, we get a hanging pointer.
One of the possible correct options:
Writer writer{}; Reader reader{}; Base* arr[] = { &writer, &reader };
Correct implementation:
Base class
class Base { virtual void open(std::fstream &a) = 0; virtual void doing(array<int, 6>::iterator first, // итератор на начало array<int, 6>::iterator last, // итератор на конец std::fstream& stream // ссылка на поток ) = 0; void close(std::fstream &a) { a.close(); } public: // те же изменения void execute(array<int, 6>::iterator first, array<int, 6>::iterator last, std::fstream &a) { open(a); doing(first, last, a); close(a); } };
Writer class
class Writer : public Base { virtual void open(std::fstream &a) override { a.open("FIle.bin", ios::binary | std::ios::out); if (!a) cout << "Error\n"; } virtual void doing(array<int, 6>::iterator first, array<int, 6>::iterator last, std::fstream& stream) override { // проверка на доступность потока // проверка на валидность итераторов for (; first != last; ++first) { // получаем указатель на реальные данные которые хранит итератор const char* pointer_to_data = reinterpret_cast<const char*>(&*first); // записываем эти данные // sizeof(int), sizeof(*first), // sizeof(std::array<int, 6>::value_type) : как угодно stream.write(pointer_to_data, sizeof(*first)); } } };
Reader class
class Reader : public Base { virtual void open(std::fstream &a) override { a.open("FIle.bin", ios::binary | ios::in); if (!a) cout << "Error\n"; } virtual void doing(array<int, 6>::iterator first, array<int, 6>::iterator last, std::fstream& stream) override { // проверка на доступность потока // проверка на валидность итераторов for (; first != last; ++first) { // проверка активен ли поток и может ли быть произведено чтение // получаем указатель на место памяти, куда указывает итератор char* pointer_to_data = reinterpret_cast<char*>(&*first); stream.read(pointer_to_data, sizeof(*first)); } } };
Also, in your example, you first perform a read operation, and then a write operation. Check for one entry can work as follows:
int main() { Reader reader{}; Writer writer{}; std::fstream stream{}; // кстати, достаточно одного потока fstream std::array<int, 6> arr1{ 1, 2, 3, 4, 5, 6 }; std::array<int, 6> arr2; std::cout << "arr1 до записи, (arr2 пустой): \n"; for (size_t i = 0; i < 6; ++i) std::cout << arr1[i] << "\t"; std::cout << "\n"; // записываем данные из arr1 writer.execute(arr1.begin(), arr1.end(), stream); // читаем данные в arr2 reader.execute(arr2.begin(), arr2.end(), stream); std::cout << "arr2 после чтения: \n"; for (size_t i = 0; i < 6; ++i) std::cout << arr2[i] << "\t"; std::cout << "\n"; return 0; }
It is worth noting that this solution is very inflexible. In an amicable way, it is first necessary to record the number of elements in the file. But since The solution is (apparently) used for educational purposes, these points can be neglected.
mainfunction, you have a pair of dangling pointers. - acade&Writer()- the object is created, its address is remembered, and the object is destroyed, and the address taken (pointer in thearrarray) will point to an object that no longer exists. - acade