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

тема Наследование правильно ли я вызываю диструктор - C++

Восстановить пароль Регистрация
 
viktorius
2 / 2 / 2
Регистрация: 24.02.2013
Сообщений: 105
29.11.2013, 14:06     тема Наследование правильно ли я вызываю диструктор #1
Всем Здравствуйте. Я не уверен правильно ли я вызываю диструктор employee в диструкторе класса Manager
вот весь код

main.cpp
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
#include <iostream>
#include "date.h"
#include "employee.h"
#include "manager.h"
#include "supervisor.h"
#include <windows.h>
using namespace std;
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    Manager m1;
    m1.SetEmp();
    m1.SetSub();
    m1.SetWork();
    m1.Print();
    //Employee e1("Вася", "Поспелов", "Специалист", 20000, 20, 11, 2011);
    //e1.Print();
    //e1.Setfir();
    //e1.Print();
    //Date d5 = e1.Hired();
    //d5.Print();
    //d5.SetDate();
    //d5.Print();
    //Date d1;
    //d1.Print();
    //d1.SetDate();
    //d1.Print();
    system("pause");
    return 0;
}
date.h
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
#include <iostream>
#ifndef DATE_H
#define DATE_H
 
class Date
{
    int day, month, year;
    static int days[];
    bool Leapyear(int);
    Date(const Date &);
    Date &operator = (const Date &);
public:
    Date();
    Date(int, int, int);
    bool operator == (const Date &);
    bool operator != (const Date &);
    bool operator < (const Date &);
    bool operator > (const Date &);
    void SetDate();
    int GetDay() const;
    int GetMonth() const;
    int GetYear() const;
    void Print() const;
};
 
#endif
date.cpp
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
#include <iostream>
#include "date.h"
using namespace std;
 
int Date::days[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
Date::Date(): day(0), month(0), year(0)
{}
 
Date::Date(int _day, int _month, int _year)
{
    year = (_year >= 2000 && _year <= 2050) ? _year : 2000;
    month = (_month >= 1 && _month <= 12) ? _month : 1;
    if(month == 2 && Leapyear(year))
        day = (_day >= 1 && _day <= 29) ? _day : 1;
    else
        day = (_day >= 1 && _day <= days[month]) ? _day : 1;
}
 
bool Date::operator == (const Date &ob)
{
    if(day == ob.day && month == ob.month && year == ob.year)
        return true;
    else
        return false;
}
 
bool Date::operator != (const Date &ob)
{
    if(day != ob.day || month != ob.month || year != ob.year)
        return true;
    else
        return false;
}
bool Date::operator < (const Date &ob)
{
    if(year < ob.year)
    {
        if(month < ob.month)
        {
            if(day < ob.day)
                return true;
            else
                return false;
        }
        else
            return false;
    }
    else
        return false;
}
 
bool Date::operator > (const Date &ob)
{
    if(year > ob.year)
    {
        if(month > ob.month)
        {
            if(day > ob.day)
                return true;
            else
                return false;
        }
        else
            return false;
    }
    else
        return false;
}
 
bool Date::Leapyear(int _year)
{
    if(_year % 400 == 0 || (_year % 100 != 0 && _year % 4 == 0))
        return true;
    else
        return false;
}
 
void Date::SetDate()
{
    while(1)
    {
        cout<<"введите через пробел день месяц год"<<endl;
        cin>>day>>month>>year;
        if((year < 2000 || year > 2050) || (month < 1 || month > 12) || (month == 2 && Leapyear(year) && (day < 1 || day > 29) || (day < 1 || day > days[month])))
            cout<<"неверная дата повторите ввод"<<endl;
        else
            break;
        cin.clear();
        while(cin.get() != '\n');
    }
}
 
int Date::GetDay() const
{
    return day;
}
 
int Date::GetMonth() const
{
    return month;
}
 
int Date::GetYear() const
{
    return year;
}
 
void Date::Print() const
{
    cout<<day<<"."<<month<<"."<<year<<endl;
}
employee.h
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
#include <iostream>
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
#include "date.h"
 
class Employee
{
    char *first, *last, *post;//имя, фамилие, должность
    int salary;//зарплата
    const int persnum;//табельный номер
    static int count;// счетчик
    Date hired, fired;//прием, увольнение
    Employee(const Employee &);
    Employee &operator = (const Employee &);
public:
    Employee();
    Employee(char *, char *, char *, int, int, int, int);
    ~Employee();
    void SetEmp();//ввод данных
    void Setfir();//ввод даты увольнения
    void Print() const;
    const char *First() const;
    const char *Last() const;
    const char *Post() const;
    int Salary() const;
    int Persnum() const;
    int Count() const;
    const Date &Hired() const;
    const Date &Fired() const;
};
 
#endif
employee.cpp
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
#include <iostream>
#include "employee.h"
#include <cstring>
using namespace std;
 
int Employee::count = 0;
 
Employee::Employee(): hired(), fired(), first(0), last(0), post(0), salary(0), persnum(count + 1)
{
    count++;
}
 
Employee::Employee(char *_first, char *_last, char *_post, int _salary, int _day, int _month, int _year): hired(_day, _month, _year), fired(), salary(_salary), persnum(count + 1)
{
    first = new char[strlen(_first) + 1];
    strcpy(first, _first);
    last = new char[strlen(_last) + 1];
    strcpy(last, _last);
    post = new char[strlen(_post) + 1];
    strcpy(post, _post);
    count++;
}
 
Employee::~Employee()
{
    delete [] first;
    delete [] last;
    delete [] post;
    first = last = post = 0;
}
 
void Employee::SetEmp()
{
    char a[80];
    cout<<"введите имя: "<<endl;
    cin>>a;
    if(first)
        delete [] first;
    first = new char[strlen(a) + 1];
    strcpy(first, a);
    cout<<"введите фамилию: "<<endl;
    cin>>a;
    if(last)
        delete [] last;
    last = new char[strlen(a) + 1];
    strcpy(last, a);
    cout<<"введите должность: "<<endl;
    cin>>a;
    if(post)
        delete [] post;
    post = new char[strlen(a) + 1];
    strcpy(post, a);
    cout<<"введите зарплату: "<<endl;
    cin>>salary;
    cout<<"введите дату приема на работу: "<<endl;
    hired.SetDate();
}
 
void Employee::Setfir()
{
    fired.SetDate();
}
 
void Employee::Print() const
{
    cout<<"Имя: "<<first<<endl<<"Фамилие: "<<last<<endl<<"Должность: "<<post<<endl
        <<"Зарплата: "<<salary<<endl<<"Табельный номер: "<<persnum<<endl
        <<"Дата приема: ";
    hired.Print();
    cout<<"Дата увольнения: ";
    if(!fired.GetDay() && !fired.GetMonth() && !fired.GetYear())
        cout<<"Еще работает"<<endl;
    else
        fired.Print();
}
 
const char *Employee::First() const
{
    return first;
}
 
const char *Employee::Last() const
{
    return last;
}
 
const char *Employee::Post() const
{
    return post;
}
 
int Employee::Salary() const
{
    return salary;
}
 
int Employee::Persnum() const
{
    return persnum;
}
 
int Employee::Count() const
{
    return count;
}
 
const Date &Employee::Hired() const
{
    return hired;
}
 
const Date &Employee::Fired() const
{
    return fired;
}
manager.h
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
#include <iostream>
#ifndef MANAGER_H
#define MANAGER_H
#include "employee.h"
 
struct Subordinate//контроль работы сотрудников
{
    Employee *worker;//работник
    char *work;//тип работы
    Date *start, *actual, *end;//дата начала, фактического окончания, окончания работы
    Subordinate *next;//следующий работник
};
 
class Manager : public Employee
{
    Subordinate *sub;
    Manager(Manager &);
    Manager &operator = (Manager &);
public:
    Manager();
    Manager(char *, char *, char *, int, int, int, int);//создает менеджера
    ~Manager();
    void SetSub();//ввод данных о работниках
    void SetWork();//ввод данных о работе выполняемой работниками
    void SetAct();//установка фактического окончания работы
    void Print() const;
};
 
#endif
manager.cpp
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
#include <iostream>
#include "manager.h"
using namespace std;
 
Manager::Manager(): Employee(), sub(0)
{}
 
Manager::Manager(char *_first, char *_last, char *_post, int _salary, int _day, int _month, int _year): Employee(_first, _last, _post, _salary, _day, _month, _year), sub(0)
{}
 
Manager::~Manager()
{
    while(sub)
    {
        if(sub->worker)
            sub->worker->~Employee();
        if(sub->work)
            delete sub->work;
        if(sub->start)
            delete sub->start;
        if(sub->end)
            delete sub->end;
        if(sub->actual)
            delete sub->actual;
        Subordinate *s1 = sub;
        sub = sub->next;
        delete s1;
    }
}
 
void Manager::SetSub()//ввод данных о работниках
{
    int i;
    cout<<"введите число добавляемых сотрудников подчиненных менеджеру: "<<endl;
    cin>>i;
    for(; i > 0; i--)
    {
        Subordinate *s1 = new Subordinate();
        cout<<"введите данные о работнике: "<<endl;
        s1->worker = new Employee();
        s1->worker->SetEmp();
        s1->next = 0;
        s1->start = 0;
        s1->actual = 0;
        s1->end = 0;
        if(!sub)
            sub = s1;
        else
        {
            s1->next = sub;
            sub = s1;
        }
    }
}
 
void Manager::SetWork()//ввод данных о работе выполняемой работниками
{
    if(!sub)
    {
        cout<<"у этого менеджера еще нет работников в подчинении"<<endl;
        SetSub();
    }
    Subordinate *s1 = sub;
    while(s1)
    {
        char a[80];
        cout<<"введите тип работы: "<<endl;
        cin>>a;
        if(s1->work)
            delete [] s1->work;
        s1->work = new char[strlen(a) + 1];
        strcpy(s1->work, a);
        cout<<"введите дату начала работы"<<endl;
        if(s1->start)
            delete s1->start;
        s1->start = new Date();
        s1->start->SetDate();
        cout<<"введите дату окончания работы"<<endl;
        if(s1->end)
            delete s1->end;
        s1->end = new Date();
        s1->end->SetDate();
        s1 = s1->next;
    }
}
 
void Manager::SetAct()
{
    Subordinate *s1 = sub;
    while(s1)
    {
        cout<<"введите дату фактического окончания работы"<<endl;
        if(s1->actual)
            delete s1->actual;
        s1->actual = new Date();
        s1->actual->SetDate();
        s1 = s1->next;
    }
}
 
void Manager::Print() const
{
    cout<<"данные менеджера: "<<endl;
    Employee::Print();
    if(sub)
    {
        cout<<"список подчиненных сотрудников менеджеру: "<<endl;
        Subordinate *s1 = sub;
        while(s1)
        {
            sub->worker->Print();
            if(sub->work && sub->start && sub->end)
            {
                cout<<"тип работы: "<<sub->work<<endl
                    <<"начало работы: ";
                sub->start->Print();
                cout<<"окончание работы: ";
                sub->end->Print();
                if(sub->actual)
                {
                    cout<<"фактическое окончание работы: ";
                    sub->actual->Print();
                }
                else
                    cout<<"фактическое окончание работы не установлено: "<<endl;
 
            }
            else
                cout<<"тип работы, дата начала, дата окончания не заданы"<<endl;
            s1 = s1->next;
        }
    }
    else
        cout<<"у этого менеджера нет подчиненных сотрудников"<<endl;
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
0x10
2425 / 1597 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
29.11.2013, 14:08     тема Наследование правильно ли я вызываю диструктор #2
Деструктор не нужно вызывать явно.
Достаточно сделать его виртуальным в базовом классе.
viktorius
2 / 2 / 2
Регистрация: 24.02.2013
Сообщений: 105
29.11.2013, 14:25  [ТС]     тема Наследование правильно ли я вызываю диструктор #3
сделал виртуальным, но при попытке отследить при пошаговом выполнении, я его вызов не наблюдаю, использую visual studio.

У меня в производном классе поле указатель на структуру в которой имеется поле указатель на базовый класс, но здесь указатель на базовый класс в роли композиции, вот в этом месте диструктор не вызывается.
ShadowFirst
54 / 47 / 1
Регистрация: 31.10.2013
Сообщений: 161
29.11.2013, 16:17     тема Наследование правильно ли я вызываю диструктор #4
сделал виртуальным, но при попытке отследить при пошаговом выполнении, я его вызов не наблюдаю, использую visual studio.

У меня в производном классе поле указатель на структуру в которой имеется поле указатель на базовый класс, но здесь указатель на базовый класс в роли композиции, вот в этом месте диструктор не вызывается.
Весь код не просматривал, больно уж много его у вас. Диструктор вызывается в трех случаех:
1) При объявлении объекта класса динамически, то есть через new. Диструктор вызывается командой delete.
2) Продолжение 1го случая если вы указали родителя, то диструктор вызывается при уничтожении родителя.
3) Если вы создаете объект класса статически (без new), то диструктор вызывается когда покидается зона видимости этого объекта, будь то функция или класс.

Вроде ничего не упустил.
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
29.11.2013, 16:49     тема Наследование правильно ли я вызываю диструктор #5
Цитата Сообщение от viktorius Посмотреть сообщение
... в которой имеется поле указатель на базовый класс, но здесь указатель на базовый класс в роли композиции, вот в этом месте диструктор не вызывается.
Указатель связан с каким-нибудь объектом?
viktorius
2 / 2 / 2
Регистрация: 24.02.2013
Сообщений: 105
30.11.2013, 03:52  [ТС]     тема Наследование правильно ли я вызываю диструктор #6
да связан, попробую по цепочке показать и рассказать свою ошибку:

C++
1
m1.sub->worker
C++
1
2
m1(объект класса Manager).sub(указатель на структуру Subordinate)->
worker(указатель на объект класса Employee(у Employee есть диструктор для очистки динамической памяти))
при попытке освободить память в диструкторе Manager этими способами:

C++
1
delete sub->worker;
C++
1
sub->worker->~Employee();
диструктор Employee() не вызывается

Добавлено через 51 минуту
извините ввел вас в заблуждение, я добавил проверку в конструктор и диструктор

C++
1
2
3
4
5
cout<<"new"<<endl;
 
cout<<"delete"<<endl;
 
вот так delete sub->worker; все ок
видимо не стоит доверять клавише f11 в Visual Studio
Yandex
Объявления
30.11.2013, 03:52     тема Наследование правильно ли я вызываю диструктор
Ответ Создать тему
Опции темы

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