Форум программистов, компьютерный форум CyberForum.ru

Код из "Р.Лафоре. ООП в С++" - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.78
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
07.10.2013, 21:02     Код из "Р.Лафоре. ООП в С++" #1
Р.Лафоре. "ООП в С++ " (4-е издание). 2012. Глава 12, стр.574, листинг 12.17, программа EMPL_IO.
В классах присутствуют виртуальные методы и используются бинарные методы чтения\записи памяти под объектами. Кто что думает по поводу этого кода?
C++
1
2
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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
// empl_io.cpp
// performs file I/O on employee objects
// handles different sized objects
#include <fstream>            //for file-stream functions
#include <iostream>
#include <typeinfo>           //for typeid()
using namespace std;
#include <process.h>          //for exit()
 
const int LEN = 32;           //maximum length of last names
const int MAXEM = 100;        //maximum number of employees
 
enum employee_type {tmanager, tscientist, tlaborer};
////////////////////////////////////////////////////////////////
class employee                //employee class
   {
   private:
      char name[LEN];         //employee name
      unsigned long number;   //employee number
      static int n;           //current number of employees
      static employee* arrap[];  //array of ptrs to emps
   public:
      virtual void getdata()
         {
         cin.ignore(10, '\n');
         cout << "   Enter last name: "; cin >> name;
         cout << "   Enter number: ";      cin >> number;
         }
      virtual void putdata()
         {
         cout << "\n   Name: " << name;
         cout << "\n   Number: " << number;
         }
      virtual employee_type get_type();  //get type
      static void add();      //add an employee
      static void display();  //display all employees
      static void read();     //read from disk file
      static void write();    //write to disk file
   };
//--------------------------------------------------------------
//static variables
int employee::n;              //current number of employees
employee* employee::arrap[MAXEM];  //array of ptrs to emps
////////////////////////////////////////////////////////////////
//manager class
class manager : public employee
   {
   private:
      char title[LEN];        //"vice-president" etc.
      double dues;            //golf club dues
   public:
      void getdata()
         {
         employee::getdata();
         cout << "   Enter title: ";          cin >> title;
         cout << "   Enter golf club dues: "; cin >> dues;
         }
      void putdata()
         {
         employee::putdata();
         cout << "\n   Title: " << title;
         cout << "\n   Golf club dues: " << dues;
         }
   };
////////////////////////////////////////////////////////////////
//scientist class
class scientist : public employee
   {
   private:
      int pubs;               //number of publications
   public:
      void getdata()
         {
         employee::getdata();
         cout << "   Enter number of pubs: "; cin >> pubs;
         }
      void putdata()
         {
         employee::putdata();
         cout << "\n   Number of publications: " << pubs;
         }
   };
////////////////////////////////////////////////////////////////   
//laborer class
class laborer : public employee
   {
   };
////////////////////////////////////////////////////////////////
//add employee to list in memory
void employee::add()
   {
   char ch;
   cout << "'m' to add a manager"
           "\n's' to add a scientist"
           "\n'l' to add a laborer"
           "\nEnter selection: ";
   cin >> ch;
   switch(ch)
      {                       //create specified employee type
      case 'm': arrap[n] = new manager;   break;
      case 's': arrap[n] = new scientist; break;
      case 'l': arrap[n] = new laborer;   break;
      default: cout << "\nUnknown employee type\n"; return;
      }
   arrap[n++]->getdata();     //get employee data from user
   }
//--------------------------------------------------------------
//display all employees
void employee::display()
   {
   for(int j=0; j<n; j++)
      {
      cout  << (j+1);           //display number
      switch( arrap[j]->get_type() )   //display type
         {
         case tmanager:    cout << ". Type: Manager";   break;
         case tscientist:  cout << ". Type: Scientist"; break;
         case tlaborer:    cout << ". Type: Laborer";   break;
         default: cout << ". Unknown type";
         }
      arrap[j]->putdata();    //display employee data
      cout << endl;
      }
   }
