Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.64/25: Рейтинг темы: голосов - 25, средняя оценка - 4.64
1 / 1 / 0
Регистрация: 07.08.2014
Сообщений: 72

Как правильно реализовать множественное наследование?

15.09.2016, 22:59. Показов 5902. Ответов 32
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет. Нужна помощь. Вот смотрите. Имеется простой класс. От него порождаются два класса-наследника. А от этих двух классов порождается один класс. Так скажем, наследник третьего поколения. В каждом классе имеется метод Show() для отображения данных класса. Я сейчас их вам представлю.
Метод Show() базового класса:
C++
1
2
3
4
5
void Person::Show()
{
    cout << "Имя: " << name << endl;
    cout << "Фамилия " << lastname << endl;
}
Метод Show() первого класса 2-го поколения:
C++
1
2
3
4
5
6
void Sniper::Show()
{
    Person::Show();
    cout << "Время приведения в боевую готовность: " << Draw() << endl;
    cout << "Насечек: " << nas << endl;
}
Draw() выводит рандомное число.
Метод Show() второго класса 2-го поколения:
C++
1
2
3
4
5
void Poker::Show()
{
    Person::Show();
    cout << "Он достал карту: " << Draw() << endl;
}
Метод Show() класса 3-го поколения я написать не могу. Он должен вывести данные базового класса, также данные двух потомков (Там в принципе одна переменная класса Sniper), а также числа от двух методов Draw() (Один от одного предка, один от другого). Это можно сделать без проблем, если вписать все туда вручную типа так:
C++
1
2
3
4
5
6
7
void Bad::Show()
{
    Person::Show();
    cout << "Время приведения в боевую готовность : " << Sniper::Draw() << endl;
    cout << "Насечек: " << Sniper::nas << endl;
    cout << "Он достал карту: " << Poker::Draw() << endl;
}
Но как это можно сделать более удобнее?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
15.09.2016, 22:59
Ответы с готовыми решениями:

Множественное наследование(правильно ли...образец)
В книге Павловская Т.А. нарвался на такой код #include &lt;iostream&gt; using namespace std; class A{ // Родительский класс... ...

Множественное наследование
Листинг: #include &lt;iostream&gt; using namespace std; class Person{private: string Fname,Sname,years;}; class Student{private:...

Множественное наследование
Добрый вечер! Выполняю дом. работу в плюсах по ООП. Не могу разобраться с реализацией функций. Задание: Имеются два класса от...

32
16.09.2016, 00:38
Студворк — интернет-сервис помощи студентам

Не по теме:

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
но ведь слушатель тоже интерфейс
не факт.
и потом, это не принципиально.
принципиально, что до тех пор, пока наследник реализует связь "я являюсь" - все будет нормально.
безотносительно к множественности наследования.

и наоборот - если логическая связь будет нарушена, получим УГ,
так же вне зависимости от множественности наследования.



Не по теме:

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
_name допустимая запись.
мина замедленного действия.

0
16.09.2016, 00:43

Не по теме:

Цитата Сообщение от hoggy Посмотреть сообщение
мина замедленного действия.
Кто там говорил про аргументы?) В private полях я даже могу оставить ссылку на голую Дженифер Лоппес - всё разрешено) Проверял

Цитата Сообщение от hoggy Посмотреть сообщение
не факт.
А что мешает не писать УГ и сделать через интерфейсы?

0
16.09.2016, 00:50

Не по теме:

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Кто там говорил про аргументы?)
выдержка из спецификации стандарта - уже не аргумент?
глобальные переменные могут вступать в коллизию с данными-членами,
это тоже не аргумент?
http://ideone.com/2E6IZ


Не по теме:


Цитата Сообщение от rikimaru2013 Посмотреть сообщение
А что мешает не писать УГ и сделать через интерфейсы?
предположим, что в примере с системой,
listner_mouse, и listner_keyboard не являются интерфейсами.
а являются обычными не абстрактными классами.

вы считаете, что код стал УГ?
какие то проблемы в дизайне наблюдаете?

с чего вообще у вас возникло такое мнение,
что если наследоваться от не интерфейса,
то обязательно будет УГ?

и вообще, какая вам разница от чего наследоваться:
интерфейса, или полноценного класса?

0
1 / 1 / 0
Регистрация: 07.08.2014
Сообщений: 72
16.09.2016, 09:00  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
нет. не может.
если хотите состояться как программист - вам придется это понять.
исходной код - это мысли программиста.
его можно читать, как книгу.
но когда в книге написан бред (отсутствует логика в повествовании),
то читать такую книгу уже не хочется.
нафиг нужно тратить время на всякий бред.
Я лишь учусь основной логике программирования. Мне нужно понять суть (в данном случае множественного наследования). Я же попросил помочь с методами, но тут придрались к названиям...

Добавлено через 6 минут
Предоставляю весь код. Классы:
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
#include <string>
#include <iostream>
 
using namespace std;
 
class Person            //Базоый класс
{                       //Содержит имя, фамилию и метод для их вывода.
public:
    Person();               
    Person(string, string);
    Person(char *, char *);
    Person(Person &);
    ~Person();
 
    void Show();
 
private:
    string name;
    string lastname;
};
class Sniper : public Person        //Класс наследник от Персон. 
{                                   //Добавляет новый член nas, также расширяет метод Show
public:                             //Метод Draw выводит время перехода в боевую готовность рандомно
    Sniper();
    Sniper(string a, string b, int x);
    ~Sniper();
 
    void Show();
protected:
    double Draw();
    int nas;
};
class Poker : public Person
{
public:
    Poker();
    Poker(string a, string b) : Person(a, b) {}
    ~Poker();
    void Show();
 
protected:
    double Draw();
};
class Bad : public Sniper, public Poker
{
public:
    Bad();
    Bad(string, string, int nas);
    ~Bad();
 
    void Show();
    double Gdraw() { return Sniper::Draw(); }
    double Cdraw() { return Poker::Draw(); }
private:
 
};
Методы классов:
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
#include <iostream>
#include <string>
#include <cstring>
#include <ctime>
#include <fstream>
#include "Header.h"
#include <sstream>
 
using namespace std;
 
//Конструкторы и деструктор
Person::Person()
{
}                   
Person::~Person()
{
}
Person::Person(string a, string b)
{
    name = a;
    lastname = b;
}
Person::Person(char * a, char * b)
{
    name = a;
    lastname = b;
}
Person::Person(Person & a)
{
    name = a.name;
    lastname = a.lastname;
}
//Метод для отображения класса Person
void Person::Show()
{
    cout << "Имя: " << name << endl;
    cout << "Фамилия " << lastname << endl;
}   
 
 
//Методы класса Снайпер
//Конструкторы и деструктор
Sniper::Sniper()
{
}
Sniper::~Sniper()
{
}
//Берет три переменные, две последние отправляет в конструктор базового класса.
Sniper::Sniper(string a, string b, int x) : Person(a, b)
{
    nas = x;
}
double Sniper::Draw()
{
    srand(time(NULL));
    return rand() % 50;
}
//Отображение всех данных класса, в том чилсе и базового
void Sniper::Show()
{
    Person::Show();
    cout << "Время приведения в боевую готовность: " << Draw() << endl;
    cout << "Насечек: " << nas << endl;
}
 
 
 
//Методы класса Poker
Poker::Poker()
{
}
Poker::~Poker()
{
}
//Отображение данных класса, в том числе и базового
void Poker::Show()
{
    Person::Show();
    cout << "Он достал карту: " << Draw() << endl;
}
//Радномная карта
double Poker::Draw()
{
    srand(time(NULL));
    return rand() % 53;
}
 
 
//Методы класса Bad
Bad::Bad()
{
}
Bad::Bad(string a, string b, int nas) : Sniper(a,b,nas)
{
}
Bad::~Bad()
{
}
void Bad::Show()
{
    Person::Show();
    cout << "Время приведения в боевую готовность : " << Gdraw() << endl;
    cout << "Насечек: " << Sniper::nas << endl;
    cout << "Он достал карту: " << Cdraw() << endl;
}
Сама программа:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>
#include "Header.h"
#include <cctype>
#include <fstream>
 
using namespace std;
 
int main()
{
    setlocale(LC_ALL,"Russian");
    
    Bad x("Sacha", "Perkow", 68);
    x.Show();
 
 
    system("PAUSE");
}
Добавлено через 1 минуту
Вообще, все работает как надо. Но я лишь спрашиваю, как можно лучше написать метод Show() последнего класса, чтобы повторно использовать код, а не переписывать все по новой и отдельно, как сделал я.
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
16.09.2016, 09:15
Цитата Сообщение от Саша Перков Посмотреть сообщение
Я лишь учусь основной логике программирования. Мне нужно понять суть (в данном случае множественного наследования). Я же попросил помочь с методами, но тут придрались к названиям...
Множественное наследование
Класс может иметь более одного
непосредственного базового класса, то есть два и более классов могут указываться после двоеточия
в объявлении класса. Рассмотрим задачу моделирования, в которой параллельно
выполняющиеся задания представлены классом Task, а сбор данных и
визуализация представлены классом Displayed. Далее мы можем определить класс
моделируемых сущностей, например класс Satellite (спутник):
C++
1
2
3
4
class Satellite : public Task, public Displayed 
{ 
    //... 
};
Использование более одного непосредственного базового класса принято
называть множественным наследованием (multiple inheritance). В противоположность
этому наличие единственного непосредственного базового класса называют одиночным
наследованием (single inheritance).
Кроме операций, определенных специально для Satellite, мы можем
использовать объединение операций классов Task и Displayed. Например:
C++
1
2
3
4
5
6
void f(Satellited& s) 
{ 
    s. draw () ; // Displayed::draw()
    s. delay A0) ; // Task::delay() 
    s. transmit () ; // Satellite: :transmit() 
}
Аналогичным образом, функциям можно передавать Satellite вместо ожидаемых
ими Task или Displayed. Например:
C++
1
2
3
4
5
6
7
void highlight (Displayed*) ; 
void suspend (Task*) ; 
void g(Satellite* p) 
{ 
highlight (p); // передать указатель на Displayed-частъ Satellite 
suspend (p); // передать указатель на Task-часть Satellite 
}
Реализация этого механизма предполагает несложные приемы от компилятора,
которые обеспечивают видимость разных частей Satellite в функциях, ожидающих
Task или Displayed, соответственно.
Виртуальные функции работают как обычно. Например:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class Task 
{ 
    virtual void pending () = 0; 
}; 
class Displayed 
{ 
    virtual void draw () = 0; 
}; 
class Satellite : public Task, public Displayed 
{ 
    void pending () ; //замещаем Task::pending() 
    void draw () ; // замещаем Displayed::draw() 
};
Это гарантирует, что функции Satellite::draw() и Satellite:: pending() будут
вызваны для Satellite, проинтерпретированного как Displayed и Task, соответственно.
В случае одиночного наследования у программиста будет более ограниченный
выбор для реализации классов Displayed, Task и Satellite. Satellite в таком случае
может быть либо Task, либо Displayed, но не обоими сразу (если только Task не был
реализован как производный класс от Displayed, или наоборот). Выбор любой из
этих альтернатив означает потерю гибкости.
А кому вообще может потребоваться такой вот класс Satellite? На самом деле,
это вполне реальный пример (даже если кому-то он показался абсолютно
искусственным). Существовала (а может и сейчас еще существует) программа, построенная
по схеме, примененной здесь для иллюстрации множественного наследования. Она
использовалась для исследования построения коммуникационных систем,
включающих спутники (satellites), наземные станции и т.д. В рамках этой модели можно
отвечать на вопросы об интенсивности трафика, находить правильную реакцию на
ситуацию выведения из строя наземной станции (например, из-за торнадо),
отыскивать оптимальное соотношение между нагрузкой на спутниковую связь и связь
по Земле и т.д. Такое интенсивное моделирование предполагает множество
операций вывода информации и множество отладочных операций. Также, нам нужно
хранить состояние объектов Satellite и их подкомпонентов для анализа, отладки
и восстановления после ошибок.
The
C++
Programming
Language
Special Edition
Bjarne Stroustrup
AT&T Labs
Murray Hill, New Jersey

Добавлено через 7 минут
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
вы же понимаете, что у вас в коде не множественное наследование, а тот способ реализации интерфейса в С++ ?
не понимаю, если я наследую два и более класса, значит я использую множественное наследование? или как? Играет роль закрытое или открытое наследование?
1
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
16.09.2016, 09:27
Цитата Сообщение от Саша Перков Посмотреть сообщение
Предоставляю весь код. Классы:
А виртуальность где? У вас же в книжке виртуальное ромбовидное наследование задано. Без нее у вас в нижнем классе
Цитата Сообщение от Саша Перков Посмотреть сообщение
Bad
ромба будет содержаться две персоны, т.е. это уже сиамский близнец какой-то. Ему тогда надо два имени и две фамилии задавать!
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
16.09.2016, 11:09

Не по теме:

hoggy, так я выспался и готов к раунду номер 2!!!

Цитата Сообщение от hoggy Посмотреть сообщение
выдержка из спецификации стандарта - уже не аргумент?
В современном мире при подсветках IDE - это не проблема.
Да и где вы видели глобальные переменные с _NAME ?
Вы просто хотите видеть их таких, чтобы оспорить _name.
А как вы тогда пишите? m_name? А вы знаете, что это бомба
замедленного действия. Вот пример:
http://ideone.com/wUHKME

Получается переменные класса лучше вообще не использовать?
Это как услышать с ваших уст : "статические переменные лучше
не использовать.". А что тогда использовать? "Ничего!".

Цитата Сообщение от hoggy Посмотреть сообщение
вы считаете, что код стал УГ?
какие то проблемы в дизайне наблюдаете?
Так какие переменные в этой классе? Чего интерфейса обычного
мало. Что нам мешает сделать качественную связь - зачем нам
гибрид этот?

Цитата Сообщение от hoggy Посмотреть сообщение
с чего вообще у вас возникло такое мнение,
что если наследоваться от не интерфейса,
то обязательно будет УГ?
Я уже отвечал на этот вопрос в начале поста №20. Попробовал - не понравилось.

И опять же:
17.4.3.1.2 Global names
Each name that contains a double underscore (_ _) or begins with an underscore
followed by an uppercase letter (2.11) is reserved to the implementation for any use.
Кто будет начинать имя переменной с заглавной буквы? Получается
я позитивно отношусь к _name потому, что подсознательно обладаю
манерой коддинга, где переменные всегда с малой буквы?


Цитата Сообщение от hoggy Посмотреть сообщение
и вообще, какая вам разница от чего наследоваться:
интерфейса, или полноценного класса?
Ну для меня есть разница - ведь как я уже говорил в одном случаи множественное
наследование, в другом реализация интерфейсов. Даже вот ваш пример через
слушатели - они больше, я уверен, будут похожи на классы-хелперы:
маленькие, 1-2 переменных, 1-4 метода.
Да таких даже тяжело назвать проблемой ... Но если они разрастутся и у нас класс
будет иметь 2 родителя гиганта - это я считаю не правильно. Чтобы вы в третий раз
мне не задали один и тот же вопрос: вы понимаете мою философию про унаследовать
класс и реализовать интерфейс??



Добавлено через 3 минуты
Цитата Сообщение от _stanislav Посмотреть сообщение
не понимаю
тогда прочтите мои сообщения - там найдете моё виденье - и вопросы далее отпадут.
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
16.09.2016, 11:13
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
вы понимаете мою философию про унаследовать
класс и реализовать интерфейс??
Теперь понятно что ты имел ввиду, просто в реализации интерфейса (в пятом посте) лежит механизм наследование, конкретно множественного наследования.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
16.09.2016, 11:15
_stanislav, это связано напрямую с тем, что нету понятия интерфейс в стандарте/языке С++ в 2016 году.
0
1 / 1 / 0
Регистрация: 07.08.2014
Сообщений: 72
17.09.2016, 16:40  [ТС]
Цитата Сообщение от Mr.X Посмотреть сообщение
А виртуальность где? У вас же в книжке виртуальное ромбовидное наследование задано. Без нее у вас в нижнем классе
Вот в этои и проблема, что я плохо понимаю как ее реализовать. У вас нет хорошего гайда по виртуальности?

