Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Shadow97
0 / 0 / 0
Регистрация: 22.02.2015
Сообщений: 2
1

Получение доступа к методам дочернего класса через указатель на родительский, хранимый в vector

22.02.2015, 19:53. Просмотров 403. Ответов 3
Метки нет (Все метки)

Была подобная тема с list'ом, но решение, предложенное там, мне не помогло.
Соль проблемы заключается в следующем: имеется vector, заполненный указателями на класс Object, являющийся родительским для всех остальных. В Object определён, среди прочих, пустой метод keyPress.
У класса Object есть дочерний класс MenuElement, где метод keyPress также пуст.
У MenuElement есть дочерний класс MenuBoolElement, где снова переопределяется метод keyPress, на сей раз он меняет значение val на противоположное.
Класс Engine хранит вышеупомянутый vector с указателями. Он поочерёдно обновляет все объекты, а в случае, если была нажата какая-то клавиша, он отправляет её код в соответствующую процедуру текущего объекта на обработку.
В данном примере vector хранит лишь один Object*, указывающий на MenuBoolElement. В ходе выполнения вызывается функция Object::keyPress(), а надо MenuBoolElement::keyPress().
Где я ошибся?

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
#define loop while(1)
#define forever while(1)
#define repeat(A, x) for(unsigned x = 0; x < A; x++)
#define repeat_AtoB(A, B, x) for(unsigned x = A; x < B; x++)
#define repeat_BtoA(A, B, x) for(long x = B - 1; x >= A; x--)
#define revrepeat(A, x) for(long x = A - 1; x >= 0; x--)
#define _getlch() tolower(_getch())
#define CONSOLE_WIDTH 50
#define TAB_OFFSET 8
#define elf else if
#define istypable(A) isalpha(A)||isdigit(A)||ispunct(A)||(A==32)
#define setCCP SetConsoleCursorPosition
#define setAttr SetConsoleTextAttribute
#define c_str(A) A.c_str()
#define t_ true
#define f_ false
#define _abstract virtual void _pure_virtual_function() = 0
#define _non_abstract virtual void _pure_virtual_function() {}
#define BLACK 0x00
#define DARK_BLUE 0x01
#define DARK_GREEN 0x02
#define DARK_CYAN 0x03
#define DARK_RED 0x04
#define DARK_MAGENTA 0x05
#define DARK_YELLOW 0x06
#define GREY 0x07
#define DARK_GREY 0x08
#define BLUE 0x09
#define GREEN 0x0A
#define CYAN 0x0B
#define RED 0x0C
#define MAGENTA 0x0D
#define YELLOW 0x0E
#define WHITE 0x0F
#define self *this
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
class Object
{
public:
    fCoord Location; // where is this object(counted from the left top corner)
    fCoord Velocity; // how many charplaces object passes each second
    fCoord Size; // physical size of the object. Used for touch calculations
    bool bCollides; // if true, this object can touch other objects;
    bool bInvertTouch; // if true, inverts touching conditions for this object. Used ONLY for game field as it limits its size
    Object* Instigator; // who spawned me?
    vector<string> Sprite; // what will be drawn on draw()?
    bitMatrix eraseMask; // what charplaces will be erased on erase()?
    short color; // color
    bool bToBeDestroyed; // if true, the object will be destroyed at the end of the tick
    Object()
        :Location(0, 0),
        Velocity(0, 0),
        Size(0, 0),
        bCollides(f_),
        bInvertTouch(f_),
        Instigator(0),
        color(0x07),
        bToBeDestroyed(f_)
    {}
    ~Object()
    {}
    void tick(time_t);
    bool Spawn(Object*, fCoord, fCoord);
    virtual void ProcessTouch(Object* Other) // describe in subclasses!
    {}
    void Destroy()
    {
        erase(Location);
        bToBeDestroyed = t_;
    }
    virtual void refresh(time_t deltaTime) {}
    virtual void keyPress(unsigned keyCode)
    {}
    virtual void draw(fCoord _where)
    {
        setCCP(hd, _where);
        setAttr(hd, color);
        repeat(Sprite.size(), r)
        {
            setCCP(hd, fCoord(Location.X, Location.Y + r));
            printf("%s", c_str(Sprite[r]));
        }
    }
    virtual void erase(fCoord _where)
    {
        repeat(eraseMask.Size.Y, r)
        {
            setCCP(hd, _where);
            repeat(eraseMask.Size.X, s)
            {
                if (s) cout << " ";
            }
            _where.Y++;
        }
    }
};
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
class MenuElement : public Object
{
public:
    string text;
    bool bFocus;
    short focusColor;
    MenuElement(fCoord Location = fCoord(0.0, 0.0),
        short color = 0x07,
        string text = "Menu element",
        bool bFocus = f_,
        short focusColor = 0x0E)
    {
        this->Location = Location;
        this->color = color;
        this->text = text;
        this->bFocus = bFocus;
        this->focusColor = focusColor;
        draw(Location);
    }
    virtual void draw(fCoord _where)
    {
        setCCP(hd, _where);
        setAttr(hd, (bFocus ? focusColor : color));
        cout << c_str(text);
    }
    virtual void erase(fCoord _where)
    {
        setCCP(hd, _where);
        repeat(text.length(), r)
        {
            cout << " ";
        }
    }
    virtual void keyPress(unsigned keyCode)
    {}
};
 
class MenuBoolElement : public MenuElement
{
public:
    bool val;
    MenuBoolElement(fCoord Location = fCoord(0.0, 0.0), 
        short color = 0x07, 
        string text = "Menu element", 
        bool val = f_, 
        bool bFocus = f_,
        short focusColor = 0x0E)
        :MenuElement(Location, color, text, bFocus, focusColor)
    {
        this->val = val;
        draw(Location);
    }
    virtual void draw(fCoord _where)
    {
        setCCP(hd, _where);
        setAttr(hd, (bFocus ? focusColor : color));
        cout << (bFocus ? "[ " : " [") << (val ? char(254) : ' ') << (bFocus ? " ]" : "] ");
        cout << c_str(text);
    }
    virtual void erase(fCoord _where, bool formerVal)
    {
        setCCP(hd, _where);
        repeat(4 + formerVal * 2 + text.length(), r)
        {
            cout << " ";
        }
    }
    virtual void keyPress(unsigned keyCode)
    {
        if (keyCode == VK_SPACE || keyCode == VK_RETURN)
        {
            val = !val;
            erase(Location, !val);
            draw(Location);
        }
    }
};
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
class engine
{
public:
    vector<Object*> vecObjList;
    vector<Object*>::iterator itr;
    time_t globalTimer;
    engine()
        :globalTimer(clock())
    {}
    ~engine()
    {}
    void MainLoop()
    {
        time_t thisTime;
        do
        {
            thisTime = clock();
            repeat(vecObjList.size(), r)
            {
                itr = vecObjList.begin() + r;
                (*itr)->tick(thisTime - globalTimer);
                if ((*itr)->bToBeDestroyed)
                {
                    vecObjList.erase(itr);
                    r--; // else one object will be skipped
                }
                // check and dispatch keyboard commands
                if (_kbhit())
                {
                    (*itr)->keyPress(_getch());
                }
            }
            globalTimer = thisTime;
        }
        loop;
    }
    void Spawn(Object* _spawned, fCoord Location = fCoord(0, 0), fCoord Velocity = fCoord(0, 0))
    {
        vecObjList.emplace_back(_spawned);
        _spawned->Location = Location;
        _spawned->Velocity = Velocity;
        _spawned->Instigator = nullptr;
    }
};
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
22.02.2015, 19:53
Ответы с готовыми решениями:

Обращение к методам класса через указатель на экземпляр класса
Добрый день. Не могу осилить проблему: Описан абстрактный класс. Описаны...

Указатель дочернего класса в базовом
Добрый день. ОШИБКА: ..\main.cpp:6: error: invalid use of incomplete type...

Как передать в метод класса Menu указатель на метод дочернего класса?
Как передать в метод базового класса указатель на метод дочернего: class...

Получение доступа к переменным класса из другого класса
Как передать по ссылке переменную из класса А в метод класса В?

Почему обращение к методам осуществляется через оператор прямого доступа, а не через оператор указателей->?
#include &lt;iostream&gt; using namespace std; class random { public: void...

3
rikimaru2013
C++ Game Dev
2473 / 1141 / 349
Регистрация: 30.11.2013
Сообщений: 3,709
22.02.2015, 20:13 2
а где push в вектор укажите плиз?

Добавлено через 6 минут
Spawn где вызывается
0
Shadow97
0 / 0 / 0
Регистрация: 22.02.2015
Сообщений: 2
22.02.2015, 22:35  [ТС] 3
C++
1
2
3
4
5
6
7
    void Spawn(Object* _spawned, fCoord Location = fCoord(0, 0), fCoord Velocity = fCoord(0, 0))
    {
        vecObjList.emplace_back(_spawned); // это и есть push в конец вектора
        _spawned->Location = Location;
        _spawned->Velocity = Velocity;
        _spawned->Instigator = nullptr;
    }
Вызывается Spawn здесь:

C++
1
2
3
4
5
void main()
{
    Engine.Spawn(&MenuBoolElement(fCoord(0, 0), 0xF, "Lol?", f_, t_));
    Engine.MainLoop();
}
Добавлено через 1 час 57 минут
Прошу прощения за ложную тревогу Пораскинув мозгами, я пришёл вот к такому решению:

C++
1
2
3
Object* X = new MenuBoolElement(fCoord(0, 0), 0xF, "Lol?", f_, t_);
Engine.Spawn(X);
// вместо Engine.Spawn(&MenuBoolElement(fCoord(0, 0), 0xF, "Lol?", f_, t_));
Я так понял, локальный указатель терялся после выхода из Spawn(), поэтому MenuBoolElement вёл себя, как Object
0
rikimaru2013
C++ Game Dev
2473 / 1141 / 349
Регистрация: 30.11.2013
Сообщений: 3,709
23.02.2015, 00:22 4
Цитата Сообщение от Shadow97 Посмотреть сообщение
поэтому MenuBoolElement вёл себя, как Object
Ахаха) Спасибо за радостный вечер) Тру стори про обидчивый MenuBoolElement, который решил насолить программисту и начал вести себя неподобающе
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.02.2015, 00:22

Обращение к полям и методам класса через объект
есть класс TEditor (методы класса обязательно должны создавать новый объект и...

Указатель на объект вектор в векторе vector < vector<int>* >*
Дело касается вот чего, есть такая вот незатейлевая вещь. #include &lt;vector&gt;...

Получение доступа к закрытым методом класса
Как получить доступ к закрытому конструктору и деструктору?


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

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

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