Russian Qt Forum
Май 11, 2024, 18:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало Форум WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  
  Просмотр сообщений
Страниц: 1 ... 121 122 [123] 124 125 ... 140
1831  Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот : Февраль 18, 2011, 17:14
Цитировать
нет, это очень плохо, в частности из-за гемороя с указателями на виртуальные методы.
Ну вот, так и знал))

Ладно, будем думать дальше)

boost::function

Спасибо)) Я кажысь раскурил как это всё можно реализовать)

Сейчас накатаю код, выложу
1832  Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот : Февраль 18, 2011, 14:16
Цитировать
нет, это очень плохо, в частности из-за гемороя с указателями на виртуальные методы.
Ну вот, так и знал))

Ладно, будем думать дальше)
1833  Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот : Февраль 17, 2011, 17:50
А чем boost::signal не устроил?
Вопрос носит чисто теоретический характер)
1834  Qt / Кладовая готовых решений / Частный случай механизма сигнал-слот : Февраль 17, 2011, 17:35
Решил тут для себя разобраться в реализации сигнально-слотового механизма, основаного на шаблонах.
Выкладываю то что успел накатать (описание ниже):

файл signal_slot.h
Код
C++ (Qt)
#ifndef SIGNAL_SLOT_H
#define SIGNAL_SLOT_H
 
#include <list>
 
template <class T_receiver, class T_return, class T_arg>
class Slot
{
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;
 
 
   Slot(T_receiver *obj, function_type_1 slot);
   Slot(T_receiver *obj, function_type_2 slot);
   Slot(T_receiver *obj, function_type_3 slot);
   Slot(T_receiver *obj, function_type_4 slot);
 
   ~Slot();
 
   T_return operator() (const T_arg &arg);
 
private:
   Slot();
   function_type_1 _slot_1;
   function_type_2 _slot_2;
   function_type_3 _slot_3;
   function_type_4 _slot_4;
 
   T_receiver *_obj;
   int _index;
};
 
 
template <class T_receiver, class T_return, class T_arg>
inline Slot<T_receiver, T_return, T_arg>::Slot()
{
}
 
template <class T_receiver, class T_return, class T_arg>
inline Slot<T_receiver, T_return, T_arg>::Slot(T_receiver *obj, function_type_1 slot)
{
   _obj = obj;
   _slot_1 = slot;
   _index = 1;
}
 
template <class T_receiver, class T_return, class T_arg>
inline Slot<T_receiver, T_return, T_arg>::Slot(T_receiver *obj, function_type_2 slot)
{
   _obj = obj;
   _slot_2 = slot;
   _index = 2;
}
 
template <class T_receiver, class T_return, class T_arg>
inline Slot<T_receiver, T_return, T_arg>::Slot(T_receiver *obj, function_type_3 slot)
{
   _obj = obj;
   _slot_3 = slot;
   _index = 3;
}
 
template <class T_receiver, class T_return, class T_arg>
inline Slot<T_receiver, T_return, T_arg>::Slot(T_receiver *obj, function_type_4 slot)
{
   _obj = obj;
   _slot_4 = slot;
   _index = 4;
}
 
template <class T_receiver, class T_return, class T_arg>
inline T_return Slot<T_receiver, T_return, T_arg>::operator ()(const T_arg &arg)
{
   if (_index == 1)
      return (_obj->*_slot_1)(arg);
   if (_index == 2)
       return (_obj->*_slot_2)(arg);
   if (_index == 3)
       return (_obj->*_slot_3)(arg);
 
   return (_obj->*_slot_4)(arg);
}
 
 
template <class T_receiver, class T_return, class T_arg>
class Signal
{
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;
 
   Signal();
   ~Signal();
 
   void operator()(const T_arg &arg);
 
   void connect(T_receiver &obj, function_type_1 slot);
   void connect(T_receiver &obj, function_type_2 slot);
   void connect(T_receiver &obj, function_type_3 slot);
   void connect(T_receiver &obj, function_type_4 slot);
 
private:
   std::list<Slot<T_receiver, T_return, T_arg>* > _list;
   typedef typename std::list<Slot<T_receiver, T_return, T_arg>* >::iterator _iterator;
 
};
 
template <class T_receiver, class T_return, class T_arg>
inline Signal<T_receiver, T_return, T_arg>::Signal()
{
}
 
template <class T_receiver, class T_return, class T_arg>
inline Signal<T_receiver, T_return, T_arg>::~Signal()
{
   _list.clear();
}
 
template <class T_receiver, class T_return, class T_arg>
inline void Signal<T_receiver, T_return, T_arg>::connect(T_receiver &obj, function_type_1 slot)
{
   _list.push_back(new Slot<T_receiver, T_return, T_arg>(&obj, slot));
}
 
template <class T_receiver, class T_return, class T_arg>
inline void Signal<T_receiver, T_return, T_arg>::connect(T_receiver &obj, function_type_2 slot)
{
   _list.push_back(new Slot<T_receiver, T_return, T_arg>(&obj, slot));
}
 
template <class T_receiver, class T_return, class T_arg>
inline void Signal<T_receiver, T_return, T_arg>::connect(T_receiver &obj, function_type_3 slot)
{
   _list.push_back(new Slot<T_receiver, T_return, T_arg>(&obj, slot));
}
 
template <class T_receiver, class T_return, class T_arg>
inline void Signal<T_receiver, T_return, T_arg>::connect(T_receiver &obj, function_type_4 slot)
{
   _list.push_back(new Slot<T_receiver, T_return, T_arg>(&obj, slot));
}
 
template <class T_receiver, class T_return, class T_arg>
inline void Signal<T_receiver, T_return, T_arg>::operator ()(const T_arg &arg)
{
   for (_iterator it = _list.begin(); it != _list.end(); it++)
       (*it)->operator()(arg);
}
 
#endif // SIGNAL_SLOT_H
 


Краткое описание.

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

Класса Slot
Он фактически представляет из себя функторный класс, который биндит указатель на метод класса, который (метод) будет реализовывать слот.
Этот класс пользователь в своём коде явно нигде не использует. Он введён для удобства и используется классом Signal

Класс Signal объявлен как
Код
C++ (Qt)
template <class T_receiver, class T_return, class T_arg> class Signal
 
где
T_receiver - это класс получатель
T_return - тип возвращаемого аргумента функции (слота)
T_arg - тип аргумента (слота и сигнала, соответственно)

Используется это так:

файл main.cpp
Код
C++ (Qt)
#include <iostream>
#include <string>
 
#include "signal_slot.h"
 
 
template <class T>
class Sender
{
public:
   Sender() {}
   Signal<T, void, std::string> signal;
 
   void run() {
       signal("Hello word!");
   }
};
 
class Receiver
{
public:
   Receiver(){}
 
   void mySlot1(const std::string &str) {
       std::cout << "mySlot1 received a signal: " << str << std::endl;
   }
   void mySlot2(std::string str) {
       std::cout << "mySlot2 receiver a signal: " << str << std::endl;
   }
 
};
 
 
int main()
{
   Sender<Receiver> sender;
   Receiver receiver;
 
   sender.signal.connect(receiver, &Receiver::mySlot1);
   sender.signal.connect(receiver, &Receiver::mySlot2);
 
   sender.run();
 
   return 0;
}
 

Недостатком такого подхода является то, что общатся между собой могут лишь объекты тех классов, что указаны (в параметрах шаблона) при их создании. Т.е. в данном случае, объекты класса Receiver могут получать сигналы от объектов класса Sender. Но объекты класса Sender не могут слать сигналы объектам другого класса, если при определении класа Sender не указать дополнительный параметр шаблона и соответствующий сигнал с этим параметром.

Я пока не раскурил, как эта проблема решена, например в boost или в libsigc++  Грустный
Если кто подскажет, скажу спасибо)

Далее хотелось бы реализовать метод disconnect, а также при коннекте проверять, есть ли в списке зарегистрированных слотов тот, который коннектится. Сейчас, если дважды подрят вызвать connect то в список будет содержать два одинаковых слота, что не есть гут.
Как это сделать пока думаю над этим..

Ещё такой вопрос: кто знает как присвоить указатель на метод одного класса к указателю на метод другого класса? И хорошо ли это?

В общем делаю это,  в первую очередь, чтоб разобраться со всем этим делом))   

архив с проектом прикреплён   


1835  Программирование / С/C++ / Re: Передача данных : Февраль 16, 2011, 22:21
Боюсь это работать не будет.
Статические функции класса могут юзать только статические переменные и статические же функции.
1836  Программирование / С/C++ / Re: Передача данных : Февраль 16, 2011, 21:56
Цитировать
Может я не правильно что-то понял, но почему бы не сделать один абстрактный класс, со статической функцией, а классы А и Б просто унаследовать от этого класса, ну а когда в классе А изменяется переменная, вызывать эту функцию
Я что то не улавливаю причинно-следственную связь..  Непонимающий Видимо уже не соображаю под вечер))
1837  Программирование / С/C++ / Re: Передача данных : Февраль 16, 2011, 18:50
Вся проблема, как я понял, в синтаксическом удобстве. Нет?
1838  Программирование / С/C++ / Re: Передача данных : Февраль 16, 2011, 17:11
libsig++ Хороший вариант

Если нехочется прикручивать всю библиотеку то можно сделать так:

Код
C++ (Qt)
#include <iostream>
 
using namespace std;
 
 
template <class T, typename U>
class Signal
{
public:
   Signal() {
       _obj = 0;
       _slot = 0;
   }
   void operator()(const U& val) {
       if (_obj) {
           (_obj->*_slot)(val);
       }
   }
   void connect(T *obj, void (T::*slot)(const U &)) {
       _obj = obj;
       _slot = slot;
   }
 
private:
   T *_obj;
   void (T::*_slot)(const U &);
};
 
 
template<class T>
class Sender
{
public:
   Sender(){}
   Signal<T, int> signal;
   void run() {
       signal(123);
   }
};
 
class Receiver
{
public:
   Receiver() {}
   void slot(const int &x) {
       cout << x << endl;
   }
};
 
int main()
{
   Sender<Receiver> sender;
   Receiver receiver;
   sender.signal.connect(&receiver, &Receiver::slot);
 
   sender.run();
 
   return 0;
}
 
 
Это фактически сильно упрощённая схема сигнал-слот, реализованая в libsig++
1839  Программирование / Алгоритмы / Re: Распознать кубик : Февраль 12, 2011, 23:48
Так сам парралепипед задан? Или есть только туева хуча точек и больше ничего?

Если второе могу предложить оч быстрый и простой метод:
Код
C++ (Qt)
bool isParallepipet(const vector<Point3D> &/*data*/) {
   return (rand() > RAND_MAX/2);
}
 

 Крутой
1840  Программирование / Алгоритмы / Re: Распознать кубик : Февраль 12, 2011, 23:40
Я не правильно понял условие задачи.  Злой
Я имел в виду: провирить являются ли заданные 8 вершин - вершинами параллеограмма.

Тогда положение меняется))
1841  Программирование / Алгоритмы / Re: Распознать кубик : Февраль 12, 2011, 23:10
Да всё просто, млин))

1) Берём любые 3 точки. (Через 3 точки всегда можно провести плоскость)
2) Перебираем оставшиеся 5 точек и для каждой проверяем, лежит ли она в данной плоскости (см п.1)
3) Если нет - это не параллепипед. Если лежит, то проверяем, является ли она 4-ой вершиной параллеограмма на плоскости. Если нет - это не параллепипед
4) Если да, запоминаем эти 4 точки. Выбираем из этих 4-ёх точек любые 2 и из оставшихся 4ёх берём любую одну точку - получается 3 точки.
5) Перебираем из оставшихся 3ёх точек каждую точку и проверяем лежит ли она в плоскости, образованой теми тремя точками. Если ни одна не лежит - это не параллепипед, если да проверяем является ли она 4ой вершиной параллеограмма. Если нет - это не параллепипед
6) Если да..
Дальше докончите сами))

Мне бы ваши проблемы Смеющийся
1842  Программирование / Алгоритмы / Re: Распознать кубик : Февраль 12, 2011, 20:32
Зачем было тогда смущать народ словом кубик?

Первое что приходит в голову для распознавания параллепипеда:
1) Выбираем любые 3 точки. Как известно, через 3 точки мона провести плоскость. Поскольку в данной плоскости должен лежать параллеограмм, перебираем оставшиеся 5 точек и ищем среди них ту, которая должна лежать в четвёртой вершине. Если такой нет, то эт не параллепипед.
2) Если среди тех 5 точек такая точка находится, то у нас имеется плоскость, проходящая через известные нам 4 точки и остаётся ещё 4 точки.
3) Проверяем, проходит ли через них плоскость: если нет - то эт не параллеограмм.
4) Если да, находим вектор нормали и проверяем, коллинеарен ли он вектору нормали первой плоскости.
5) Если да... решение близко))
1843  Программирование / Алгоритмы / Re: Распознать кубик : Февраль 12, 2011, 19:33
Если ставится задача распознать именно куб, то решение достаточно простое:
1) выбирается произвольная точка.
2) Строится 7 векторов от этой точки до оставшихся вершин
3) Считается длина каждого вектора
4) Если это куб то должно быть: 3 длины должна совпадать и равны длинам рёбер куба, 3 другие длины должны совпадать и равны sqrt(2) * a ( a длина куба) и длина одного из векторов должна быть равна: угадайте чему))
1844  Программирование / Алгоритмы / Re: Распознать кубик : Февраль 12, 2011, 19:21
Так чтож конкретно нужно: распознать куб или параллепипед?
Куб - эт частный случай параллепипеда.
да не суть важно, от общего идем к частностям, тут просто Igors в своем репертуаре Улыбающийся
Я это к тому, что куб распознать гораздо проще. Вот пример:
Упростим задачу: Нужно распознать квадрать от другой фигуры. Пусть также каждая вершина фигуры имеет три координаты (x, y, z).
Для распознания квадрата алгоритм прост:
1) Проверяем число вершин: если их 4 переходим к пункту 2
2) Берём произвольную точку (пусть A(x1, y1, z1) )
Строим 3 вектора AB, AC, AD.
3) Перемножаем векторно N1 = [AB, AC], N2 = [AC, AD].
4) Если вестора N1 и N2 коллинеарны и равны по модулю, и (AB, AD) = 0 или (AB, AC)=0 - это квадрат
ежели нет, то не факт что это параллепипед вообще.  
1845  Программирование / Алгоритмы / Re: Распознать кубик : Февраль 12, 2011, 19:07
Так чтож конкретно нужно: распознать куб или параллепипед?
Куб - эт частный случай параллепипеда.
Страниц: 1 ... 121 122 [123] 124 125 ... 140

Страница сгенерирована за 0.413 секунд. Запросов: 24.