Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.67/18: Рейтинг темы: голосов - 18, средняя оценка - 4.67
2544 / 1203 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
1

Вызов метода родителя

08.03.2016, 20:20. Показов 3666. Ответов 23
Метки нет (Все метки)

Добрый вечер,

как можно заставить метод "не забыть" вызвать этот же метод родителя ?


Есть такая "очень классная архитектура":
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <conio.h>
using namespace std;
 
//////////////////////////////////////////////////////////////////////////
struct Base
{
    virtual bool SceneOnKeyPressed(int key)
    {
        bool result = true;
        switch(key)
        {
            case '1':
            {
                cout << "Base processed key" << key << endl;
            }
                break;
            case '2':
            {
                cout << "Base processed key" << key << endl;
                result = false;
            }
                break;
            default:
            {
                result = false;
            }               
                break;
        }
        return result;
    }
};
//////////////////////////////////////////////////////////////////////////
struct Derivered : public Base
{
    typedef Base Parent;
    bool SceneOnKeyPressed(int key) override
    {
        bool result = true;
        if(!Parent::SceneOnKeyPressed(key))
        {
            switch(key)
            {
                case '2':
                {
                    cout << "Derivered processed key" << key << endl;                   
                }
                    break;
                case '3':
                {
                    cout << "Derivered processed key" << key << endl;
                }
                    break;
                default:
                {
                    result = false;
                }
                    break;
            }
        }       
        return result;
    }
};
//////////////////////////////////////////////////////////////////////////
int main()
{
    Base* ptr = new Derivered();
    while(true)
    {
        if(_kbhit())                                                
        {
            ptr->SceneOnKeyPressed(_getch());
            cout << endl;
        }
    }
}


Base и Derivered находятся в разных проектах и в разных *.lib файлах. Если Base решил отработать нажатую кнопку 'R', то Derivered не может претендовать на отработку этой кнопки.

Подскажите как Derivered "заставить не забыть" вызвать 'Base::SceneOnKeyPressed' ведь согласно VTABLE получит нажатость последний с иерархии, и Base с другого *.lib и не узнает об этом.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.03.2016, 20:20
Ответы с готовыми решениями:

Принудительный вызов метода родителя
#include &lt;iostream&gt; using namespace std; class A { public: virtual void f() { cout &lt;&lt;...

Вызов метода потомка через указатель на родителя
Всем доброго времени суток, никак не придумаю, как провернуть такое: Пишу простенькую игру на...

Наследование. Переопределение метода родителя
не работает конструкция вида: class AllFigureData { protected: int id; int x; int y;...

Вызов из потомка конструктор родителя
Как на с++ вызывается конструктор-родителя от конструктора-потомка. На яве так работает: ...

23
Модератор
Эксперт С++
11314 / 9294 / 5575
Регистрация: 18.12.2011
Сообщений: 24,795
08.03.2016, 20:24 2
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
if(!Parent::SceneOnKeyPressed(key))
А это разве не нужный Вам вызов?
0
2544 / 1203 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
08.03.2016, 20:26  [ТС] 3
zss, перечитайте пост. Спасибо.
1
Эксперт С++
1667 / 1039 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
08.03.2016, 20:31 4
В описанных условиях очевидно, что Derived должен добровольно вести себя хорошо и почтительно по отношению к родителям. Добиться повторяемости можно, сделав Derived шаблоном и описав там повторяющуюся часть функционала. Как конкретно описывать индивидуальное поведение и как различать инстанции - зависит от обстоятельств, можно просто выписывать реализации методов, можно параметризовать шаблон стратегиями, можно ещё как-то.
0
Don't worry, be happy
17206 / 10084 / 1945
Регистрация: 27.09.2012
Сообщений: 25,164
Записей в блоге: 1
08.03.2016, 20:32 5
rikimaru2013, может шаблонный метод, не виртуальный интерфейс помо(жет|гут)?
0
2544 / 1203 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
08.03.2016, 20:41  [ТС] 6
Цитата Сообщение от Nick Alte Посмотреть сообщение
описав там повторяющуюся часть функционала
А можно подробнее? Имплиминтация Base не известна Derivered и наоборот.

Croessmah, часть проекта где Base lib берёт на себя описание основных телодвижений, и если Derivered хочет "расширить" функционал он должен "не забыть" прокинуть к Base вызов.

Еще условный пример с жизни:
Поступает в универ военный (Человек -> Мужчина -> Военный) вызывается метод onEnterUniversity. Данный метод прокидывается по родителем: итого у военного как у человека запросят паспорт, у мужчины - военный билет, у военного - каску(не придумал).

Опять же пример с инициализацией - попросили инициализировать класс С (A -> B -> C) он заставит инициализироваться все состовляющие
0
Эксперт С++
1667 / 1039 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
08.03.2016, 20:52 7
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
А можно подробнее? Имплиминтация Base не известна Derivered и наоборот.
Достаточно интерфейса. Base сообщает, была ли обработана клавиша. Соответственно, Derived как послушный сын сначала отдаёт клавишу родителю, и если тот её отверг, обрабатывает сам. А если не отверг, то Derived сразу возвращает ответ родителя. Эту логику и можно запихнуть в виртуальный метод шаблона, а собственную обработку клавиши у Derived вынести в отдельный метод.
0
Эксперт CЭксперт С++
5068 / 2253 / 331
Регистрация: 20.02.2013
Сообщений: 5,595
Записей в блоге: 19
08.03.2016, 20:55 8
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Еще условный пример с жизни:
Поступает в универ военный (Человек -> Мужчина -> Военный) вызывается метод onEnterUniversity. Данный метод прокидывается по родителем: итого у военного как у человека запросят паспорт, у мужчины - военный билет, у военного - каску(не придумал).
Поступает в универ абитуриент (Человек -> Мужчина -> Абитуриент) вызывается метод onEnterUniversity. Данный метод прокидывается по родителем: итого у абитуриента как у человека запросят паспорт, у мужчины - военный билет, у абитуриента - аттестат.
1
2544 / 1203 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
08.03.2016, 21:14  [ТС] 9
Цитата Сообщение от Nick Alte Посмотреть сообщение
Derived как послушный сын сначала отдаёт клавишу родителю
а кто его заставит? Он может просто забыть или не знать, что где-то там его родители ждут от него весточки вслучаи евента)

Добавлено через 9 минут
Croessmah, как первая lib узнает что где-то там есть Derivered который ждёт foo<Derivered>
0
Эксперт С++
1667 / 1039 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
08.03.2016, 21:19 10
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
а кто его заставит?
Я же и говорю: его заставит тот факт, что он является шаблоном и эта логика описана в его методе SceneOnKeyPressed.
0
2544 / 1203 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
08.03.2016, 21:29  [ТС] 11
Nick Alte, к сожалению, я не могу представить себе код о котором вы говорите.

Добавлено через 3 минуты
И кстати, еще никто не сказал, что моя архитектура га*но hoggy, такой код не стерпел бы (((
0
Don't worry, be happy
17206 / 10084 / 1945
Регистрация: 27.09.2012
Сообщений: 25,164
Записей в блоге: 1
08.03.2016, 21:37 12
rikimaru2013, а как это сферическое нечто узнает, что код наследника обрабатывает данное событие?

Добавлено через 37 секунд
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
И кстати, еще никто не сказал, что моя архитектура га*но
а смысл, если
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Есть такая "очень классная архитектура"
Вы сами ей недовольны?
0
2544 / 1203 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
08.03.2016, 21:45  [ТС] 13
Croessmah, так родитель и не должен знать захочет ли его потомок переопределить метод. Главное сказать потомку - раз взялся - то перенаправь мне вызов, чтобы и я отработала евент, ведь в родители скрыта часть реализации о которой потомок и не должен знать, но без её выполнении, родительский класс будет вести как-будто и не было вызова метода foo.

Цитата Сообщение от Croessmah Посмотреть сообщение
Вы сами ей недовольны?
моего опыта в программирования не хватает придумать что-то более умного. Обратился к старейшинам
0
Don't worry, be happy
17206 / 10084 / 1945
Регистрация: 27.09.2012
Сообщений: 25,164
Записей в блоге: 1
08.03.2016, 21:55 14
Хреновая идея, наверное
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
//clang 3.7.0
 
#include <iostream>
#include <utility>
 
 
 
class Base
{
public:
    bool some(int x){
        auto result = do_some(x);
        if(result.second){//second true? Функция обработала событие
            return result.first;
        }
        return Base::do_some(x).first;
    }
private:
    virtual std::pair<bool, bool> do_some(int x){
        bool result = true;
        std::cout << "Base::do_some(" << x << ")" << std::endl;
        return std::make_pair(result, true);
    }
};
 
 
 
class Derived : public Base
{
private:
    std::pair<bool, bool> do_some(int x) override {
        bool result;
        std::cout << "Derived::do_some(" << x << ")" << std::endl;
        if(x==10)
            return std::make_pair(result, true);//обработали, вернули true в second
        return std::make_pair(result, false);//функция отказалась от обработки, вернули false в second
    }
};
 
 
 
 
 
int main()
{
    Derived x1;
    x1.some(12);
    x1.some(10);
    x1.some(0);
}
http://rextester.com/ZYY13168
1
Эксперт С++
8556 / 4132 / 908
Регистрация: 15.11.2014
Сообщений: 9,330
08.03.2016, 22:44 15
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Подскажите как Derivered "заставить не забыть" вызвать 'Base::SceneOnKeyPressed'
"фабричный метод" вроде бы паттерн называется.

когда алгоритм сосредоточен в одном месте.
наследники реализуют какие то частности,
но не контролируют основной ход бизнес-логики,
и поэтому, ничего не могут ничайно забыть:


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
#include <iostream>
#include <conio.h>
using namespace std;
 
//////////////////////////////////////////////////////////////////////////
struct Base
{
    bool SceneKeyPressed(int key)
    {
        bool result = true;
        switch(key)
        {
            case '1':
                cout << "Base processed key" << key << endl;
                break;
            case '2':
                cout << "Base processed key" << key << endl;
                result = false;
                break;
            default:
                result = false;
                break;
        }
        return result ? true: onSceneKeyPressed(key);
    }
protected:
    virtual bool onSceneKeyPressed(int key) = 0;
};
//////////////////////////////////////////////////////////////////////////
struct Derivered : public Base
{
private:
    bool onSceneKeyPressed(int key) override
    {
        bool result = true;
        switch(key)
        {
            case '2':
                cout << "Derivered processed key" << key << endl;                   
                break;
            case '3':
                cout << "Derivered processed key" << key << endl;
                break;
            default:
                result = false;
                break;
        }
        return result;
    }
};
//////////////////////////////////////////////////////////////////////////
int main()
{
    Base* ptr = new Derivered();
    while(true)
        if(_kbhit())                                                
            ptr->SceneKeyPressed(_getch()),
            cout << endl;
}
1
2544 / 1203 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
08.03.2016, 22:50  [ТС] 16
hoggy, если унаследовать Derivered - то всё сломается и вызовы получать крайние - средний не узнает

Добавлено через 4 минуты
Croessmah, жёсткий код) Сижу читаю)
0
Эксперт С++
8556 / 4132 / 908
Регистрация: 15.11.2014
Сообщений: 9,330
08.03.2016, 22:53 17
Лучший ответ Сообщение было отмечено rikimaru2013 как решение

Решение

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
если унаследовать Derivered - то всё сломается и вызовы получать крайние - средний не узнает
если наследнику критично,
что именно его вирт. функции будет вызвана,
то он должен объявить её как final.

других способов задать контракт,
за которым сможет проследить компилятор
не существует.

на практике обычно не заморачиваются.
наследник тупо делегирует по необходимости базовому классу,
и реализует свою ботву.
и так по всей иерархии наследования.
1
Эксперт С++
1667 / 1039 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
08.03.2016, 22:58 18
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Nick Alte, к сожалению, я не могу представить себе код о котором вы говорите.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<typename Base, typename Impl> class Derived: public Base {
public:
    virtual bool SceneOnKeyPressed(int key) {return Base::SceneOnKeyPressed(key) ? true : impl.OnKey(key);}
private:
    Impl impl;
};
 
class Soldier {
public:
    bool OnKey(int key) {return false;}
};
 
Base* createSoldier()
{
    return Derived<GameObject, Soldier>();
}
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
И кстати, еще никто не сказал, что моя архитектура га*но
Я по старой памяти от другой темы думал, что это внешняя библиотека, не подлежащая пересмотру.
1
2544 / 1203 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
08.03.2016, 23:00  [ТС] 19
Цитата Сообщение от Nick Alte Посмотреть сообщение
Я по старой памяти от другой темы думал, что это внешняя библиотека, не подлежащая пересмотру.
Да вы правы, cocos2dx method Node::init
0
Эксперт С++
1667 / 1039 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
08.03.2016, 23:06 20
Забыл в примере new, но надеюсь, на понятности не скажется.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.03.2016, 23:06

Вызов метода объекта внутри определения метода другого объекта(вложенные классы)
Как мне вызвать метод объекта slider класса Slider внутри определения метода объекта класса...

Вызов метода из метода
Можно ли вызвать метод из метода. Это программа не работает #include&lt;iostream&gt; using namespace...

Вызов метода
Друзья подскажите пожалуйста! Есть родительский класс TModel, в нем есть метод Euler2(), как это...

Вызов метода
Добрый вечер, я не знаю c++, пытаюсь разобраться, знаком с c#, delphi. Создаю библиотеку для c#...


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

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

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