//--------------------------------------------------------------
//return the type of this object
employee_type employee::get_type()
   {
   if( typeid(*this) == typeid(manager) )
      return tmanager;
   else if( typeid(*this)==typeid(scientist) )
      return tscientist;
   else if( typeid(*this)==typeid(laborer) )
      return tlaborer;
   else
      { cerr << "\nBad employee type"; exit(1); }
   return tmanager;
   }
//--------------------------------------------------------------
//write all current memory objects to file
void employee::write()
   {
   int size;
   cout << "Writing " << n << " employees.\n";
   ofstream ouf;              //open ofstream in binary
   employee_type etype;       //type of each employee object
 
   ouf.open("EMPLOY.DAT", ios::trunc | ios::binary);
   if(!ouf)
      { cout << "\nCan't open file\n"; return; }
   for(int j=0; j<n; j++)     //for every employee object
      {                       //get its type
      etype = arrap[j]->get_type();
                              //write type to file
      ouf.write( (char*)&etype, sizeof(etype) );
      switch(etype)           //find its size
         {
         case tmanager:   size=sizeof(manager); break;
         case tscientist: size=sizeof(scientist); break;
         case tlaborer:   size=sizeof(laborer); break;
         }                    //write employee object to file
      ouf.write( (char*)(arrap[j]), size );
      if(!ouf)
         { cout << "\nCan't write to file\n"; return; }
      }
   }
//--------------------------------------------------------------
//read data for all employees from file into memory
void employee::read()
   {
   int size;                  //size of employee object
   employee_type etype;       //type of employee
   ifstream inf;              //open ifstream in binary
   inf.open("EMPLOY.DAT", ios::binary);
   if(!inf)
      { cout << "\nCan't open file\n"; return; }
   n = 0;                     //no employees in memory yet
   while(true)
      {                       //read type of next employee
      inf.read( (char*)&etype, sizeof(etype) );
      if( inf.eof() )         //quit loop on eof
         break;
      if(!inf)                //error reading type
         { cout << "\nCan't read type from file\n"; return; }
      switch(etype)
         {                    //make new employee
         case tmanager:       //of correct type
            arrap[n] = new manager;
            size=sizeof(manager);
            break;
         case tscientist:
            arrap[n] = new scientist;
            size=sizeof(scientist);
            break;
         case tlaborer:
            arrap[n] = new laborer;
            size=sizeof(laborer);
            break;
         default: cout << "\nUnknown type in file\n"; return;
         }                    //read data from file into it
      inf.read( (char*)arrap[n], size  );
      if(!inf)                //error but not eof
         { cout << "\nCan't read data from file\n"; return; }
      n++;                    //count employee
      }  //end while
   cout << "Reading " << n << " employees\n";
   }
////////////////////////////////////////////////////////////////
int main()
   {
   char ch;
   while(true)
      {
      cout << "'a' -- add data for an employee"
              "\n'd' -- display data for all employees"
              "\n'w' -- write all employee data to file"
              "\n'r' -- read all employee data from file"
              "\n'x' -- exit"
              "\nEnter selection: ";
      cin >> ch;
      switch(ch)
         {
         case 'a':            //add an employee to list
            employee::add(); break;
         case 'd':            //display all employees
            employee::display(); break;
         case 'w':            //write employees to file
            employee::write(); break;
         case 'r':            //read all employees from file
            employee::read(); break;
         case 'x': exit(0);   //exit program
         default: cout << "\nUnknown command";
         }  //end switch
      }  //end while
   return 0;
   }  //end main()
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,915
Записей в блоге: 2
Завершенные тесты: 1
07.10.2013, 21:09     Код из "Р.Лафоре. ООП в С++" #2
Цитата Сообщение от alsav22 Посмотреть сообщение
В классах присутствуют виртуальные методы
А что в этом такого?
Правда я не вижу виртуального деструктора