Добавлено через 47 секунд
Цитата Сообщение от Mr.X Посмотреть сообщение
ромба будет содержаться две персоны, т.е. это уже сиамский близнец какой-то. Ему тогда надо два имени и две фамилии задавать!
Дело в том, что объект класса Bad является и снайпером и игроком в покер, поэтому я использую множественное наследование.
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
17.09.2016, 17:23
Цитата Сообщение от Саша Перков Посмотреть сообщение
Вот в этои и проблема, что я плохо понимаю как ее реализовать. У вас нет хорошего гайда по виртуальности?
Да все элементарно. Если хотите, чтобы все подобъекты базового класса сливались в потомках в один, то наследуете от этого класса виртуально. В любом учебнике это описано.
Цитата Сообщение от Саша Перков Посмотреть сообщение
Дело в том, что объект класса Bad является и снайпером и игроком в покер, поэтому я использую множественное наследование.
Ну так о нем и речь. Сколько раз наследуется базовый класс, столько его подобъектов и будет содержаться в потомке. У вас в Bad содержится две персоны. Чтобы была одна, надо виртуально от персоны всем наследоваться.
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
17.09.2016, 19:49
Саша Перков, кстати вот хорошая статья, советую прочитать.
Вложения
Тип файла: rar Виртуальное наследование.rar (76.8 Кб, 11 просмотров)
0
"C with Classes"
2022 / 1404 / 523
Регистрация: 16.08.2014
Сообщений: 5,885
Записей в блоге: 1
17.09.2016, 20:57
и еще хорошая статья.
Вложения
Тип файла: rar Виртуальные функции.rar (73.0 Кб, 7 просмотров)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
17.09.2016, 20:57

Множественное наследование
Есть два класса Human(fname, lname) и класс Employee c чисто виртуальными функц (зарплата и печать). На базе этих классов нужно создать...

Множественное наследование
Возник вопрос по теме множественное наследование. Вот скажем у нас определены классы: class Animal{ public: int...

Множественное наследование
Всем привет. Не могу понять следующий подход. Объясните немного, дальше я сам разберусь. Есть класс данных Data. Есть...

Множественное наследование
Здравствуйте! Делаю следующее задание по подготовке к экзамену по С++. Пока только начал. Вкратце - есть абстрактный класс. Его...

Множественное наследование в С++
Столкнулся с такой проблемой: class D{ ... public: ... void setD(); ... }; class Dd : public D{ ...


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

Или воспользуйтесь поиском по форуму:
33
Ответ Создать тему
Новые блоги и статьи
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version 1. 2003 - 06 - Designing Virtual Worlds (1st Edition) Автор: Richard A. Bartle | Объем: 768 стр. Ссылки: Amazon . . .
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров". Задача: Запрет инициалов. Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
Про "Windows must die!"
kumehtar 04.11.2026
Знаете, чет накатило. . . . Когда-то это было почти боевым кличем: мол, нормальный человек сидит на DOS, OS/ 2 или Linux, а вот это вот - Must Die. А теперь человек произносит «мастдай» с усмешкой - и. . .
Красочные поля с номером страницы svg+background-image
russiannick 04.11.2026
Красочные поля с номером страницы не менее важны чем в эпоху бумажных книг. Посему спешу представить почтеннейшей публике этот важный инструмент который эти поля и формирует. В процессе разработки. . .
Вступаем в новую фазу генерации favicons, векторную.
russiannick 02.11.2026
Теперь нет нужды скрывать что используется простой svg. Исходный код изображения помещаем в поле и жмем кнопку. Исходник преобразуется в вид корректный для помещения в favicon или в url(). Нажатие. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru