1816
|
Разное / Говорилка / Re: ЧТо должно быть в багаже программиста при устройстве на работу
|
: Февраль 21, 2011, 14:06
|
В данный момент я работаю на фирме кодером. Пишу на Qt под Windows и Ubuntu. Год тому назад писал на Visual Basic. Времени на изучение чего то нового не хватает катастрофически так как ещё учусь в универе на 3-ем курсе, но не хочется останавливаться только на данных языках программирования. Я хочу выкраивать драгоценное время на изучение ещё чего нибудь и не хочу обжечся выбрав невостребованное, так как технологии не стоят на одном месте. Я жду советов в тех областях, которые будут ещё перспективны долгие годы. Те проекты которые сейчас уже существуют, но всё же продолжают совершенствоваться и в будущем может ещё сделают революцию, а не просто умрут. Я думаю что я сделал правильный выбор в сторону С++. А какие примерно нужно знать алгоритмы, такой банальный вопрос? Может посоветуете книги, сайты. Какие советы: рыться в чужих кодах и тем самым набирать опыт кодинга? Изобретать свои велосипеды и не использовать готовые решения? Какие разделы математики необходимо подтянуть? И вообще трудно ли будет мне в будущем если у меня туго с математикой?
Как говорится: Фотографирует не фотоаппарат, а фотограф.. Это я к тому, что ставить такие вопросы как: а что выбрать: Nikon или Canon - не хорошо, это даже не этично и не проффесионально.. Будете ставить такие вопросы и пытаться искать на них ответы - убъёте сразу двух зайцев: 1) Своё драгоценное время 2) Так и останетесь кодером Не надо делать из технологии культ, учитесь мыслить абстрактно и учитесь для себя в первую очередь, а не для ради того что через N лет устроится в компанию X и писать с использованием технологии Y
|
|
|
1817
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 21, 2011, 00:49
|
Вобщем остановился на варианте BRE: отнаследовать receiver от trackable (он же в прошлом spy), т.е. на схеме используемой в libsigc++. Это означает, что объект который получает сигналы (receiver) должен быть отнаследован от класса trackable. trackable - автоматически разрывает соединение, если receiver будет уничтожен. Выглядит это так: C++ (Qt) #include <iostream> #include <string> #include "signal_slot.h" /* Класс A испускает сигналы */ class A { public: A() {} ssc::signal<void, std::string> my_signal; void run() { my_signal("Hello Word!"); } }; /* Класс B содержит слоты, поэтому он должен отнаследоваться от trackable */ class B : public ssc::trackable { public: B() {} void slot1(const std::string &str) { std::cout << "slot1, signal - " << str << std::endl; } void slot2(std::string str) const { std::cout << "slot2, signal - " << str << std::endl; } }; int main() { B *b = new B; A *a = new A; connect(a->my_signal, b, &B::slot1); connect(a->my_signal, b, &B::slot2); a->run(); delete b; delete a; return 0; } Сам механизм сигнал-слот здесь реализован по следующей схеме: 1) Класс base_signal: C++ (Qt) template <class T_return, class T_arg> class base_signal
Чисто абстрактный класс, реализующий интерфейс: C++ (Qt) virtual T_return operator() (const T_arg &) const = 0; virtual bool valid() const = 0;
2) Класс signal: C++ (Qt) template <class T_return, class T_arg> class signal
Знает о всех соединениях со слотами: имеет список (std::list) соединений (manager_connection) являющихся потомками base_signal. Имеет перегруженный оператор C++ (Qt) T_return operator() (const T_arg &arg) const в котором перебирается весь список соединений и для каждого объекта manager_connection вызывается свой переопределённый virtual T_return operator() (const T_arg &) const. 3) Класс manager_connection: C++ (Qt) template <class T_receiver, class T_return, class T_arg> class manager_connection : public base_signal<T_return, T_arg>
наследуется от класса base_signal и реализует весь функционал. 4) Класс trackable и trigger: C++ (Qt) class trigger { public: trigger() : _flag(true) {} void set(bool flag) { _flag = flag; } bool get() const { return _flag; } private: bool _flag; }; class trackable { public: trackable() { spy = smart_ptr<trigger>(new trigger); } virtual ~trackable() { spy->set(false); } smart_ptr<trigger> spy; };
trigger - простой класс имеющий два состояния: true - receiver жив, false - уничтожен Класс trackable - обёртка над trigger, причём trigger заворачивается в умный указатель, который знает сколько других указателей ссылаются на объект. smart_ptr уничтожит объект если число ссылок counter == 1. manager_connection также содержит C++ (Qt) private: T_receiver *_receiver; // указатель на receiver smart_ptr<trigger> _spy; // шпион, он же trackable ... При вызове одного из 4 конструктора manager_connection происходит следующее: C++ (Qt) manager_connection(signal<T_return, T_arg> &s, T_receiver *obj, function_type_4 slot) { _receiver = obj; // копируем указатель _spy = _receiver->spy; /* копируем шпиона, который вкурсе что происходит с receiverОМ по средством функции bool get() const */ _slot_4 = slot; _index = 4; s.connect(this); // Заносим данное соединение в список соединений нашего сигнала } Конечно, в пользовательском коде реально используется только два класса: signal и trackable и ещё один из вариантов перегруженной функции connect: C++ (Qt) template <class T_receiver, class T_return, class T_arg> void connect(signal<T_return, T_arg> &s, T_receiver *obj, T_return (T_receiver::*slot)(T_arg)) { new manager_connection<T_receiver, T_return, T_arg>(s, obj, slot); } в которой просто создаётся объект manager_connection и передаются все аргументы. Как то так.. Выкладываю для тестирования файл проекта. Немного причесал код, сейчас вроде всё работает адекватно))
|
|
|
1818
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 20, 2011, 16:26
|
А что если я хочу посылать сигналы объектам разных классов и принимать сигналы от объектов разных классов? И не думать о том каким именно объектам мне слать и получать до того момента когда наступет нужда создать соединение (уже в самом пользовательском коде)?
А в чем помеха? Объект создается с пустыми контейнерами sender'ов (receiver'ов), connect (который так или иначе неизбежен) их заполняет Помеха в том, что в контейнере должны будут находится объекты одного класса. Либо сделать один абстрактный класс, но тогда придётся писать интерфейс на все случаи жизни, что не есть гут) Идея в том, что общаться могут объекты совершенно разных классов. Задаётся лишь общий шаблон функции сигнала и слота. Или как Вы имеете в виду?
|
|
|
1819
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 20, 2011, 15:00
|
Переписал smart_ptr, как предложил brankovic Вроде сейчас утечек нет: C++ (Qt) #ifndef SMART_PTR_H #define SMART_PTR_H namespace ssc { template <class T> class smart_ptr { public: smart_ptr(); smart_ptr(const smart_ptr<T> &other); smart_ptr(T *p); ~smart_ptr(); bool is_null() const; T* operator->() const; T& operator*() const; T* get() const; smart_ptr<T> &operator=(const smart_ptr<T> &p); private: T *_obj; int *_counter; void try_destroy(); smart_ptr<T> &operator=(T*); }; template <class T> inline smart_ptr<T>::smart_ptr() : _obj(0), _counter(0) { } template <class T> inline smart_ptr<T>::smart_ptr(const smart_ptr<T> &other) : _obj(other._obj), _counter(other._counter) { if (_counter) (*_counter)++; } template <class T> inline smart_ptr<T>::smart_ptr(T *p) : _obj(p), _counter(new int(1)) { } template <class T> inline void smart_ptr<T>::try_destroy() { if (!_obj) return; if ((*_counter) == 1) { delete _counter; _counter = 0; delete _obj; _obj = 0; } } template <class T> inline smart_ptr<T>::~smart_ptr() { try_destroy(); } template <class T> inline bool smart_ptr<T>::is_null() const { return !_obj; } template <class T> inline T* smart_ptr<T>::operator->() const { return _obj; } template <class T> inline T& smart_ptr<T>::operator*() const { return *_obj; } template <class T> inline T* smart_ptr<T>::get() const { return _obj; } template <class T> inline smart_ptr<T>& smart_ptr<T>::operator=(const smart_ptr<T> &p) { if (_obj != p._obj) { try_destroy(); _counter = p._counter; _obj = p._obj; if (_counter) (*_counter)++; } return *this; } template <class T> inline smart_ptr<T>& smart_ptr<T>::operator=(T*) { return *this; } template <class T> inline bool operator==(const T *o, const smart_ptr<T> &p) { return o == p.operator->(); } template<class T> inline bool operator==(const smart_ptr<T> &p, const T *o) { return p.operator->() == o; } template <class T> inline bool operator==(T *o, const smart_ptr<T> &p) { return o == p.operator->(); } template<class T> inline bool operator==(const smart_ptr<T> &p, T *o) { return p.operator->() == o; } template<class T> inline bool operator==(const smart_ptr<T> &p1, const smart_ptr<T> &p2) { return p1.operator->() == p2.operator->(); } template <class T> inline bool operator!=(const T *o, const smart_ptr<T> &p) { return o != p.operator->(); } template<class T> inline bool operator!= (const smart_ptr<T> &p, const T *o) { return p.operator->() != o; } template <class T> inline bool operator!=(T *o, const smart_ptr<T> &p) { return o != p.operator->(); } template<class T> inline bool operator!= (const smart_ptr<T> &p, T *o) { return p.operator->() != o; } template<class T> inline bool operator!= (const smart_ptr<T> &p1, const smart_ptr<T> &p2) { return p1.operator->() != p2.operator->(); } } #endif // SMART_PTR_H
Как сделать теперь его тред-сейф ? Так какой вариант: со шпионом (он же trackable в libsigc++) или через умные указатели использовать? Как идеалогически правильнее?
|
|
|
1820
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 20, 2011, 13:50
|
Следующий шаг - это наследование класса recivera от класса spy, вместо создания его экземпляра и можно переименовывать spy в trackble. Но всё же эти две реализации схемы сигнал-слот отличаются) Идея отнаследоваться от spy это хорошо, мы теперь уже явно в коннект не будем передавать шпиона.. А если делать это по простому/народному, не связываясь ни с какими указателями? Ну у объекта 2 контейнера указателей - кому он посылает и кто ему посылает. Деструкторы вычеркивают из этих контейнеров, оператор = может копировать контейнеры, а может и нет (как нравится). Ну "навести песики" типа C++ (Qt) class CMyClass : public CSignalReceiver, public CSignalSender {..
А что если я хочу посылать сигналы объектам разных классов и принимать сигналы от объектов разных классов? И не думать о том каким именно объектам мне слать и получать до того момента когда наступет нужда создать соединение (уже в самом пользовательском коде)?
|
|
|
1821
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 20, 2011, 12:30
|
Чем не нравится такой ptr:
1. утечка памяти (не удаляется valid) 2. туманная семантика (хотя тут я, возможно, просто мыслю шаблонами типа "должно быть как boost::shared_ptr") 3. не тред-сейф (легко исправить)
Почему бы не выкинуть is_killer и вместо bool is_valid не сделать int counter? Завладев указателем счётчик увеличиваем, потеряв его (через деструктор или operator=) счётчик уменьшаем. Последний владелец это тот, кто опустит счётчик до нуля, тогда можно удалить и счётчик и T.
Да, Вы правы, я малость перемудрил с ptr. Вариант с каунтером гораздо лучше. У меня просто в голове крутилась идея что убить объект должен именно тот, кто им первым завладеет.. как раз хочется другой вариант. smart_ptr всё равно понадобится, но чтобы спрятать его внутрь
Другой вариант заклюсается в том, что мы создаём в класса receivera некий объект шпион, который будет следить за своим хозяином: C++ (Qt) class B { public: B() {} void slot1(const std::string &str) { std::cout << "slot1, signal - " << str << std::endl; } void slot2(std::string str) const { std::cout << "slot2, signal - " << str << std::endl; } ssc::spy spy; // Вот этот объект. Его предназначение, следить за своим владельцем. private: int _i; };
Но теперь, при создании соединения необходимо также передать ссылку на шпиона (млин, теперь в connect на один аргумент стало больше ) пример: C++ (Qt) int main() { A *a = new A; B *b = new B(12); connect(a->my_signal, b, &B::slot1, b->spy); connect(a->my_signal, b, &B::slot2, b->spy); a->run(); return 0; } Всё.. Если теперь удалить объект delete b то соединение разорвётся. Сам шпион представляет из себя следующее: C++ (Qt) class spy { public: spy() : _valid(new bool(true)) {} ~spy() { *_valid = false; } bool operator()() const { return *_valid; } template <class T1, class T2, class T3> friend class manager_connection; private: bool *_valid; }; Хотя на первый взгляд, при уничтожении spy происходит утечка (остаётся висячим _valid) это не совсем так, поскольку его другом является manager_connection и соответственно имеет доступ к его закрытым членам и он ответственен за зачистку указателя _valid. Теперь, при уничтожении хозяина: delete b, будет также вызван деструктор шпиона, который сделает: *_valid = false; Но соединение с объектом b создано раньше и владеет указателем на _valid и поэтому всегда знает, что в данный момент происходит с b.
|
|
|
1822
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 20, 2011, 01:06
|
1) signal 2) smart_ptr
По сигналу: теперь ресивера _обязательно_ заворачивать в smart_ptr? Теперь обязательно, для того что бы при уничтожении receiver а разрывалось и соответствующее соединение. Хотя есть и другой вариант как это сделать без использования smart_ptr. 1) signal 2) smart_ptr
smart_ptr просто ужасный: 1. деструктор и operator= должны вызывать общий метод destroy, чтобы их поведение было консистентным (в operator= вы забыли *valid=0, кроме того is_killer обнуляется и объект никто не удалит -- утечка памяти) Постараюсь объяснить логику этого указателя (для краткости в дальнейшем просто ptr): ptr может быть либо киллером либо нет. У киллера есть право убить объект. Т.е. право убить объект принадлежит тому, кто первый им завладел. пример: C++ (Qt) smart_ptr<B> p1(new B); // p1 - киллер и убъёт объект smart_ptr<B> p2 = p1; /* p2 - не имееет права убивать объект, он просто копирует указатель на на него. флаг _is_killer = false. Сам объект не клонируется. */
Другая ситуация: C++ (Qt) smart_ptr<B> p1(new B); // p1 - киллер и убъёт объект smart_ptr<B> p2(new B); // p2 - тоже киллер! // Внимание фокус! p2 = p1; /* Поскольку p2 - киллер он вначале убъёт объект на который ссылается, затем скопирует указатель на объект на который ссылается p1. Далее он сбросит флаг _is_killer = false и лишится права удалять объект, поскольку им уже владел до него p1 и владеет. Флаг _valid он скопирует также, и соответственно _valid == true, так что пока всё хорошо)) */ // А вот здесь: p1 = p2; /* Ничего не произойдёт, поскольку operatop=() сначало проверяет не ссылаются ли они на один и тот же объект. И если да (а в данном случае так и есть) то return *this и всё.*/
Т.е. идея в том, что указателей на объект может быть много, но среди них только у одного есть право его убить. Каждый указатель может изменять данные объекта, но не клонировать его при этом. После того, как киллер убъёт объект, все остальные смогут узнать об этом, за счёт флага _valid, который будет равен *_valid == false. Кстати, вот он так и будет висеть и никто его никогда не удалит, но это 1 висячий байт... За то польза)) 2. smart_ptr это симметричный объект, не может быть один "киллер", потому что если он погибнет раньше остальных, у других ptr-а не станет. Каждый владелец ptr может оказаться последним, "киллером".
Если киллер умрёт, то он за одно убъёт и сам объект и зделает не валидными оставшиеся ptrЫ. Я такого поведения от него и добивался. А как Вы видете это всё? Как по Вашему более правильно организовать логику? Спасибо за обсуждение)
|
|
|
1823
|
Qt / Пользовательский интерфейс (GUI) / Re: QColor
|
: Февраль 19, 2011, 23:22
|
Пробовал так: const QColor * c = & int QColor::red () const; const int * c = & int QColor::red () const;
Ну вы и извращенец)) Даже я бы так не смог придумать)) Надо будет запомнить)
|
|
|
1824
|
Qt / Пользовательский интерфейс (GUI) / Re: QColor
|
: Февраль 19, 2011, 23:14
|
Пробовал так: const QColor * c = & int QColor::red () const; const int * c = & int QColor::red () const;
Ну вы и извращенец)) Даже я бы так не смог придумать)) Надо будет запомнить)
|
|
|
1825
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 19, 2011, 20:13
|
Дописал) Теперь соединение автоматически разрывается, если один из объектов уничтожается. Пришлось для этого писать свой умный указатель (smart_ptr), который следит за всем этим делом.. Зато получаем все плюшки автоматического удаления объектов Все классы помещены в пространство имён ssc (от signal slot connection) Базовые два класса это: 1) signal 2) smart_ptr Используется так: C++ (Qt) #include <iostream> #include <string> #include "signal_slot.h" class A { public: A() { std::cout << "A()" << std::endl; } ~A() { std::cout << "~A()" << std::endl; } ssc::signal<void, std::string> my_signal; void run() { my_signal("Hello Word!"); } }; class B { public: B() : _i(0) { std::cout << "B()" << std::endl; } B(int i) : _i(i) { std::cout << "B(int i = " << _i << ")" << std::endl; } ~B() { std::cout << "~B(); i = " << _i << std::endl; } void slot1(const std::string &str) { std::cout << "slot1, signal - " << str << " i = " << _i << std::endl; } void slot2(std::string str) const { std::cout << "slot2, signal - " << str << " i = " << _i << std::endl; } private: int _i; }; int main() { ssc::smart_ptr<A> a = new A; // A *a = new A; можно и так, но придётся удалять руками //{ если раскомментировать, соединения автоматически разорвуться ssc::smart_ptr<B> p(new B(12)); /* B *b = new B(12) а вот так можно, но в connect мы его не сможем засунуть поскольку connect хочет чтоб b был умным)) */ connect(a->my_signal, p, &B::slot1); connect(a->my_signal, p, &B::slot2); //} см. выше a->run(); return 0; } Исходники прилогаются. Прошу потестить, кому не лень. Возможно я где нить накасячил) Конструктивная критика приветствуется)
|
|
|
1826
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 18, 2011, 22:38
|
Вроде всё работает Теперь всё хорошо и работает так: Уже симпатично выглядит. А что будет если объект 'b' разрушится (delete например), а потом 'a' испустит сигнал? В общем самое простое решение я вижу так: Нужно разорвать соединение, если объект b разрушится. Это можно сделать, если завернуть объект b в умный указатель, который занулит себя при уничтожении b. А поскольку этот указатель хранится в manager_connection то перед тем как вызывать operator()() проверять его на валидность. Как то так.. Сейчас попробую код накатать..
|
|
|
1827
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 18, 2011, 20:43
|
Просто в последним варианте, при использовании этого механизма никаких явных template писать уже не нужно, говорю ж всё максимально приближено к Qt варианту сигнал-слот.
Ну а зачем Вы выбрали тему которая уже известна, более того (в каком-то смысле "авторитетна")? Это, на мой взгляд, неразумно/непрактично. Ну посидеть пару вечерков конечно можно - но на этом дело кончится. Да и что "такого уж хорошего" в ихней схеме слот/сигнал? Везде есть нормальное "sendEvent" (выполнить немедленно) и "postEvent" (засунуть в очередь). Нормальный программист легко этим пользуется, зачем это накручивать в виде MOC компилятора? В результате мы часто видим "месиво из сигналов" вместо нормального, логичного текста. Ну во-первых лично моё имхо, механизм сигнал-слот - это очень удобная штука. И реализация в Qt это не единственная её реализация. Я не хочу сказать, что в Qt с помощью moc - это круто, напротив, вызов обходится дороже, чем например в схеме сигнал-слот в boost. Во-вторых я предложил вариант сигнал-слот отличный от реализованного в Qt и отличный от реализации в boost::signal. (как правильно заметил brankovic в boost всё завязано на boost::function) Это своего рода ещё одна вариация на тему)) И я считаю имеет право быть, хотя бы как объект теоретического исследования) Короче, Нет ничего практичнее хорошей теории))
|
|
|
1828
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 18, 2011, 20:03
|
m_ax, мои замечания - чисто субъективны, я не пытаюсь о чем-то авторитетно судить, делать выводы и.т.п. Если возникнет вопрос "пользоваться этим или нет", то мой однозначный ответ "нет", и (возможно) я буду здесь совсем не один. Наверняка Вы сделали все правильно, но каждый template требует как-то "настроить мозги". То есть "врубиться" конечно можно, но это обходится недешево, это надо держать в памяти и не забывать. Когда программист сосредоточен на прикладном аспекте - это особенно болезненно. Нет желанной "простоты использования". Еще раз - это мое субъективное мнение, не более того Отчасти я Вас понимаю, но с другой стороны не писать же с нуля весь инструментарий? Я например, как и многие другие использую Qt и я совсем не парюсь по поводу сколько там у них template или ещё чего. Я в исходники то их от силы раза 3-4 заглядывал)) Мне остаётся только довериться разработчикам) Или Вы что-то другое имеете ввиду? Просто в последним варианте, при использовании этого механизма никаких явных template писать уже не нужно, говорю ж всё максимально приближено к Qt варианту сигнал-слот. Есть, тут правда ещё недопиленные места, но это детали..
|
|
|
1829
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 18, 2011, 19:48
|
Вроде всё работает Теперь всё хорошо и работает так: Уже симпатично выглядит. А что будет если объект 'b' разрушится (delete например), а потом 'a' испустит сигнал? Известно что: грохинг программы Я как раз курю на эту тему)) Если есть предложения буду рад выслушать.
|
|
|
1830
|
Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот
|
: Февраль 18, 2011, 19:28
|
Вроде всё работает Теперь всё хорошо и работает так: main.cpp C++ (Qt) #include <iostream> #include <string> #include "signal_slot.h" class A { public: A() {} signal<void, std::string> my_signal; void run() { my_signal("Hello Word!"); } }; class B { public: B() {} void slot1(const std::string &str) { std::cout << "slot1, signal - " << str << std::endl; } void slot2(std::string str) const { std::cout << "slot2, signal - " << str << std::endl; } }; int main() { A a; B b; connect(&b, &B::slot1, &a.my_signal); connect(&b, &B::slot2, &a.my_signal); a.run(); return 0; }
Теперь всё как в Qt и только с использованием шаблонов Функция connect создаёт соединение между слотом объекта класса b и сигналом объекта a. Сам сигнал представляет из седя шаблонный класс template <class T_return, class T_arg> class signal где T_return - тип возвращаемого аргумента T_arg - тип передаваемого аргумента Если нужно чтобы ваш клас умел испускать сигналы необходимо просто включить класс сигнала в определение класса, как в примере: C++ (Qt) class A { public: A() {} /* Объявляем сигнал, который будет соеденён с функцией, которая возвращает void и принимает один аргумент std::string */ signal<void, std::string> my_signal; /* В той функции, где необходимо вызвать сигнал, просто вызываем сигнал как обычную функцию */ void run() { my_signal("Hello Word!"); } }; Сама реализация механизма сигнал-слот: C++ (Qt) #ifndef SIGNAL_SLOT_H #define SIGNAL_SLOT_H #include <list> template <class T_return, class T_arg> class base_signal { public: base_signal() {} virtual ~base_signal() {} virtual T_return operator() (const T_arg &) = 0; }; template <class T_receiver, class T_return, class T_arg> class manager_connection; template <class T_return, class T_arg> class signal { public: signal() {} ~signal() { for (_iterator it = _list.begin(); it != _list.end(); it++) { delete *it; } _list.clear(); } T_return operator() (const T_arg &arg) { for (_iterator it = _list.begin(); it != _list.end(); it++) { (*it)->operator()(arg); } } template <class T1, class T2, class T3> friend class manager_connection; private: std::list<base_signal<T_return, T_arg>* > _list; typedef typename std::list<base_signal<T_return, T_arg>* >::iterator _iterator; void connect(base_signal<T_return, T_arg> *_signal) { _list.push_back(_signal); } }; template <class T_receiver, class T_return, class T_arg> class manager_connection : public base_signal<T_return, T_arg> { public: typedef T_return (T_receiver::*function_type_1)(T_arg); typedef T_return (T_receiver::*function_type_2)(const T_arg &); typedef T_return (T_receiver::*function_type_3)(T_arg) const; typedef T_return (T_receiver::*function_type_4)(const T_arg &) const; manager_connection(T_receiver *obj, function_type_1 slot, signal<T_return, T_arg> *s) { _receiver = obj; _slot_1 = slot; _index = 1; s->connect(this); } manager_connection(T_receiver *obj, function_type_2 slot, signal<T_return, T_arg> *s) { _receiver = obj; _slot_2 = slot; _index = 2; s->connect(this); } manager_connection(T_receiver *obj, function_type_3 slot, signal<T_return, T_arg> *s) { _receiver = obj; _slot_3 = slot; _index = 3; s->connect(this); } manager_connection(T_receiver *obj, function_type_4 slot, signal<T_return, T_arg> *s) { _receiver = obj; _slot_4 = slot; _index = 4; s->connect(this); } ~manager_connection() { } T_return operator()(const T_arg &arg) { if (_index == 1) return (_receiver->*_slot_1)(arg); if (_index == 2) return (_receiver->*_slot_2)(arg); if (_index == 3) return (_receiver->*_slot_3)(arg); if (_index == 4) return (_receiver->*_slot_4)(arg); return T_return(); } private: T_receiver *_receiver; function_type_1 _slot_1; function_type_2 _slot_2; function_type_3 _slot_3; function_type_4 _slot_4; int _index; manager_connection() : _receiver(0), _index(0) {} manager_connection(const manager_connection &) {} }; template <class T_receiver, class T_return, class T_arg> void connect(T_receiver *obj, T_return (T_receiver::*slot)(T_arg), signal<T_return, T_arg> *s) { new manager_connection<T_receiver, T_return, T_arg>(obj, slot, s); } template <class T_receiver, class T_return, class T_arg> void connect(T_receiver *obj, T_return (T_receiver::*slot)(const T_arg &), signal<T_return, T_arg> *s) { new manager_connection<T_receiver, T_return, T_arg>(obj, slot, s); } template <class T_receiver, class T_return, class T_arg> void connect(T_receiver *obj, T_return (T_receiver::*slot)(T_arg) const, signal<T_return, T_arg> *s) { new manager_connection<T_receiver, T_return, T_arg>(obj, slot, s); } template <class T_receiver, class T_return, class T_arg> void connect(T_receiver *obj, T_return (T_receiver::*slot)(const T_arg &) const, signal<T_return, T_arg> *s) { new manager_connection<T_receiver, T_return, T_arg>(obj, slot, s); } #endif // SIGNAL_SLOT_H
Архив с проектом прикреплён.
|
|
|
|
|