Добавлено через 2 минуты
Или Вы имеете ввиду, что будет и указатель на таблицу виртуальных функций записан при
Цитата Сообщение от alsav22 Посмотреть сообщение
используются бинарные методы чтения\записи памяти под объектами.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
07.10.2013, 21:11  [ТС]     Код из "Р.Лафоре. ООП в С++" #3
Цитата Сообщение от Croessmah Посмотреть сообщение
Или Вы имеете ввиду, что будет и указатель на таблицу виртуальных функций записан
Именно это.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,915
Записей в блоге: 2
Завершенные тесты: 1
07.10.2013, 21:33     Код из "Р.Лафоре. ООП в С++" #4
Цитата Сообщение от alsav22 Посмотреть сообщение
Именно это.
скажем так, что в пределах одной компиляции это не так критично. Но если, создать файл, выйти, потом перекомпилировать программу, и потом считать, то адрес таблицы может поменяться и тогда беда.

Добавлено через 4 минуты
Специально потестил:
Первый запуск:
croessmah@croessmah-pc:~/c++/prj1/prj1$ ./main
'a' -- add data for an employee
'd' -- display data for all employees
'w' -- write all employee data to file
'r' -- read all employee data from file
'x' -- exit
Enter selection: a
'm' to add a manager
's' to add a scientist
'l' to add a laborer
Enter selection: m
Enter last name: 1111
Enter number: 22
Enter title: 333
Enter golf club dues: 4444

'a' -- add data for an employee
'd' -- display data for all employees
'w' -- write all employee data to file
'r' -- read all employee data from file
'x' -- exit
Вот этот момент важен (то, что создали):
Enter selection: d
1. Type: Manager
Name: 1111
Number: 22
Title: 333
Golf club dues: 4444
'a' -- add data for an employee
'd' -- display data for all employees
'w' -- write all employee data to file
'r' -- read all employee data from file
'x' -- exit
Enter selection: w
Writing 1 employees.
'a' -- add data for an employee
'd' -- display data for all employees
'w' -- write all employee data to file
'r' -- read all employee data from file
'x' -- exit
Enter selection: r
Reading 1 employees
'a' -- add data for an employee
'd' -- display data for all employees
'w' -- write all employee data to file
'r' -- read all employee data from file
'x' -- exit
Вот этот момент важен (то, что записали в файл и считали):
Enter selection: d
1. Type: Manager
Name: 1111
Number: 22
Title: 333
Golf club dues: 4444
'a' -- add data for an employee
'd' -- display data for all employees
'w' -- write all employee data to file
'r' -- read all employee data from file
'x' -- exit
Enter selection: x
Вышли из программы, добавил в прогу одну функцию:
C++
1
2
3
4
 int foo () {
     std::cout <<"Fuck off"<<std :: endl;
     return 25 ;
 }
и её вызов в main

Теперь запускаем новую программу:
croessmah@croessmah-pc:~/c++/prj1/prj1$ ./main
Fuck off //Добавленная строчка
'a' -- add data for an employee
'd' -- display data for all employees
'w' -- write all employee data to file
'r' -- read all employee data from file
'x' -- exit
Enter selection: r
Считали данные (там как и положенно один рабочий)
Reading 1 employees
'a' -- add data for an employee
'd' -- display data for all employees
'w' -- write all employee data to file
'r' -- read all employee data from file
'x' -- exit
И кульминация:
Enter selection: d
1. Type: Scientist
Name: 1111
Number: 22
Number of publications: 3355443

'a' -- add data for an employee
'd' -- display data for all employees
'w' -- write all employee data to file
'r' -- read all employee data from file
'x' -- exit
Enter selection: x
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
07.10.2013, 21:56  [ТС]     Код из "Р.Лафоре. ООП в С++" #5
Я его так пробовал: код в Debug записывал, а четние и вывод - в Release (или наоборот), или переносил файл, записанный в студии, в Code Blocks и запускал там чтение файла и вывод данных. Ошибки.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,915
Записей в блоге: 2
Завершенные тесты: 1
07.10.2013, 22:24     Код из "Р.Лафоре. ООП в С++" #6
Цитата Сообщение от alsav22 Посмотреть сообщение
Кто что думает по поводу этого кода?
вот:
Цитата Сообщение от alsav22 Посмотреть сообщение
Ошибки.
В книге далее нигде не упоминается об этом?

Добавлено через 10 минут
Да и еще, нафига
C++
1
#include <process.h>          //for exit()
cstdlib же есть!
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
07.10.2013, 22:33  [ТС]     Код из "Р.Лафоре. ООП в С++" #7
Цитата Сообщение от Croessmah Посмотреть сообщение
В книге далее нигде не упоминается об этом?
Сильно далеко не смотрел. Далее есть описание взаимодействия с этого программой (скрины). Всю книгу не читал, поэтому сказать не могу: затрагивается ли там эта тема или нет, но мне кажется, что о таких вещах сразу предупреждают.
Миниатюры
Код из "Р.Лафоре. ООП в С++"   Код из "Р.Лафоре. ООП в С++"  
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,915
Записей в блоге: 2
Завершенные тесты: 1
07.10.2013, 22:36     Код из "Р.Лафоре. ООП в С++" #8
Цитата Сообщение от alsav22 Посмотреть сообщение
что о таких вещах сразу предупреждают.
В книжных листингах всегда есть ошибки, которые могут оставаться не замеченными долгое время. Если есть более новое издание, может в нем они уже исправлены.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
07.10.2013, 22:46  [ТС]     Код из "Р.Лафоре. ООП в С++" #9
Цитата Сообщение от Croessmah Посмотреть сообщение
В книжных листингах всегда есть ошибки
Есть то они есть... Но тут ошибка не техническая (если это ошибка). Тут же весь код на полиморфизме построен.

Добавлено через 4 минуты
Да и более поздних изданий я не вижу.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,915
Записей в блоге: 2
Завершенные тесты: 1
07.10.2013, 22:50     Код из "Р.Лафоре. ООП в С++" #10
Цитата Сообщение от alsav22 Посмотреть сообщение
Тут же весь код на полиморфизме построен.
Цитата Сообщение от alsav22 Посмотреть сообщение
Но тут ошибка не техническая
Почему не техническая? Как раз самая техническая - забыли про реализацию виртуальности.

Не по теме:

Как раз моя подпись подходит... про второй экземпляр

TheChosenOne
13 / 13 / 1
Регистрация: 13.09.2013
Сообщений: 113
08.12.2013, 16:35     Код из "Р.Лафоре. ООП в С++" #11
up
Как раз изучаю тему работы с файлами по этой книге. Тоже столкнулся с этой проблемой. В пределах одной компиляции все работает стабильно - пишет-читает-выводит. Но после перезапуска ,при попытки считать - пишет что считал,а при попытки вывести на экран - компилятор завершает работу. Я с плюсами недавно, по-этому,не могли бы вы популярно объяснить почему так происходит ?
Буду благодарен
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
08.12.2013, 16:52  [ТС]     Код из "Р.Лафоре. ООП в С++" #12
Здесь почитайте: Запись и чтение объектов разных классов в один файл
Запись и извлечение данных в несколько запусков программы
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.12.2013, 17:35     Код из "Р.Лафоре. ООП в С++"
Еще ссылки по теме:

C++ В зависимости от времени года "весна", "лето", "осень", "зима" определить погоду "тепло", "жарко", "холодно", "очень холодно"
Разобраться в примерх к книге Лафоре "Обьектно-ориентированое программирование в С++" C++
Не компилируется листинг "Передача по ссылке аргументов" Р.Лафоре C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
TheChosenOne
13 / 13 / 1
Регистрация: 13.09.2013
Сообщений: 113
08.12.2013, 17:35     Код из "Р.Лафоре. ООП в С++" #13
Благодарю,разобрался
Yandex
Объявления
08.12.2013, 17:35     Код из "Р.Лафоре. ООП в С++"
Ответ Создать тему
Опции темы

Текущее время: 16:21. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru