Виртуальные базовые классы и деструкторы
05.09.2018, 00:36. Показов 2156. Ответов 4
Пожалуйста, помогите разобраться. Решаю задачу 6 глава 17 из Праты. Кратко: в определении виртуального абстрактного класса определяю деструктор: C++ | 1
| virtual ~abstr_emp() = 0 {}; |
|
В процессе освобождения памяти, выделенной динамически в массиве указателей, по цепочке вызываются деструкторы по умолчанию вплоть до этого C++ | 1
| virtual ~abstr_emp() = 0 {}; |
|
(В функции: C++ | 1
2
3
4
5
6
7
| void free(abstr_emp** pc, int nn)
{
for (int i = 0; i < nn; i++)
{
delete pc[i];
};
} |
|
И здесь выскакивает исключение:
Exception thrown: read access violation.
_Pnext was 0x38E9DC.
Указывает на (если это поможет):
C++ | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| // MEMBER FUNCTIONS FOR _Container_base12
inline void _Container_base12::_Orphan_all()
{ // orphan all iterators
#if _ITERATOR_DEBUG_LEVEL == 2
if (_Myproxy != 0)
{ // proxy allocated, drain it
_Lockit _Lock(_LOCK_DEBUG);
for (_Iterator_base12 **_Pnext = &_Myproxy->_Myfirstiter;
*_Pnext != 0; *_Pnext = (*_Pnext)->_Mynextiter) // - ошибка!
(*_Pnext)->_Myproxy = 0;
_Myproxy->_Myfirstiter = 0;
}
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
} |
|
Причем ошибка возникает с данными, кот были считаны из бинарников. При первом запуске и записи в бинарник освобождение памяти идет на ура.
Полный код программы:
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
| #pragma once
#ifndef EMP_H
#define EMP_H
#include <iostream>
#include <fstream>
#include <string>
using std::string;
using std::ofstream;
using std::ostream;
using std::ifstream;
enum classType { Employee, Manager, Fink, Highfink };
class abstr_emp
{
private:
string fname;
string lname;
string job;
public:
abstr_emp() : fname("Noname"), lname("No_last_name"), job("No_job") {};
abstr_emp(const string & fn, const string & ln, const string & j) :
fname(fn), lname(ln), job(j) {}
virtual void ShowAll() const;
virtual void SetAll();
friend ostream& operator<<(ostream &os, const abstr_emp & e);
virtual ~abstr_emp() = 0 {};
virtual bool writeall(ofstream & fout) const;
virtual bool getall(ifstream &fin);
};
class employee: public abstr_emp
{
public:
employee() :abstr_emp() {};
employee(const string& fn, const string & ln, const string &j) :
abstr_emp(fn, ln, j) {};
virtual void ShowAll() const { abstr_emp::ShowAll(); };
virtual void SetAll() { abstr_emp::SetAll(); };
virtual bool writeall(ofstream &fout) const;
virtual bool getall(ifstream &fin) { return abstr_emp::getall(fin); };
};
class manager : virtual public abstr_emp
{
private:
int inchargeof;
protected:
int InChargeOf() const { return inchargeof; };
int & InChargeOf() { return inchargeof; };
public:
manager() :abstr_emp(), inchargeof(0) {};
manager(const string & fn, const string & ln, const string & j, int ico = 0) :
abstr_emp(fn, ln, j), inchargeof(ico) {};
manager(const abstr_emp& e, int ico) : abstr_emp(e), inchargeof(ico) {};
manager(const manager &m) : abstr_emp(m), inchargeof(m.inchargeof) {};
virtual void ShowAll() const;
virtual void SetAll();
virtual bool writeall(ofstream &fout) const;
virtual bool getall(ifstream &fin);
};
class fink : virtual public abstr_emp
{
private:
string reportsto;
protected:
const string ReportsTo() const { return reportsto; };
string & ReportsTo() { return reportsto; };
public:
fink() :abstr_emp(), reportsto("No_reprs") {};
fink(const string & fn, const string & ln, const string & j, const string & rpo) :
abstr_emp(fn, ln, j), reportsto(rpo) {};
fink(const abstr_emp & e, const string& rpo) : abstr_emp(e), reportsto(rpo) {};
fink(const fink & e) : abstr_emp(e), reportsto(e.reportsto) {};
virtual void ShowAll() const;
virtual void SetAll();
virtual bool writeall(ofstream &fout) const;
virtual bool getall(ifstream &fin);
};
class highfink : public manager, public fink
{
public:
highfink() : manager(), fink() {};
highfink(const string & fn, const string & ln, const string & j, const string & rpo) :
manager(fn, ln, j), fink(fn, ln, j, rpo) {};
highfink(const abstr_emp &e, const string & rpo, int ico) :
manager(e, ico), fink(e, rpo) {};
highfink(const fink& f, int ico) :
manager(f, ico), fink(f) {};
highfink(const manager & m, const string & rpo) :
manager(m), fink(m, rpo) {};
highfink(const highfink & h) : manager(h), fink(h) {};
virtual void ShowAll() const;
virtual void SetAll();
virtual bool writeall(ofstream &fout) const;
virtual bool getall(ifstream &fin);
}; |
|
Тест:
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
| #include "Employee.h"
#include <memory>
using std::cerr;
using std::ios_base;
using std::fstream;
using std::cout;
using std::endl;
using std::cin;
const int MAX = 2;
abstr_emp *pc[MAX];
void usr_inp(abstr_emp** pc, int nn);
void show_it(abstr_emp** pc, int nn);
void free(abstr_emp** pc, int nn);
bool save2file(abstr_emp** pc, int nn, ofstream& fout);
bool read_from_file(abstr_emp** pc, int nn, ifstream& fin);
int main()
{
ofstream fout;
fout.open("f1.txt", ios_base::out | ios_base::app | ios_base::binary);
if (!fout.is_open())
{
cerr << "Error opening " << "f1.txt" << " file!\n";
exit(EXIT_FAILURE);
}
fout.seekp(0, fout.end);
long length = fout.tellp();
if (length == 0)
{
usr_inp(pc, MAX);
cout << "\n\nUr input to be written in a file: ";
show_it(pc, MAX);
if (save2file(pc, MAX, fout))
{
cout << "Saved successfully...";
}
fout.close();
}
else {
fout.seekp(0, fout.beg);
ifstream fin;
fin.open("f1.txt", ios_base::in | ios_base::binary);
if (!fin.is_open())
{
cerr << "Error opening " << "f1.txt" << " file!\n";
exit(EXIT_FAILURE);
}
if (read_from_file(pc, MAX, fin))
show_it(pc, MAX);
fin.clear();
fin.close();
cout << "Modify info? (Y/N): ";
char yn;
while (cin >> yn && tolower(yn) != 'n')
{
if (tolower(yn) == 'y')
{
free(pc, MAX);
usr_inp(pc, MAX);
if (save2file(pc, MAX, fout))
{
cout << "Saved successfully...";
break;
}
}
else {
cout << "Wrong value. Try again pls: ";
continue;
}
}
cin.get();
};
fout.close();
cout << "Programm terminating...\n";
free(pc, MAX);
cin.get();
return 0;
}
void usr_inp(abstr_emp** pc, int nn)
{
int W_class;
for (int i = 0; i < nn; i++)
{
cout << "Type of the worker (0 for Employee, 1 for Manager, 2 for Fink, 3 for HighFink):\n";
cin >> W_class;
cin.get();
switch (W_class){
case Employee: pc[i] = new employee;
break;
case Manager: pc[i] = new manager;
break;
case Fink: pc[i] = new fink;
break;
case Highfink: pc[i] = new highfink;
break;
default: cout << "Ur value has not been matched..\n";
break;
};
pc[i]->SetAll();
};
}
void show_it(abstr_emp** pc, int nn)
{
for (int i = 0; i < nn; i++)
pc[i]->ShowAll();
}
void free(abstr_emp** pc, int nn)
{
for (int i = 0; i < nn; i++)
{
delete pc[i];
};
}
bool save2file(abstr_emp** pc, int nn, ofstream& fout)
{
int i;
cout << "Saving to the file..\n";
for (i = 0; i < MAX; i++)
{
pc[i]->writeall(fout);
}
if (!fout)
{
cerr << "Smth went wrong while writing into the file..\n";
system("pause");
return false;
}
else return true;
}
bool read_from_file(abstr_emp** pc, int nn, ifstream& fin)
{
cout << "Reading the info from a file:\n";
int type;
int i = 0;
while (!fin.eof() && i < MAX)
{
fin.read((char *)&type, sizeof(type));
switch (type) {
case Employee: pc[i] = new employee;
break;
case Manager: pc[i] = new manager;
break;
case Fink: pc[i] = new fink;
break;
case Highfink: pc[i] = new highfink;
break;
default: cout << "ID Value has not been matched..\n";
system("pause");
break;
}
pc[i++]->getall(fin);
}
if (fin)
return true;
else return false;
} |
|
Реализация:
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
| #include "Employee.h"
using std::cout;
using std::endl;
using std::cin;
void abstr_emp::ShowAll() const
{
cout << "Employee info:\n";
cout << "Name: " << fname << endl
<<"Last name: " << lname << endl
<<"Job: " << job << endl;
}
void abstr_emp::SetAll()
{
cout << "Input the name: ";
getline(cin, fname);
cout << "Lname: ";
getline(cin, lname);
cout << "Job: ";
getline(cin, job);
}
bool abstr_emp::writeall(ofstream & fout) const
{
fout.write((char*) &fname, sizeof(fname));
fout.write((char*) &lname, sizeof(lname));
fout.write((char*) &job, sizeof(job));
if (fout)
return true;
else return false;
}
bool abstr_emp::getall(ifstream & fin)
{
fin.read((char*)&fname, sizeof(fname));
fin.read((char*)&lname, sizeof(lname));
fin.read((char*)&job, sizeof(job));
if (fin)
return true;
else return false;
}
ostream & operator<<(ostream & os, const abstr_emp & e)
{
os << "Fname: " << e.fname << endl;
os << "Lname: " << e.lname << endl;
os << "Job: " << e.job << endl;
return os;
}
void manager::ShowAll() const
{
abstr_emp::ShowAll();
cout << "Inchargeof: " << InChargeOf() << endl;
}
void manager::SetAll()
{
abstr_emp::SetAll();
cout << "Inchargeof: ";
cin >> InChargeOf();
}
bool manager::writeall(ofstream & fout) const
{
classType Type = Manager;
fout.write((char*)&Type, sizeof(Type));
abstr_emp::writeall(fout);
fout.write((char*) &inchargeof, sizeof(inchargeof));
if (fout)
return true;
else return false;
}
bool manager::getall(ifstream & fin)
{
abstr_emp::getall(fin);
fin.read((char *) &inchargeof, sizeof(inchargeof));
if (fin)
return true;
else return false;
}
void fink::ShowAll() const
{
abstr_emp::ShowAll();
cout << "Reports to: " << ReportsTo() << endl;
}
void fink::SetAll()
{
abstr_emp::SetAll();
cout << "Reports to: ";
cin >> ReportsTo();
}
bool fink::writeall(ofstream & fout) const
{
classType Type = Fink;
fout.write((char*)&Type, sizeof(Type));
abstr_emp::writeall(fout);
fout.write((char*)&reportsto, sizeof(reportsto));
if (fout)
return true;
else return false;
}
bool fink::getall(ifstream & fin)
{
abstr_emp::getall(fin);
fin.read((char *)&reportsto, sizeof(reportsto));
if (fin)
return true;
else return false;
}
void highfink::ShowAll() const
{
cout << "Showing highfink output items: \n";
abstr_emp::ShowAll();
cout << "Inchargeof: " << manager::InChargeOf() << endl;
cout << "Reports to: " << fink::ReportsTo() << endl;
}
void highfink::SetAll()
{
abstr_emp::SetAll();
cout << "Inchargeof: ";
cin >> manager::InChargeOf();
cout << "Reports to: ";
cin >> fink::ReportsTo();
}
bool highfink::writeall(ofstream & fout) const
{
classType Type = Highfink;
fout.write((char*)&Type, sizeof(Type));
abstr_emp::writeall(fout);
const int ico = InChargeOf();
const string rpt = ReportsTo();
fout.write((char*)&ico, sizeof(ico));
fout.write((char*)&rpt, sizeof(rpt));
if (fout)
return true;
else return false;
}
bool highfink::getall(ifstream & fin)
{
abstr_emp::getall(fin);
int ico = manager::InChargeOf();
string rpt = fink::ReportsTo();
fin.read((char *)&ico, sizeof(ico));
fin.read((char *)&rpt, sizeof(rpt));
if (fin)
return true;
else return false;
}
bool employee::writeall(ofstream & fout) const
{
classType Type = Employee;
fout.write((char*)&Type, sizeof(Type));
return abstr_emp::writeall(fout);
} |
|
Буду признателен за любую помощь!
0
|