70 / 70 / 35
Регистрация: 06.07.2016
Сообщений: 415
1

Множественное наследование и виртуальные функции

24.09.2017, 23:05. Показов 742. Ответов 1
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Имеется вот такой код :
1.emp.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
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
#pragma once
 
#include <iostream>
#include <string>
 
class abstr_emp
{
private:
    std::string fname;
    std::string lname;
    std::string job;
 
    const std :: string defaultString =  "Nully";
public:
    abstr_emp() : fname{defaultString}, lname{defaultString}, job{defaultString}{}
    abstr_emp(const std::string & fn, const std::string & ln,const std::string & j):
    fname{fn}, lname{ln}, job{j}{}
 
    std::string Fname() const noexcept {return fname;}
    std::string Lname() const noexcept {return lname;}
    std::string Job() const noexcept {return job;}
 
    virtual void ShowAll() const
    {
        std::cout<<"\nName : " << fname
        << " Surname : " << lname <<
        " Job : " << job << std :: endl;
    }
 
    virtual void SetAll()
    {std::cout<<"Input name : "; std::cin >> fname;
    std::cout<<"Input surname : "; std::cin >> lname;
    std :: cout << "\nInput the job : "; std :: cin >> job;}
 
    friend std::ostream &
    operator << (std::ostream & os, const abstr_emp & e) {return os << e.Fname() << e.Lname();}
};
 
class employee : public abstr_emp
{
public:
    employee () : abstr_emp(){}
    employee(const std::string & fn, const std::string & ln, const std::string & j)
    : abstr_emp(fn,ln,j) {}
    virtual void ShowAll() const {abstr_emp::ShowAll();}
    virtual void SetAll() {abstr_emp :: SetAll();}
 
    friend std::ostream &
    operator << (std::ostream & os, const employee & e)
    {return operator << (os, static_cast <const abstr_emp &> (e));}
};
 
class manager: virtual public abstr_emp
{
private:
    int inchargeof; // количество управляемых
 
protected :
    int & InChargeOf(){ return inchargeof; } // ввод
public:
    manager(const std::string & fn, const std::string & ln, const std ::string & j, int ico = 0)
    : abstr_emp(fn, ln, j), inchargeof{ico}{}
    manager(const abstr_emp & e, int ico)
    : abstr_emp(e.Fname(), e.Lname(), e.Job()), inchargeof{ico} {}
    manager (const int &ico = 0):inchargeof{ico}{}
 
    virtual void ShowAll() const {abstr_emp :: ShowAll(); std::cout<<"Manager : "<<inchargeof<<std::endl;}
 
    int InChargeOf() const { return inchargeof; } // вывод
 
 
    virtual void SetAll()
    {abstr_emp :: SetAll(); std::cout<<"Input the quantity of bosses : "; std :: cin >> inchargeof;}
 
    friend std::ostream &
    operator << (std::ostream & os, const manager & e)
    {return operator << (os, static_cast <const abstr_emp &> (e));}
};
 
class fink: virtual public abstr_emp
{
private:
    std::string reportsto; // кому выводить отчеты
 
protected :
    std :: string& ReportsTo() noexcept {return reportsto;}
public:
    fink (const std::string &reports = ""):reportsto{reports}{}
    fink(const std::string & fn, const std::string & ln,const std::string & j, const std::string & rpo)
    : abstr_emp(fn, ln, j), reportsto{rpo}{}
    fink(const abstr_emp & e, const std::string & rpo)
    : abstr_emp(e.Fname(), e.Lname(), e.Job()), reportsto{rpo}{}
 
    virtual void ShowAll() const
    {abstr_emp :: ShowAll(); std::cout<<"Quantity of the reports : " << reportsto<<std::endl;}
 
    std :: string ReportsTo() const noexcept {return reportsto;}
 
    virtual void SetAll() {abstr_emp :: ShowAll();
    std::cout<<"Input the man who will answer on reports : ";std::cin>>reportsto;}
 
    friend std::ostream &
    operator << (std::ostream & os, const fink & e)
    {return operator << (os, static_cast <const abstr_emp &> (e));}
};
 
class highfink: public manager, public fink // надзор за управляющими
{
public:
    highfink () : abstr_emp(){}
    highfink(const std::string & fn, const std::string & ln,
    const std::string & j, const std::string & rpo, int ico)
    : abstr_emp(fn, ln, j), manager{ico}, fink{rpo} {}
 
    highfink(const abstr_emp & e, const std::string & rpo, int ico)
    : abstr_emp(e.Fname(), e.Lname(), e.Job()), manager(ico), fink(rpo) {}
 
    highfink(const fink & f, int ico)
    :abstr_emp(f.Fname(), f.Lname(), f.Job()),
     manager(ico), fink(f.Fname(), f.Lname(), f.Job(), f.ReportsTo()){}
 
    highfink(const manager & m, const std::string & rpo)
    :abstr_emp(m.Fname(), m.Lname(), m.Job()),
      manager(m.Fname(), m.Lname(), m.Job(), m.InChargeOf()), fink{m.Fname(), m.Lname(), m.Job(), rpo} {}
 
    virtual void ShowAll() const
     {
         abstr_emp :: ShowAll();
         std::cout<<"Manager : " << InChargeOf();
         std::cout<<"fink : " << ReportsTo();
         std::cout<<std::endl;
     };
 
    virtual void SetAll()
    {
        abstr_emp::SetAll();
        std::string name;
        int temporary;
 
        std::cout<<"Input manager : ";
        std::cin>>temporary;
        InChargeOf() = temporary;
 
        std::cout<<"Input fink : ";
        std::cin>>name;
        ReportsTo() = name;
    }
};


2.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
33
34
35
36
#include <iostream>
#include <vector>
#include <cstring>
 
#include "emp.h"
 
 
using std :: cin;
using std :: cout;
using std :: endl;
 
int main(void)
{
    employee em("Trip", "Harris", "Thumper");
    cout << em << endl;
    em.ShowAll();
    manager ma("Amorphia", "Spindragon", "Nuancer", 5);
    cout << ma << endl;
    ma.ShowAll();
    fink fi("Matt", "Oggs", "Oiler", "JunoBarr");
    cout << fi << endl;
    fi.ShowAll();
    highfink hf(ma, "Curly Kew"); // укомплектовано?
    hf.ShowAll() ;
    cout << "Press a key for next phase:\n";
    cin.get() ;
    highfink hf2;
    hf2.SetAll();
    cout << "Using an abstr_emp * pointer:\n";
    const int size{4};
    std :: vector <abstr_emp*> tri{&em, &fi, &hf, &hf2};
    for (int i = 0; i < size; i++)
    {
        tri[i]->ShowAll() ;
    }
}


Это упражнение номер 5 главы номер 14 книги "Язык программирования С++. Лекции и упражнения" Стивена Пратты :
Кликните здесь для просмотра всего текста
5. Ниже приведено несколько объявлений классов:
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
// emp.h — заголовочный файл для класса abstr_emp и его дочерних классов
#include <iostream>
#include <string>
class abstr_emp
{
private:
    std::string fname; // имяabstr_emp
    std::string lname; // фамилия abstr_emp
    std::string job;
public:
    abstr_emp();
    abstr_emp(const std::string & fn, const std::string & In, const std::string & j);
    virtual void ShowAllO const; // выводит все данные с именами
    virtual void SetAllO; // запрашивает значения у пользователя
    friend std::ostream &
    operator << (std::ostream & os, const abstr_emp & e) ; // Выводит только имя и фамилию
    virtual ~abstr_emp() = 0; // виртуальный базовый класс
};
class employee : public abstr_emp
{
public:
    employee () ;
    employee(const std::string & fn, const std::string & In,
    const std::string & j);
    virtual void ShowAll() const;
    virtual void SetAll();
};
 
class manager: virtual public abstr_emp
{
private:
    int inchargeof; // количество управляемых abstr_emp
protected:
    int InChargeOf() const { return inchargeof; } // вывод
    int & InChargeOf(){ return inchargeof; } // ввод
public:
    manager();
    manager(const std::string & fn, const std::string & In, const std: :string & j, int ico = 0) ;
    manager(const abstr_emp & e, int ico);
    manager(const manager & m) ;
    virtual void ShowAll() const;
    virtual void SetAll();
};
class fink: virtual public abstr_emp
{
private:
    std::string reportsto; // кому выводить отчеты
protected:
    const std::string ReportsTo() const { return reportsto; }
    std::string & ReportsTo() { return reportsto; }
public:
    fink() ;
    fink(const std::string & fn, const std::string & In, const std::string & j, const std::string & rpo);
    fink(const abstr_emp & e, const std::string & rpo);
    fink(const fink & e) ;
    virtual void ShowAll() const;
    virtual void SetAll();
};
 
