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

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

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

Студворк — интернет-сервис помощи студентам
Имеется вот такой код :
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
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
24.09.2017, 23:05
Ответы с готовыми решениями:

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

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

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

1
284 / 232 / 114
Регистрация: 07.09.2016
Сообщений: 584
25.09.2017, 00:15
а не пробовали сделать так, чтобы она уже была инициализирована на момент использования? вот так
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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
25.09.2017, 00:15
Помогаю со студенческими работами здесь

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

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

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

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

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


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

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

Новые блоги и статьи
Оптимизация производительности Express.js бэкенда
Reangularity 23.05.2025
Express. js заслуженно остаётся одним из самых популярных инструментов для создания бэкенда, но даже он не застрахован от проблем с производительностью. Многие разработчики сталкиваются с ситуацией,. . .
Продвинутая обработка данных с LINQ в C#
stackOverflow 23.05.2025
LINQ (Language Integrated Query) — это фундаментальное изменение парадигмы работы с данными в C#. Простые запросы Where и Select знакомы любому разработчику, но настоящая мощь LINQ раскрывается в. . .
Инфраструктура PKI и сертификатов безопасности
Mr. Docker 23.05.2025
PKI (Public Key Infrastructure) — это невидимый фундамент цифрового доверия, без которого современный интернет просто рассыпался бы как карточный домик. За этой аббревиатурой скрывается целый. . .
Аутентификация OAuth в Python
py-thonny 22.05.2025
OAuth (Open Authorization) — это целый стандарт для делегированного доступа. Звучит занудно? Давайте проще: OAuth позволяет приложениям получать доступ к информации пользователя на сторонних сервисах. . .
Хеширование и соль паролей в веб-приложениях C#
stackOverflow 22.05.2025
Когда-то в начале своей карьеры я тоже грешил простейшими подходами к хранению паролей – MD5-хеширование казалось верхом защиты. Но технологии не стоят на месте, вычислительные мощьности растут, и. . .
Генераторы Python для эффективной обработки данных
AI_Generated 21.05.2025
В Python существует инструмент настолько мощный и в то же время недооценённый, что я часто сравниваю его с тайным оружием в арсенале программиста. Речь идёт о генераторах — одной из самых элегантных. . .
Чем заменить Swagger в .NET WebAPI
stackOverflow 21.05.2025
Если вы создавали Web API на . NET в последние несколько лет, то наверняка сталкивались с зелёным интерфейсом Swagger UI. Этот инструмент стал практически стандартом для документирования и. . .
Использование Linq2Db в проектах C# .NET
UnmanagedCoder 21.05.2025
Среди множества претендентов на корону "идеального ORM" особое место занимает Linq2Db — микро-ORM, балансирующий между мощью полноценных инструментов и легковесностью ручного написания SQL. Что. . .
Реализация Domain-Driven Design с Java
Javaican 20.05.2025
DDD — это настоящий спасательный круг для проектов со сложной бизнес-логикой. Подход, предложенный Эриком Эвансом, позволяет создавать элегантные решения, которые точно отражают реальную предметную. . .
Возможности и нововведения C# 14
stackOverflow 20.05.2025
Выход версии C# 14, который ожидается вместе с . NET 10, приносит ряд интересных нововведений, действительно упрощающих жизнь разработчиков. Вы уже хотите опробовать эти новшества? Не проблема! Просто. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru