ОБЪЕКТНО-ОРИЕНТИРОВАННОЕ ПРОГРАММИРОВАНИЕ В C++ (4-Е ИЗДАНИЕ) (часть 12) онлайн
Как объекты записывают и читают сами себя
Иногда имеет смысл разрешить каждому компоненту класса читать и записы- вать самого себя. Это довольно прозрачный подход и отлично работает, если нужно писать и читать небольшое число объектов. В нашем примере мы добави- ли два метода — diskOut() и diskIn() — в класс person. Эти функции позволяют объектам person записывать себя в файл и читать себя же из него.
Примем некоторые упрощающие допущения. Во-первых, все объекты будут храниться в одном и том же файле PERSFILE.DAT. Во-вторых, новые объекты всег- да будут добавляться к концу файла. Аргумент функции diskIn() позволяет читать данные о любом человеке из файла. Для предотвращения попыток прочитать данные, выходящие за пределы файла, мы включаем в программу статический метод diskCount(), возвращающий число людей, информация о которых хранится в файле. При вводе данных следует использовать только фамилии людей, про- белы не допускаются.
Листинг 12.16. Программа REWOBJ
// rewobj.cpp
// Файловый ввод/вывод объектов person
#include <fstream> // Для файловых потоков
#include <iostream>
using namespace std;
///////////////////////////////////////////////////////////
class person // класс person
{
protected:
char name[40]; // имя человека
int age; // его возраст
public:
void getData(void) // получить данные
{
cout << "\n Введите фамилию: "; cin >> name;
cout << " Введите возраст: "; cin >> age;
}
void showData(void) // Вывод данных
{
cout << "\n Имя: " << name;
cout << "\n Возраст: " << age;
}
void diskIn(int); // чтение из файла
void diskOut(); // запись в файл
static int diskCount(); // Число человек в файле
};
//---------------------------------------------------------
void person::diskIn(int pn) // Чтение данных о числе
// человек pn из файла
{
ifstream infile; // создать поток
infile.open("PERSFILE.DAT", ios::binary); // открыть его
infile.seekg( pn*sizeof(person) ); // сдвиг
// файлового указателя
infile.read( (char*)this, sizeof(*this) ); // чтение данных
// об одном человеке
}
//---------------------------------------------------------
void person::diskOut() // запись в конец файла
{
ofstream outfile; // создать поток
// открыть его
outfile.open("PERSFILE.DAT", ios::app | ios::binary);
outfile.write((char*)this,sizeof(*this)); //записать в него
}
//---------------------------------------------------------
int person::diskCount() // число людей в файле
{
ifstream infile;
infile.open("PERSFILE.DAT", ios::binary);
infile.seekg(0, ios::end); // перейти на позицию «0 байт
// от конца файла»
// вычислить количество людей
return (int)infile.tellg() / sizeof(person);
}
///////////////////////////////////////////////////////////
int main()
{
person p; // создать пустую запись
char ch;
do { // сохранение данных на диск
cout << "Введите данные о человеке: ";
p.getData(); // Получить данные
p.diskOut(); // записать на диск
cout << "Продолжить (y/n)? ";
cin >> ch;
} while(ch=='y'); // цикл до 'n'
int n = person::diskCount(); // сколько людей в файле?
cout << "В файле " << n << " человек(а)\n";
for(int j=0; j<n; j++) // для каждого
{
cout << "\nПерсона " << j;
p.diskIn(j); // считать с диска
p.showData(); // вывести данные
Листинг 12.16 (продолжение)
}
cout << endl;
return 0;
}
Здесь для вас не должно быть новых откровений. Большинство элементов этой программы уже встречались. Она работает примерно по тому же принципу, что и DISKFUN. Тем не менее имейте в виду, что все подробности дисковых опе- раций невидимы для main(), они спрятаны внутрь класса person.
Заранее никогда неизвестно, где находятся данные, с которыми мы собираем- ся работать, так как каждый объект находится в своей области памяти. Но указа- тель this всегда подскажет, где мы находимся во время выполнения какого-либо метода. В потоковых функциях read() и write() адрес объекта, который будет читаться или записываться, равен *this, а его размер — sizeof(*this).
Вот результат работы программы при предположении, что до начала ее рабо- ты в файле уже было две записи:
Введите данные о человеке: Введите имя: Гребеньков Введите возраст:19 Продолжить (y/n)? У
Введите данные о человеке: Введите имя: Андреанов Введите возраст:20 Продолжить (y/n)? N
Персона #1 Имя:Ершова Возраст:21 Персона #2 Имя:Малахова Возраст:20 Персона #3 Имя:Гребеньков Возраст:19 Персона #4
Имя:Андреанов
Возраст: 20
Чтобы пользователь мог ввести собственное имя файла, вместо жесткого закре- пления его в программе, как мы делали в предыдущих примерах, следует создать статическую компонентную переменную (например, charfileName[]), а также ста- тическую функцию для ее установки. Можно сделать и по-другому: каждый объ- ект записывать в свой файл. Для этого понадобится нестатическая функция.
12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
Схожі підручники
- Сила воли. Как развить и укрепить (онлайн)
- Фінансовий Ринок терміни
- Стан НПС та основні напрями природоохоронної політики Фінляндії управлінські, організаційні, економічні та юридичні аспекти
- Соціальна психологія (частина 3)
- СЕМІНАРСЬКО-ПРАКТИЧНЕЗАНЯТТЯ з курсу Економіка Підприємства
- Мне тебя обещали (онлайн)