class highfink: public manager, public fink // надзор за управляющими
{
public:
    highfink () ;
    highfink(const std::string & fn, const std::string & In,
    const std::string & j, const std::string & rpo, int ico) ;
    highfink(const abstr_emp & e, const std::string & rpo, int ico);
    highfink(const fink & f, int ico);
    highfink(const manager & m, const std::string & rpo);
    highfink(const highfink & h) ;
    virtual void ShowAll() const;
    virtual void SetAll();
};
Здесь в иерархии классов используется множественное наследование с
виртуальным базовым классом. Поэтому не забывайте о специальных правилах для
списков инициализации в конструкторах. Обратите также внимание на наличие
нескольких методов с защищенным доступом. Это упрощает код некоторых
методов highfink. (Например, если метод highfink: :ShowAll () просто
вызывает fink: : ShowAll () и manager: : ShowAll (), то это приводит к двукратному
вызову abstremp: : ShowAll ().) Реализуйте эти методы и протестируйте классы.
Ниже приведена минимальная тестовая программа:

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
// ре14-5.срр
// useempl.cpp — использование классов abstremp
#include <iostream>
using namespace std;
#include "emp.h"
int main(void)
{
    employee em("Trip", "Harris", "Thumper");
    cout << em << endl;
    em.ShowAll();
    manager ma("Amorphia", "Spindragon", "Nuancer", 5);
    cout << ma << endl;
    ma.ShowAll();
    fink fi("Matt", "Oggs", "Oiler", "JunoBarr");
    cout << fi << endl;
    fi.ShowAll();
    highfink hf(ma, "Curly Kew"); // укомплектовано?
    hf.ShowAll();
    cout << "Press a key for next phase:\n";
    // Нажать любую клавишу для следующей фазы
    cin.get () ;
    highfink hf2;
    hf2.SetAll() ;
    cout << "Using an abstr_emp * pointer:\n";
    // Использование указателя abstr_emp *
    abstr_emp * tri[4] = {&em, &fi, &hf, &hf2};
    for (int i = 0; i < 4; i++)
        tri[i]->ShowAll() ;
return 0;
}
Почему не определена операция присваивания?
Почему методы ShowAll () и SetAll () виртуальные?
Почему класс abstr_emp является виртуальным базовым классом?
Почему в классе highfink нет раздела данных?
Почему достаточно только одной версии операции operator« () ?
Что произойдет, если код в конце программы модифицировать следующим образом:
C++
1
2
3
abstr_emp tri[4] = {em, fi, hf, hf2};
for (int i = 0; i < 4; i++)
tri[i] .ShowAll ();

Непосредственно n-е количество времени было затрачено, чтобы заставить это работать.
Но нет, чего-то я видимо недопонимаю, так как в моменте начала работы с hf2 начинаются чудеса.
Программа вылетает с ошибками ***stack smashing***, segmentation fault. Gdb ничего не говорит кроме этого, даже когда иду со входом в функции.
Это уже третья реализация, где убрал почти что всю отсебятину, первоначальные версии были куда красивее и аккуратнее.
Ткните носом, что же не так.

Добавлено через 2 часа 23 минуты
Какой ужас. Проблема решена.
На строчке
Цитата Сообщение от Notoriously Посмотреть сообщение
highfink hf2;
Происходит вызов конструктора по умолчанию класса abstr_emp, где для инициализации значений используется
Цитата Сообщение от Notoriously Посмотреть сообщение
const std :: string defaultString = *"Nully";
, память для которой при инициализации в списке объектов еще не была выделена, в итоге идет обращение по адресу, где должна лежать defaultstring, но ее там, понятное дело, нет, поэтому идет обращение по невалидному адресу и программа падает.
Ну, после того как дебаггер VS кинул на файл xmemory, все стало ясно.
Решение - или инициализировать "чистой" строкой, либо же, я сделал так :

emp.h
C++
1
2
3
4
5
class abstr_emp
{
private:
...
    static constexpr char* defaultString{ "Nully" };
...
}

emp.cpp
C++
1
2
3
#include "emp.h"
 
constexpr char* abstr_emp::defaultString;
То есть просто ввел себе статическую переменную. Забавно, конечно, теперь все работает как часы.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.09.2017, 23:05
Ответы с готовыми решениями:

Множественное наследование, виртуальные функции...
Помогите пожалуйста разобраться... 1. В классах есть переопределенные виртуальные функции класса...

Наследование и виртуальные функции
Всем привет. Может кто, пожалуйста, объяснить одну строчку из задания? Не понимаю, что именно нужно...

Наследование и виртуальные функции
Всем здарова. Есть пару косяков в коде, но я их не могу найти. Быть может вы найдёте их? Вот код:...

Наследование и виртуальные функции
Определить иерархию классов (игрушка, продукт, товар, молочный продукт). Определить в классе...

1
284 / 232 / 114
Регистрация: 07.09.2016
Сообщений: 584
25.09.2017, 00:15 2
а не пробовали сделать так, чтобы она уже была инициализирована на момент использования? вот так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class abstr_emp
{
private:
  const std::string defaultString = "Nully";
 
  std::string fname;
  std::string lname;
  std::string job;
 
//  const std::string defaultString = "Nully";
public:
  abstr_emp() : fname{ defaultString }, lname{ defaultString }, job{ defaultString } {}
...
это проще, но дефолтная неменающаяся строка в виде мембера - это лишнее. в виде статической константы или в виде
получения ее из функции - это куда правильнее. ей не место среди членов класса.
0
25.09.2017, 00:15
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.09.2017, 00:15
Помогаю со студенческими работами здесь

Наследование и виртуальные функции
Общая постановка. Программа должна содержать: - базовый класс Х, включающий два элемента х1, х2...

Наследование. Виртуальные функции
Всем привет. Недавно изучил раздел , который в названии. Вы могли бы дать задачку по выше указанной...

Наследование и виртуальные функции
⦁ Определить иерархию классов (в соответствии с вариантом). ⦁ Определить в классе...

Наследование и виртуальные функции
Написать программу в которой создается иерархия классов.Включить полиморфные обьекты в связанный...


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

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru