Проблема: хочу вызвать член одного класса через указатель в другом классе, не прибегая к передаче в последний объекта первого.
Пытаюсь реализовать вызов члена контроллера из вьюхи, однако столкнулся с проблемой. Насколько я понял, для вызова из одного класса члена другого необходимо иметь инстанс класса, которому принадлежит вызываемый метод. Можно ли как-то этого избежать? В данном случае, хотелось бы, что бы вьюха ничего не знала про контроллер (кроме типа хэндлера, без этого не типизировать коллбэк).
Или есть более грамотный способ реализовать данное поведение? Использовать в качестве коллбэка дружественную функцию или статический член — не вариант.
Здравствуйте, aalp, Вы писали:
A>Здравствуйте,
A>Проблема: хочу вызвать член одного класса через указатель в другом классе, не прибегая к передаче в последний объекта первого.
A>Пытаюсь реализовать вызов члена контроллера из вьюхи, однако столкнулся с проблемой. Насколько я понял, для вызова из одного класса члена другого необходимо иметь инстанс класса, которому принадлежит вызываемый метод. Можно ли как-то этого избежать? В данном случае, хотелось бы, что бы вьюха ничего не знала про контроллер (кроме типа хэндлера, без этого не типизировать коллбэк).
A>Или есть более грамотный способ реализовать данное поведение? Использовать в качестве коллбэка дружественную функцию или статический член — не вариант.
A>
A>class Controller;
A>class IView;
A>class View;
A>typedef void(Controller::* OnEventHandler)();
A>struct IView
A>{
A> virtual void Exec() = 0;
A> virtual void SetHandler(OnEventHandler) = 0;
A>};
A>struct Controller
A>{
A>public:
A> Controller(IView* pView)
A> {
A> pView->SetHandler(&Controller::Handler);
A> }
A> void Handler()
A> {
A> std::cout << "Handler from Controller called" << std::endl;
A> }
A>};
A>struct View : public IView
A>{
A> OnEventHandler handler;
A> virtual void SetHandler(OnEventHandler callback)
A> {
A> handler = callback;
A> }
A> virtual void Exec()
A> {
A> if(handler)
A> {
A> std::cout << "Handler exist, calling: ";
A> handler();
A> }
A> else
A> {
A> std::cout << "Handler does not exist" << std::endl;
A> }
A> }
A>};
A>int main()
A>{
A> IView* view = new View();
A> Controller c(view);
view->>Exec();
A>}
A>
Заведи в Controller поле boost::function<...>, в main установи его посредством View, и вызывай когда надо.
Или посмотри в строну boost::signal, тоже самое в принципе.
Re[2]: Вызов коллбэка-члена класса из другого класса
....
_>Заведи в Controller поле boost::function<...>, в main установи его посредством View, и вызывай когда надо. _>Или посмотри в строну boost::signal, тоже самое в принципе.
Хотелось бы обойтись без буста. Код должен собираться на маке, помимо вин32, тащить буст туда по определенным причинам нельзя.
Здравствуйте, aalp, Вы писали:
A>Проблема: хочу вызвать член одного класса через указатель в другом классе, не прибегая к передаче в последний объекта первого.
Не получится по следующей причине: любая функция-член класса неявно первым аргументом принимает указатель на объект класса. То есть вызов MyClass.MyFunc() с точки зрения C-программиста это MyFunc(&MyClass); с некоторыми дополнительными ограничениями. Простой указатель на MyClass::MyFunc не сохраняет информацию об объекте класса, поэтому вы должны её каким-то образом предоставить.
Я предлагаю указатель на интерфейс контроллера во вьюхе и вызов по этому указателю. То есть нечто вроде:
Здравствуйте, aalp, Вы писали:
A>Здравствуйте, placement_new, Вы писали:
A>....
_>>Заведи в Controller поле boost::function<...>, в main установи его посредством View, и вызывай когда надо. _>>Или посмотри в строну boost::signal, тоже самое в принципе.
A>Хотелось бы обойтись без буста. Код должен собираться на маке, помимо вин32, тащить буст туда по определенным причинам нельзя.
Ну тогда можно обоитись указателем на член-ф-ию, что и есть по сути boost::function.
В принципе так же как у тебя, с тем лишь отличием что сделать метод SetHandler(<указатель на член IView>), а не в конструктор вьюшку передавать. А "менее зависимо" мне кажется не получится.
Здравствуйте, aalp, Вы писали:
A>Проблема: хочу вызвать член одного класса через указатель в другом классе, не прибегая к передаче в последний объекта первого.
Singleton с reference counting?
class C1 : public Singleton<C1>
{
public:
void OnEvent();
};
class C2
{
void CallOnEvent()
{
C1* c = C1::Instance();
c->OnEvent();
c->FreeInstance();
}
};
Примерно так, как вариант. Но не подходит для задач, где экземпляров C1 может быть больше 1.
Техника в приципе известная, с помощью классов переходников.
Re[3]: Вызов коллбэка-члена класса из другого класса
От:
Аноним
Дата:
22.01.09 13:23
Оценка:
Здравствуйте, aalp, Вы писали:
A>Здравствуйте, placement_new, Вы писали:
A>....
_>>Заведи в Controller поле boost::function<...>, в main установи его посредством View, и вызывай когда надо. _>>Или посмотри в строну boost::signal, тоже самое в принципе.
A>Хотелось бы обойтись без буста. Код должен собираться на маке, помимо вин32, тащить буст туда по определенным причинам нельзя.
на мой взгляд, есть 2 варианта:
1) сделать колбек не указателем а структурой (возможно с разделенными интерфейсом и реализацией) и в поле структуры хранить указатель на создавший колбек объект.
2) использовать компиляторы поддерживающие tr1/functional (std::tr1::function копия boost::function), менее велосипедно.
под винду это умеет 2008я студия, пол линукс последние версии gcc, под мак наверняка тоже что-то есть.
Здравствуйте, aalp, Вы писали:
A>Или есть более грамотный способ реализовать данное поведение? Использовать в качестве коллбэка дружественную функцию или статический член — не вариант.