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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 16, средняя оценка - 4.88
newbie666
Заблокирован
#1

Можно ли как-то в дочернем классе получить указатель родителя? - C++

09.04.2014, 17:11. Просмотров 2585. Ответов 40
Метки нет (Все метки)

У меня тут появилась мыслишка
В любом классе есть так сказать скрытый указатель на самого себя - this, а можно ли как то получить в дочернем классе указатель на родительский класс?
P.S.: без всякой явной передачи в конструктор дочернего класса указателя на базовый ...

Добавлено через 12 минут
ладно, опять же забейте, просто было интересно, есть ли возможность в дочернем классе получить указатель на базовый и присвоить какое то значение по этому указателю, например:
(конструктор дочернего)
C++
1
2
3
4
Child()
{
   (Base*)this->x = 4;
}
ну конечно же так не работает
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.04.2014, 17:11
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Можно ли как-то в дочернем классе получить указатель родителя? (C++):

Как обьявить переменную в одном классе и что бы ее было видно в дочернем классе - C++
У меня есть основной класс с названием Root один из его членов наследует дочерний класс SubRoot. Скажите как объявить, что бы один из...

Запуск конструктора родителя в дочернем конструкторе - C++
Вобщем имеется два класса class Coma{ public: double x,y; Coma(){ x=0; y=0; } Coma(int x, int y){ this->x=x;

Как получить ссылку на указатель или указатель на указатель в массиве? - C++
В процессе реализации сортировки пузырьком натолкнулся на такую проблему: как поменять значения указателей, передаваемых в функцию. Если...

Ошибка в дочернем классе - C++
Не могу найти ошибку в дочернем классе, возможно не правильно написать main Задание и код: Код нужно переписывать в сообщение Только...

Перегрузка fstream в дочернем классе - C++
h class Child:public StudentsBD{ friend fstream &operator<<( fstream& , string & ); friend fstream &operator>>( fstream& , string...

Изменение информации в дочернем классе, через ссылку - C++
Подскажите, есть класс class Class1 В конструкторе я создаю структуру, которая будет хранить в себе ссылки на все классы...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,094
10.04.2014, 21:40 #31
Цитата Сообщение от newbie666 Посмотреть сообщение
Можешь функции разнести по разным классам, тогда основной класс будет создавать объект того или иного типа в зависимости от выбранного пользователем типа коннекта ..
В этом и соль. Как организовать этот выбор? Через if или switch? И что, при добавлении нового типа источника данных каждый раз лопатить этот код и добавлять? К тому же - этот код библиотечный (представление). А модель мы пишем сами. Как библиотека узнает о твоем типе, если ты его сам написал, не пользуясь наследованием как бесполезной вещью? И как она сможет его распознать, если проверки на этот тип там нет. Ну да, можно передавать вместе с типом еще и функцию (callback), которая разберется как выбрать. Мы все усложняем и усложняем код, а задача-то не решается. И когда мы все это реализуем, преодолев все трудности и игнорируя наследование, то мы обнаружим, сюрприз, что реализовали полиморфизм. Только своими руками.
А про обязательность абстрактных классов никто не говорил. Я говорил про полиморфизм в целом.

Цитата Сообщение от newbie666 Посмотреть сообщение
да никак - самолёты слишком простая задача, которая пишется в рамках одного класса )))
Это еще почему? Разве в мире существует только один самолет? Или ты предлагаешь все характеристики задавать состоянием? Но это дикая избыточность. Кроме того это потенциально может нарушить инвариант. Если заданные значения противоречат друг другу при компоновке объекта значениями (например выбрали материал - дерево, а двигатель - реактивную турбину). Понадобится писать дополнительный код проверки, чтобы не допускать такого. В общем опять сложности на пустом месте. Ведь мы ничего не выигрываем таким подходом.
1
newbie666
Заблокирован
10.04.2014, 21:56  [ТС] #32
Цитата Сообщение от DrOffset Посмотреть сообщение
В этом и соль. Как организовать этот выбор?
ну вот покажи мне пример из пары строк, где это необходимо ... про что ты тут пишешь ....
P.S.: про самолёты - ноу коммент, комменты будут когда покажешь хоть пару строк кода с классами, где реально необходимо наследование и без него никак или как - но сложнее ...
0
0x10
2464 / 1636 / 238
Регистрация: 24.11.2012
Сообщений: 4,031
10.04.2014, 21:58 #33
Цитата Сообщение от newbie666 Посмотреть сообщение
пользователю то похрену как там чё внутри Qt устроено
А Qt писали не люди? Это такая данность свыше, материализовавшаяся сама по себе?
Внезапно библиотеки тоже пишутся людьми. И написать более-менее универсальную библиотеку, которую можно использовать в разных приложениях, задача не всегда простая.

Цитата Сообщение от newbie666 Посмотреть сообщение
Ну совсем не обязательно делать
Продолжая рассуждения, можно вообще весь код написать в main. Только как потом это поддерживать?
1
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,094
10.04.2014, 22:08 #34
Цитата Сообщение от newbie666 Посмотреть сообщение
ну вот покажи мне пример из пары строк, где это необходимо
Ты же говорил, что Qt знаешь. Открой любой пример на MVC и посмотри. Преимущество в том, что полиморфные вызовы не накладывают на библиотеку обязанности знать что за тип на самом деле используется. Это очень удобно и все остальные варианты банально технически сложнее. Но даже после реализации без наследования и виртуальности - получится тот же самый полиморфизм, только врукопашную (да, полиморфизм на if`ах).

Или ты хочешь такой пример, который вообще без виртуальных функций и наследования реализован быть не может в принципе? Ну так ты это, вспомни про то, что полиморфизм - это общее понятие. Оно даже к языку не привязано - это понятие из ООП. Поэтому любая такая задача, в которой есть работа с разнородными данными одинаковым образом, - сведется к полиморфизму. Просто на С - это будет больше кода и указатели на функции в таблицах. А на С++ есть готовый инструмент в виде наследования и виртуальных вызовов. Поэтому не понято с чего бы нам, имея инструмент, городить свои if`ы и(или) таблицы вызовов.

Ну и я уже привел тебе пример свой, он тебе чем-то не подошел. Но и варианта своего ты не предложил.
1
newbie666
Заблокирован
10.04.2014, 22:24  [ТС] #35
с утра отпишусь, но пока аргументы в пользу полиморфизма, нежели в пользу какого - то оптимального паттерна для конкретной задачи, выглядят сомнительно ....
Цитата Сообщение от DrOffset Посмотреть сообщение
Ты же говорил, что Qt знаешь.
Где это я говорил? Но Qt я всё таки знаю

Вот можно реально пример какой - нибуть хотя бы на двух трёх классах из пары строк, где было бы видно, что О-О да, тут с полиморфизмом реально круче, удобней и меньше строк кода ....
0
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,094
11.04.2014, 10:30 #36
Цитата Сообщение от newbie666 Посмотреть сообщение
нежели в пользу какого - то оптимального паттерна
Ты хотя бы один паттерн-то назови?
Цитата Сообщение от newbie666 Посмотреть сообщение
выглядят сомнительно
То есть ты никогда не применял этот подход? Если не применял, то тогда не понятна твоя уверенность в соей правоте.

Цитата Сообщение от newbie666 Посмотреть сообщение
Но Qt я всё таки знаю
Ну так в чем проблема поcмотреть на MVC?

Добавлено через 30 минут
newbie666,
Ну на вот тебе пример. Основная идея в main();
С полиморфизмом.

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
class FlyingMachine
{
public:
    virtual void tryToFly(Pilot const &) = 0;
};
 
class Helicopter : public FlyingMachine
{
public:
    Helicopter(Position const & pos)
        : engine_()
        , rotor_(engine_), tailRotor_(engine_)
        , ctrl_(engine_, rotor_, tailRotor_)
    { }
 
    void tryToFly(Pilot const & pilot)
    {
        // пилом проверяет систему
        pilot.enable(ctrl_, HeliControlPanel::checkSystem);
        // запуск двигателя
        pilot.enable(ctrl_, HeliControlPanel::startEngine);
        // ждем нужной скорости
        pilot.wait(ctrl_, HeliControlPanel::setEngineTakeoffMode); 
        // тяга вверх,
        pilot.enable(ctrl_, HeliControlPanel::up);
        // режим полета
        pilot.enable(ctrl_, HeliControlPanel::setEngineFlyMode);
    }
 
private:
// system
    TurboShaft engine_;
 
    Rotor     rotor_;
    TailRotor tailRotor_;
 
    HeliControlPanel ctrl_;
};
 
class Aeroplane : public FlyingMachine
{
public:
    Aeroplane(Position const & pos)
        : leftEngine_(), rightEngine_()
        , ctrl_(leftEngine_, rightEngine_)
    { }
 
    void tryToFly(Pilot const & pilot)
    {
        pilot.busy();
 
        // пилом проверяет систему
        pilot.enable(ctrl_, JetControlPanel::checkSystem);
        // запуск двигателя
        pilot.enable(ctrl_, JetControlPanel::startEngine);
        // перевод двигателя в режим взлета
        pilot.enable(ctrl_, JetControlPanel::setEngineTakeoffMode);
        // разгон и ожидание набора нужной скорости
        pilot.wait(ctrl_, JetControlPanel::racing);
        // выпустить закрылки
        pilot.enable(ctrl_, JetControlPanel::releaseFlaps);
        // тяга вверх
        pilot.enable(ctrl_, JetControlPanel::up);
        // режим полета
        pilot.enable(ctrl_, JetControlPanel::setEngineFlyMode);
    }
 
private:
// system
    TurboJet leftEngine_;
    TurboJet rightEngine_;
 
    JetControlPanel ctrl_;
};
 
// Теперь использование
int main()
{
    // некая функция, возвращает эскадрилью летательных аппаратов
    std::vector<FlyingMachine *> squadron = takeSquadron();
    // запустим их в воздух
    // для простоты не сажаю их непосредственно в машину, хотя можно было бы,
    // только кода станет больше.
    for(size_t i = 0, size = squadron.size(); i < size; ++i)
    {
        Pilot & pilot = getFreePilot(); // получим свободного
        squadron[i]->tryToFly(pilot);
        pilot.busy(); // занят
    }
    // Мы можем спокойно добавлять любые аппараты в эскадрилью - этот код не нужно будет менять
}

Без полиморфизма (на самом деле он там есть, только реализованный вручную).

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
// Теперь без наследования и полиморфизма,
// классы оставляю прежними, только убираю наследование и базовый класс
 
class Helicopter
{
public:
    Helicopter(Position const & pos)
        : engine_()
        , rotor_(engine_), tailRotor_(engine_)
        , ctrl_(engine_, rotor_, tailRotor_)
    { }
 
    void tryToFly(Pilot const & pilot)
    {
        // пилот проверяет систему
        pilot.enable(ctrl_, HeliControlPanel::checkSystem); // throws system_error, если ошибка
        // запуск двигателя
        pilot.enable(ctrl_, HeliControlPanel::startEngine); // throws engine_fail, если отказ движка
        // ждем нужной скорости
        pilot.wait(ctrl_, HeliControlPanel::setEngineTakeoffMode); //включаем взлетный режим
        // тяга вверх,
        pilot.enable(ctrl_, HeliControlPanel::up); // throws flying_fail, если внезапное препятствие
        // режим полета
        pilot.enable(ctrl_, HeliControlPanel::setEngineFlyMode);
    }
 
private:
// system
    TurboShaft engine_;
 
    Rotor     rotor_;
    TailRotor tailRotor_;
 
    HeliControlPanel ctrl_;
};
 
class Aeroplane
{
public:
    Aeroplane(Position const & pos)
        : leftEngine_(), rightEngine_()
        , ctrl_(leftEngine_, rightEngine_)
    { }
 
    void tryToFly(Pilot const & pilot)
    {
        // пилот проверяет систему
        pilot.enable(ctrl_, JetControlPanel::checkSystem);
        // запуск двигателя
        pilot.enable(ctrl_, JetControlPanel::startEngine);
        // запуск двигателя
        pilot.enable(ctrl_, JetControlPanel::setEngineTakeoffMode);
        // разгон и ожидание набора нужной скорости
        pilot.wait(ctrl_, JetControlPanel::racing);
        // выпустить закрылки
        pilot.enable(ctrl_, JetControlPanel::releaseFlaps);
        // тяга вверх
        pilot.enable(ctrl_, JetControlPanel::up);
        // режим полета
        pilot.enable(ctrl_, JetControlPanel::setEngineFlyMode);
    }
 
private:
// system
    TurboJet leftEngine_;
    TurboJet rightEngine_;
 
    JetControlPanel ctrl_;
};
 
// Теперь использование
int main()
{
    // здесь первая трудность, как этот список вернуть в одном массиве?
    // Можно выкрутиться, написав класс FlyingMachineHolder, пусть он хранит тип аппарата и указатель на него (void*)
 
    // некая функция, возвращает эскадрилью летательных аппаратов
    std::vector<FlyingMachineHolder> squadron = takeSquadron();
    // запустим их в воздух
    // для простоты не сажаю их непосредственно в машину, хотя можно было бы.
    // Только кода станет больше.
    for(size_t i = 0, size = squadron.size(); i < size; ++i)
    {
        Pilot & pilot = getFreePilot(); // получим свободного
 
        switch(squadron[i].type())
        {
        case M_HELICOPTER:
            // преобразование можно запихать в шаблон (без него будет еще хуже)
            // шаблоны ведь можно использовать? :)
            squadron[i].toConcreteMachine<Helicopter>()->tryToFly(pilot);
            break;
        case M_AERORPLANE:
            squadron[i].toConcreteMachine<Aeroplane>()->tryToFly(pilot);
            break;
        }
        pilot.busy(); // занят
    }
    // Если у нас таких аппаратов хотя бы 15 разных, то switch вырастет еще на 13 веток.
}

Модель упрощена, иначе придется реализовывать слишком много. Всего лишь демонстрация.
Это нужно учитывать.
Классы Pilot и характеристики внутренностей воздушных судов и т.д. не привожу, их реализация не влияет на идею.
Способы взлета вертолета и самолета разные. Алгоритм, который назначает машины к взлету не обязан знать про это. Так же как и диспетчеру все равно на какие конкретные кнопки нажимает пилот, главное чтобы он соблюдал нормы полета. Первый пример устойчив к расширению парка машин, второй - нет. Это основное и главное преимущество.
Код не компилируемый, предназначен для демонстрации идеи и все.
1
newbie666
Заблокирован
11.04.2014, 10:52  [ТС] #37
DrOffset, не ну ты уж меня за нуба то не держи, несмотря на мой ник
Что такое полиморфизм я прекрасно знаю.
Но вот например, как быть с полиморфизмом, ну допустим даже с твоими флаинг машинами, если им нужно обмениваться данными между друг другом?
0
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,094
11.04.2014, 11:41 #38
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от newbie666 Посмотреть сообщение
Но вот например, как быть с полиморфизмом, ну допустим даже с твоими флаинг машинами, если им нужно обмениваться данными между друг другом?
В общем случае через двойную диспетчеризацию например.

На примере же летательных апаратов: какими данными могут они обмениваться? Обычно это радиосвязь. Ну тут все просто. Есть общий канал, в каждом классе есть модуль "радиостанция". Радиостанция посылает в этот канал несколько параметров. Скажем частота, позывной адресата и сообщение. Класс "канал связи" инициирует передачу и другой летательный аппарат ловит сообщение через свою радиостанцию.
Даже если не применять наследование и полиморфизм, то здесь все равно придется делать третий класс, который занимается диспетчеризацией сообщений. Не хранить же ссылки на все адресаты внутри каждого объекта? Это опять же приведет к проблемам, если появляется новый объект, с которым нужно наладить связь.
1
newbie666
Заблокирован
11.04.2014, 11:50  [ТС] #39
DrOffset, ладно, убедил, в некоторых случаях полиморфизм может дать профит
спасибо за потраченное время, поставлю ка я тебе во всех постах по плюсу ...
1
Бендерродригез
Сгибальщик
42 / 42 / 3
Регистрация: 18.05.2013
Сообщений: 220
Завершенные тесты: 1
11.04.2014, 12:13 #40
Если надо изменить переменную базового класса разом для всех дочерних, то чем плохи static-члены?
0
newbie666
Заблокирован
11.04.2014, 12:26  [ТС] #41
не люблю я бендеров ))))
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.04.2014, 12:26
Привет! Вот еще темы с ответами:

Использование переменных базового класса в дочернем классе - C++
Доброго времени суток. Подскажите пожалуйста как в классе SumbString работать с переменными(string s;int z ; ) класса factory ? Мне...

Не могу в дочернем классе вызвать protected метод - C++
Всем привет! Начал писать одну программку, и столкнулся со следующей проблемой: у меня пока 2 класса: MemObject и Vector, где Vector...

R6025 pure virtual function call при вызове метода, реализованного в дочернем классе - C++
Всем привет. Вот такая ошибка у меня возникает при вызове метода, который реализован в дочернем классе, но потом он почему-то становится...

Как в main() создать указатель на функцию, которая находится в классе? - C++
В этом примере как определить указатель на функцию F()? class A { public: bool F(int &amp;a, int &amp;b) { return a&lt;b; } }; int...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
11.04.2014, 12:26
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru