КулЛиб - Классная библиотека! Скачать книги бесплатно
Всего книг - 713194 томов
Объем библиотеки - 1403 Гб.
Всего авторов - 274655
Пользователей - 125093

Новое на форуме

Новое в блогах

Впечатления

Влад и мир про Семенов: Нежданно-негаданно... (Альтернативная история)

Автор несёт полную чушь. От его рассуждений уши вянут, логики ноль. Ленин был отличным экономистом и умел признавать свои ошибки. Его экономическим творчеством стал НЭП. Китайцы привязали НЭП к новым условиям - уничтожения свободного рынка на основе золота и серебра и существование спекулятивного на основе фантиков МВФ. И поимели все технологии мира в придачу к ввозу промышленности. Сталин частично разрушил Ленинский НЭП, добил его

  подробнее ...

Рейтинг: +1 ( 1 за, 0 против).
Влад и мир про Шенгальц: Черные ножи (Альтернативная история)

Читать не интересно. Стиль написания - тягомотина и небывальщина. Как вы представляете 16 летнего пацана за 180, худого, болезненного, с больным сердцем, недоедающего, работающего по 12 часов в цеху по сборке танков, при этом имеющий силы вставать пораньше и заниматься спортом и тренировкой. Тут и здоровый человек сдохнет. Как всегда автор пишет о чём не имеет представление. Я лично общался с рабочим на заводе Свердлова, производившего

  подробнее ...

Рейтинг: +1 ( 1 за, 0 против).
Влад и мир про Владимиров: Ирландец 2 (Альтернативная история)

Написано хорошо. Но сама тема не моя. Становление мафиози! Не люблю ворьё. Вор на воре сидит и вором погоняет и о ворах книжки сочиняет! Любой вор всегда себя считает жертвой обстоятельств, мол не сам, а жизнь такая! А жизнь кругом такая, потому, что сам ты такой! С арифметикой у автора тоже всё печально, как и у ГГ. Простая задачка. Есть игроки, сдающие определённую сумму для участия в игре и получающие определённое количество фишек. Если в

  подробнее ...

Рейтинг: 0 ( 0 за, 0 против).
DXBCKT про Дамиров: Курсант: Назад в СССР (Детективная фантастика)

Месяца 3-4 назад прочел (а вернее прослушал в аудиоверсии) данную книгу - а руки (прокомментировать ее) все никак не доходили)) Ну а вот на выходных, появилось время - за сим, я наконец-таки сподобился это сделать))

С одной стороны - казалось бы вполне «знакомая и местами изьезженная» тема (чуть не сказал - пластинка)) С другой же, именно нюансы порой позволяют отличить очередной «шаблон», от действительно интересной вещи...

В начале

  подробнее ...

Рейтинг: +2 ( 2 за, 0 против).
DXBCKT про Стариков: Геополитика: Как это делается (Политика и дипломатия)

Вообще-то если честно, то я даже не собирался брать эту книгу... Однако - отсутствие иного выбора и низкая цена (после 3 или 4-го захода в книжный) все таки "сделали свое черное дело" и книга была куплена))

Не собирался же ее брать изначально поскольку (давным давно до этого) после прочтения одной "явно неудавшейся" книги автора, навсегда зарекся это делать... Но потом до меня все-таки дошло что (это все же) не "очередная злободневная" (читай

  подробнее ...

Рейтинг: +1 ( 1 за, 0 против).

Обработка событий в С++ [Александр Клюев] (fb2) читать постранично


 [Настройки текста]  [Cбросить фильтры]

Александр Клюев Обработка событий в С++

Введение

Так уж исторически сложилось, что в языке С++ нет событий. Событием (event) является исходящий вызов (программисты на VB хорошо знакомы с ними) и в С++ их действительно нет. Иногда события путают с сообщениями (message), но это не верно. Сообщение это прямой вызов: например windows вызывает оконную процедуру для передачи собщения окну. Объект (система) вызывает функцию обькта(окна). Вызов происходит от объекта к объекту. В отличии от сообщения событие имеет другую механику. Объект инициирует событие и вызываются все объекты-обработчики. Т.е. от одного объекта к нескольким. Причем объект инициатор события может ничего не «знать» об его обработчиках, поэтому событие называют исходящим вызовом.

Раз уж в С++ события на уровне языка не поддерживаются, значит стоит организовать их на уровне библиотеки. Здесь приведена реализация такой библиотеки. В ней есть два класса signal и slot.

Итак, чтобы сделать какой нибудь класс источником события поместите в него переменную типа signal:

struct EventRaiser { // источник события

 signal<void> someEvent; // void – тип аргумента события

};

А чтобы сделать класс обработчиком поместите в него переменную типа slot, функцию обработчик и свяжите slot с обработчиком:

struct EventHandler { // обработчик события

 slot someHandler; // переходник

 void onEvent(void) {

  // функция обработчик события

  printf("event handled");

 }

 void connect (EventRaiser& er) {

  someHandler.init(er.someEvent, onEvent, this); // установим связь события с обработчиком

 }

};


Так как эти объекты являются частью своих хозяев, не нужно заботится о времени жизни связи. Ее разрыв произойдет во время разрушения одного из них. Событие же инициируется вызвовом метода signal::raise:

struct EventRaiser { // источник события

 signal<void> someEvent; // void – тип аргумента события

 void someFunc() {

  someEvent.raise(); // инициация события

 }

};

Пример

В примере создаются два класса обработчик и инициатор события, устанавливается связь между ними и иллюстрируется обработка события в нескольких объектах одновременно:

#include "stdafx.h"

#include "sigslot.h"


struct EventRaiser { // источник события

 signal<const char*> event; // const char* – тип аргумента. может быть void

 void raise(const char *eventName) {

  printf("raising %s event\n", eventName);

  event.raise(eventName);

 }

} g_Raiser; // глобальный объект


struct EventHandler { // обработчик события

 const char *color;

 slot handler; // переходник

 void onEvent(const char *eventName) { // обработчик события

  printf("\t%s event handled in %s object\n", eventName, color);

 }

 EventHandler(const char *clr): color(clr) {

  handler.init(g_Raiser.event, onEvent, this); // установим связь

 }

};


int main(int argc, _TCHAR* argv[]) {

 EventHandler red("Red");

 g_Raiser.raise("Small"); // событие обработается в red

 {

  {

   EventHandler blue("Blue");

   g_Raiser.raise("Big"); // событие обработается в red и blue

  }

  EventHandler green("Green");

  g_Raiser.raise("Medium"); // событие обработается в red и green.

  // объект blue уничтожен, связь разорвана

 }

 return 0;

}

Краткое описание классов

signal – cобытие (детали реализации опущены)

template <class Arg> // Arg – тип аргумента функции обработчика

class signal {

public:

 // Инициировать событие

 void raise(

  Arg arg // Арумент arg будет передан в обработчики события

 );

};

slot – переходник для обработки события в классе-обработчике (детали реализации опущены)

class slot {

public:

 // установить связь с событием и обработчиком

 template <

  class Owner, // класс-обработчик

  class Arg // Тип аргумента события.

 >

 void init(

  signal<Arg>&sig, // событие

  void (Owner::*mpfn)(Arg), // функция обработчик

  Owner *This // обьект обработчик

 );

 // установить связь с событием и обработчиком для случая signal<void>

 template <

  class Owner // класс-обработчик

 >

 void init(

  signal<void>&sig, // событие

  void (Owner::*mpfn)(), // функция обработчик

  Owner *This // обьект обработчик

 );

 // разорвать связь

 void clear();

};

Исходный код

Весь код находится в файле sigslot.h

#ifndef _SIGSLOT_h_

#define _SIGSLOT_h_

// sigslot.h – autor Kluev Alexander kluev@pragmaworks.com


template <class Arg> class signal;


class slot {

 friend class signal_base;

 slot *_prev;

 slot *_next;

 struct Thunk {};

 typedef void (Thunk::*Func)();

 Thunk *_trg;

 Func _mfn;

public:

 slot(): _trg(0), _mfn(0), _prev(0), _next(0) {}

 ~slot() {clear();}

public:

 void clear() {

  if (_next) _next->_prev = _prev;

  if (_prev) _prev->_next = _next;

  _prev = _next = 0;

 }

 template <class Owner, class Arg>

 void init(signal<Arg>&sig, void (Owner::*mpfn)(Arg), Owner *This) {

  clear();

  _trg = (Thunk*)This;

  _mfn = (Func)mpfn;

   sig._add(*this);

 }

 template <class Owner>

 void init(signal<void>&sig, void (Owner::*mpfn)(), Owner *This) {

  clear();

  _trg = (Thunk*)This;

  _mfn = (Func)mpfn; sig._add(*this);

 }

private:

 template <class Arg>

 void _call(Arg a) {

  typedef void (Thunk::*XFunc)(Arg);

  XFunc f = (XFunc)_mfn;

  (_trg->*f)(a);

 }

 void _call() {

  (_trg->*_mfn)();

 }

};


class signal_base {

protected:

 friend class