Чайниковский вопрос по C++
-
- Уже с Приветом
- Posts: 1491
- Joined: 02 Jul 2003 22:47
Чайниковский вопрос по C++
Задача стоит такая - реализовать механизм событий,
аналогичный в DELPHI.
Т.е. существует к примеру класс Cbutton, экземпляр которого
используется в наследнике классе СWindow, и нужно,
чтобы на событие OnClick экземпляра Cbutton вызывался
метод класса CWindow.
Проблема в том, что function pointer OnClick класса Cbutton должен
быть описан как метод какого-то конкретного класса, что неприемлимо,
т.к. неизвестно в каком классе он будет вызыватся.
аналогичный в DELPHI.
Т.е. существует к примеру класс Cbutton, экземпляр которого
используется в наследнике классе СWindow, и нужно,
чтобы на событие OnClick экземпляра Cbutton вызывался
метод класса CWindow.
Проблема в том, что function pointer OnClick класса Cbutton должен
быть описан как метод какого-то конкретного класса, что неприемлимо,
т.к. неизвестно в каком классе он будет вызыватся.
-
- Уже с Приветом
- Posts: 12072
- Joined: 17 Nov 2002 03:41
- Location: английская колония
Re: Чайниковский вопрос по C++
Angry wrote:Задача стоит такая - реализовать механизм событий,
аналогичный в DELPHI.
Т.е. существует к примеру класс Cbutton, экземпляр которого
используется в наследнике классе СWindow, и нужно,
чтобы на событие OnClick экземпляра Cbutton вызывался
метод класса CWindow.
Проблема в том, что function pointer OnClick класса Cbutton должен
быть описан как метод какого-то конкретного класса, что неприемлимо,
т.к. неизвестно в каком классе он будет вызыватся.
Не понял. Кто ето все будет писать - Вы?
Тогда самому можно и дописать функцию в СБаттон.
Иначе Можно иметь месседж мап в Виндовс и посылать месседж.
Вы на пальцах покажите где узкое место. А Делфи мы уж давно не помним.
Верить нельзя никому - даже себе. Мне - можно!
-
- Уже с Приветом
- Posts: 1491
- Joined: 02 Jul 2003 22:47
Re: Чайниковский вопрос по C++
A. Fig Lee wrote:Angry wrote:Задача стоит такая - реализовать механизм событий,
аналогичный в DELPHI.
Т.е. существует к примеру класс Cbutton, экземпляр которого
используется в наследнике классе СWindow, и нужно,
чтобы на событие OnClick экземпляра Cbutton вызывался
метод класса CWindow.
Проблема в том, что function pointer OnClick класса Cbutton должен
быть описан как метод какого-то конкретного класса, что неприемлимо,
т.к. неизвестно в каком классе он будет вызыватся.
Не понял. Кто ето все будет писать - Вы?
Тогда самому можно и дописать функцию в СБаттон.
Иначе Можно иметь месседж мап в Виндовс и посылать месседж.
Вы на пальцах покажите где узкое место. А Делфи мы уж давно не помним.
У разных экземпляров Cбаттон - разные обработчики в OnClick
Узкое место - если описано
class CSpriteAnimation2
{
public:
CSpriteAnimation2(LPDIRECT3DDEVICE9 m_Device,char *fname,char *ftexturename);
CSpriteAnimation2(LPDIRECT3DDEVICE9 m_Device,char *fname,LPDIRECT3DTEXTURE9 Texture);
~CSpriteAnimation2();
long (*function)(int i);
};
А потом
long CCustomPresentation::testf(int i)
{
CSpriteAnimation2 a(NULL,"1","2");
a.function=this->testf;
}
Выдает ошибку
Нессответствие типов 'long (__thiscall CCustomPresentation::* )(int)' to 'long (__cdecl *)(int)'
Возможно ли это обойти?
-
- Уже с Приветом
- Posts: 12072
- Joined: 17 Nov 2002 03:41
- Location: английская колония
Re: Чайниковский вопрос по C++
Angry wrote:A. Fig Lee wrote:Angry wrote:Задача стоит такая - реализовать механизм событий,
аналогичный в DELPHI.
Т.е. существует к примеру класс Cbutton, экземпляр которого
используется в наследнике классе СWindow, и нужно,
чтобы на событие OnClick экземпляра Cbutton вызывался
метод класса CWindow.
Проблема в том, что function pointer OnClick класса Cbutton должен
быть описан как метод какого-то конкретного класса, что неприемлимо,
т.к. неизвестно в каком классе он будет вызыватся.
Не понял. Кто ето все будет писать - Вы?
Тогда самому можно и дописать функцию в СБаттон.
Иначе Можно иметь месседж мап в Виндовс и посылать месседж.
Вы на пальцах покажите где узкое место. А Делфи мы уж давно не помним.
У разных экземпляров Cбаттон - разные обработчики в OnClick
Узкое место - если описано
class CSpriteAnimation2
{
public:
CSpriteAnimation2(LPDIRECT3DDEVICE9 m_Device,char *fname,char *ftexturename);
CSpriteAnimation2(LPDIRECT3DDEVICE9 m_Device,char *fname,LPDIRECT3DTEXTURE9 Texture);
~CSpriteAnimation2();
long (*function)(int i);
};
А потом
long CCustomPresentation::testf(int i)
{
CSpriteAnimation2 a(NULL,"1","2");
a.function=this->testf;
}
Выдает ошибку
Нессответствие типов 'long (__thiscall CCustomPresentation::* )(int)' to 'long (__cdecl *)(int)'
Возможно ли это обойти?
Так. Вы смешали в кучу Сшные каллбеки и С++.
Мона сделать так - все баттоны должны быть деривед иот класса ВасяПупкин.
В классе Вася Пупкин имеем одну публи фанкшн которую и будем звать.
Тогда и присваивать ничего не надо?
class VasjaPupkin
{
public:
virtual void do_it(){/*do it here*/}
};
class MyButton1 : public VasjaPupkin
{
...
};
class MyButton2 : public VasjaPupkin
{
...
};
int do_any(VasjaPupkin *a)
{
a->do_it();
}
and you may call
do_any(new MyButton1)
{
}
Примерно так.
Верить нельзя никому - даже себе. Мне - можно!
-
- Уже с Приветом
- Posts: 1906
- Joined: 14 Mar 2001 10:01
Действительно, как уже писал A. Fig Lee хотелось бы знать поконкретней вашу проблему.
Пока могу только догадываться, что раз вы не используете стандартные massage maps, которые есть практически по всех GUI библиотеках для Windows, вы имеете дело с собственным набором событий, а не со стандартными windows messages.
Тогда, возможно, вам лучше вообще по-другому сделать, и GUIные библиотеки (во всяком случае те, которые я знаю) здесь не очень хороший пример для подражания.
Возможно, вам подойдёт какая-нить вариация Observer Pattern.
Пока могу только догадываться, что раз вы не используете стандартные massage maps, которые есть практически по всех GUI библиотеках для Windows, вы имеете дело с собственным набором событий, а не со стандартными windows messages.
Тогда, возможно, вам лучше вообще по-другому сделать, и GUIные библиотеки (во всяком случае те, которые я знаю) здесь не очень хороший пример для подражания.
Возможно, вам подойдёт какая-нить вариация Observer Pattern.
Code: Select all
struct MouseObserver
{
virtual void OnLButtonDown() = 0;
...
};
class Mouse
{
public:
void Subscribe(MouseObserver * o) { m_obs.add(o); }
void Unsibscribe(MouseObserver * o) { m_obs.remove(o); }
private:
void FireLButtonDown()
{
for each o in m_obs
o->OnLButtonDown();
}
ObsList m_obs;
};
-
- Уже с Приветом
- Posts: 1906
- Joined: 14 Mar 2001 10:01
Re: Чайниковский вопрос по C++
A. Fig Lee wrote: Мона сделать так - все баттоны должны быть деривед иот класса ВасяПупкин...
Как я понял, Angry хочет динамически управлять диспетчеризацией, раз вон указатели на ф-ции пытается присваивать во время выполнения?
-
- Уже с Приветом
- Posts: 11475
- Joined: 20 Nov 2000 10:01
- Location: Escondido, CA
Надо декларировать пойнтер как
Если хотите вызывать функцию не для родительского объекта ( в первом примере, CButton не наследует от CWindow ), нужно еще сохранять указатель на объект.
Code: Select all
long (CSpriteAnimation2::*function)(int i);
Если хотите вызывать функцию не для родительского объекта ( в первом примере, CButton не наследует от CWindow ), нужно еще сохранять указатель на объект.
-
- Уже с Приветом
- Posts: 1976
- Joined: 08 Jun 1999 09:01
- Location: SPb -> SFBA -> Beaverton, OR
Hamster wrote:Надо декларировать пойнтер какCode: Select all
long (CSpriteAnimation2::*function)(int i);
Если хотите вызывать функцию не для родительского объекта ( в первом примере, CButton не наследует от CWindow ), нужно еще сохранять указатель на объект.
Angry, почитайте про Pointer-to-Member Operators, Hamster дело говорит.
-
- Уже с Приветом
- Posts: 394
- Joined: 12 Feb 2001 10:01
- Location: USA
Re: Чайниковский вопрос по C++
Вот вам примерчик. Писалось на коленке, так что не ругайте. Старался сделать как можно больше похоже на Делфи, для аналогий.Angry wrote:Задача стоит такая - реализовать механизм событий, аналогичный в DELPHI....Проблема в том, что function pointer OnClick класса Cbutton должен быть описан как метод какого-то конкретного класса, что неприемлимо, т.к. неизвестно в каком классе он будет вызыватся.
Code: Select all
#include "stdafx.h"
class TNotifyEvent
{
public:
virtual void Call(void *sender) = 0;
};
template<class T> class TTNotifyEvent: public TNotifyEvent
{
typedef void (T::*_NotifyFuncPtr)(void *);
private:
T *m_target_obj;
_NotifyFuncPtr m_target_obj_func;
public:
TTNotifyEvent(T *target, _NotifyFuncPtr func): m_target_obj(target), m_target_obj_func(func) {};
virtual void Call(void *sender)
{
(m_target_obj->*(m_target_obj_func))(sender);
}
};
class TButton
{
private:
public:
TNotifyEvent *OnClick;
void Click()
{
if (OnClick)
{
OnClick->Call(this);
}
}
void BtnDoSomething(void) {}
};
class TForm
{
private:
void FormDoSomething(void) {}
public:
TButton btn;
void btn_click(void *sender)
{
printf("Button clicked!");
reinterpret_cast<TButton *>(sender)->BtnDoSomething();
FormDoSomething();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TForm frm;
frm.btn.OnClick = new TTNotifyEvent<TForm>(&frm, &TForm::btn_click);
frm.btn.Click();
delete frm.btn.OnClick;
return 0;
}
-
- Уже с Приветом
- Posts: 1491
- Joined: 02 Jul 2003 22:47
-
- Уже с Приветом
- Posts: 2013
- Joined: 16 Mar 2002 10:01
- Location: New York City
-
- Уже с Приветом
- Posts: 394
- Joined: 12 Feb 2001 10:01
- Location: USA
-
- Уже с Приветом
- Posts: 394
- Joined: 12 Feb 2001 10:01
- Location: USA
Я не вижу, как RTTI тут может помочь. Вам же нужно в compile-time проверять, подходит ли сигнатура обработчика события к определению этого события. А RTTI - это run-time.Angry wrote:Спасибо, я понял в чем дело - в с++ нет RTTI и по ссылке на объект нельзя узнать что это за класс и какие в нем есть методы.
-
- Уже с Приветом
- Posts: 1491
- Joined: 02 Jul 2003 22:47
Yuri_p33 wrote:Я не вижу, как RTTI тут может помочь. Вам же нужно в compile-time проверять, подходит ли сигнатура обработчика события к определению этого события. А RTTI - это run-time.Angry wrote:Спасибо, я понял в чем дело - в с++ нет RTTI и по ссылке на объект нельзя узнать что это за класс и какие в нем есть методы.
В делфи можно написать.
var obj:tobject;
but:tbutton;
begin
tbutton(obj)=but;
obj.onclick;
end;
А мне именно это и нужно было. Вообще для моей текущей конкретной задачи можно обойтись и без run-time определения типа, вопрос я задал из чисто теоретических соображений
-
- Уже с Приветом
- Posts: 394
- Joined: 12 Feb 2001 10:01
- Location: USA