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

Войти
 
  Начало Форум WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  
  Просмотр сообщений
Страниц: 1 ... 118 119 [120] 121 122 ... 140
1786  Программирование / С/C++ / Re: Где взять информацию про имеющиеся классы исключений на Си++? : Март 03, 2011, 14:35
Цитировать
Ну это сильно проигрывает обычному exception

- код не прерывается, надо вставлять return, если ф-ция глубоко вложена - то везде по стеку

- напр. человек разрабатывает класс пока не заботясь как он будет использоваться. Но он уже должен иметь ввиду некую систему, полагать что в дальнейшем (каждый) пользователь класса свяжет "слот-сигнал веники" до того. А тот пользователь в еще более неловком положении потому что Вы заставляете его изучать Вашу систему  Улыбающийся Если напиcано throw - сразу ясно, а кто такой exception_type? Надо разбираться - а зачем?
Ну я с Вами тут не соглашусь. И вот почему:
1) Если ошибка настолько ужасна, что продолжать программу дальше нельзя, то стандартные исключения здесь очень кстати. После блока catch всё и закончится..
А вот если есть надежда, что обработчик исключения всёже как то исправит ситуацию, то нужно позаботится о том, чтобы заново повторить тот фрагмент, где было вызвано исключение. И вот здесь начинается самое весёлое. Т.е. после обработки исключения в блоке catch Вам придётся явно! вернуть управление к точке возникновения ошибки.
Как? Помещать блок try в бесконечный цикл? Нет уж, спасибо))

Цитировать
- напр. человек разрабатывает класс пока не заботясь как он будет использоваться. Но он уже должен иметь ввиду некую систему, полагать что в дальнейшем (каждый) пользователь класса свяжет "слот-сигнал веники" до того. А тот пользователь в еще более неловком положении потому что Вы заставляете его изучать Вашу систему
   
А я например могу не заставлять пользователя явно связывать сигнал со слотом. Это можно сделать в конструкторе класса, который занимается расчётами. И вместо класса ExceptionHandler, я могу определить просто функцию:
Код
C++ (Qt)
#include <iostream>
#include <string>
#include "signal_slot.h"
#include "messenger.h"
 
using namespace std;
 
 
typedef ssc::messenger3<string, string, double&> exception_type;
 
int funcF(double x, double y) {  // Пример функции, кидающей обычное исключение
   if (x == 0.0)
       throw exception_type("funcF", "divizion by zero", x);
   return y / x;
}
 
void exceptionHandler(const exception_type &e) { // Функция обработки исключений
   cout << e.arg1 << endl;
   cout << e.arg2 << endl;
   cout << e.arg3 << endl;
   const double epsilon = 0.0000001;
   e.arg3 = epsilon;
}
 
class SomeClass
{
public:
   SomeClass() { // В самом конструкторе соединяем наши сигналы с обработчиками
       exception.connect(exceptionHandler);
   }
   ssc::signal<const exception_type &> exception;
   double func(double x) {
       if (x == 0.0)
           exception(exception_type("func", "divizion by zero", x));
       return 1.0 / x;
   }
};
 
 
int main()
{
  SomeClass sc; // Создаём наш клас и всё..
 
  double res = sc.func(0.0); /* Проблемный момент, но мы хотим
                                                исправить ситуацию не прерывая программу! */

 
  cout << "res = " << res << endl; // До этой точки мы дойдём!
 
  try {
 
      double res = funcF(0.0, 1.0); // А вот функция, кидающая обычные исключения
      cout << "res = " << res << endl; // Сюда мы уже не попадём!! (без лишниз телодвижений)
 
  } catch (exception_type e) {
       cout << e.arg1 << endl;
       cout << e.arg2 << endl;
       cout << e.arg3 << endl;
       const double epsilon = 0.0000001;
       e.arg3 = epsilon; // Вот на этом всё и закончится)
  }
 
   return 0;
}
 
Поэтому это ещё спорный вопрос, что удобней))
1787  Программирование / С/C++ / Re: Где взять информацию про имеющиеся классы исключений на Си++? : Март 03, 2011, 12:52
Мне вообще, исключения не очень симпатичны.. Я их не использую, к тому же сейчас есть механизм сигнал-слот, который более изящно справляется с этим всем.
Хорошее словцо "изящно", но по-моему исключения и сигналы никак не альтернатива друг другу. Не видно даже такого примера когда вместо exception можно сигналить или наоборот.
[/quote]
Ну вот смотрите:
На примере деления на ноль.
1) У нас есть класс SomeClass, который реализует всякие там мат. вычисления.. Ниже код с пояснениями самой идеи. (использовал libssc)
Код
C++ (Qt)
#include <iostream>
#include <string>
#include "signal_slot.h"
#include "messenger.h"
 
using namespace std;
 
 
typedef ssc::messenger3<string, string, double&> exception_type; // Это класс, который содержит информацию о том что произошло и где это произошло.. ну и т.д.  
 
/* Вот этот класс и для простоты он имеет только одну функцию */
class SomeClass
{
public:
   ssc::signal<const exception_type &> exception; // сигнал - замещает исключения
 
   double func(double x) {
       if (x == 0.0) // пытаемся делить на ноль!
           exception(exception_type("func", "divizion by zero", x)); /* Шлём сигнал об этом безобразии, указывая также имя функции, где это произошло, что произошло, и ссылку на x*/
       return 1.0 / x;
   }
};
 
/* Класс обработчик исключений */
class ExceptionHandler : public ssc::trackable
{
public:
   void handleEvent(const exception_type& e) { /* Выводит информацию о том что случилось и */
       cout << e.arg1 << endl;
       cout << e.arg2 << endl;
       cout << e.arg3 << endl;
       const double epsilon = 0.0000001;
       e.arg3 = epsilon; // Вмешивается в дальнейший процесс, изменяя наш x!
   }
};
 
 
int main()
{
  SomeClass sc; // создаём наш класс
  ExceptionHandler eh; // создаём класс обработчик
 
  sc.exception.connect(&eh, &ExceptionHandler::handleEvent); // коннектим их
 
  double res = sc.func(0.0); // Вызываем функцию в нуле!
 
  cout << res << endl; // и что же получаем??
 
   return 0;
}
 

Ну вот приммерно так..
1788  Разное / Говорилка / Re: Покупка в США и выбор посредника. : Март 02, 2011, 23:33
Не знаю как насчёт americansale.ru, но у меня остались хорошие впечатления от eBay.
Заказывал там как то сначала фотик, потом объектив. Связался с селлером, договорились что да как и все дела))
Всё было доставлено в лучшем виде)     
1789  Программирование / С/C++ / Re: Где взять информацию про имеющиеся классы исключений на Си++? : Март 02, 2011, 21:04
Интересно, а правильно ли я понял, что для математических особых ситуаций мне потребуется самому создавать классы, если не пользоваться сторонними библиотеками (например для ситуации деления на ноль)?
Боюсь вам придётся переписывать все функции в которых потенциально возможно появление неприятностей.
Мне вообще, исключения не очень симпатичны.. Я их не использую, к тому же сейчас есть механизм сигнал-слот, который более изящно справляется с этим всем.

ЗЫ: тут в соседней ветке (про преобразование интов и флоатов) нечто подобное обсуждается.
Смеющийся Собственно, как я понял это и есть логическое продолжение той ветки)) Автор тот же))
1790  Программирование / С/C++ / Re: Где взять информацию про имеющиеся классы исключений на Си++? : Март 02, 2011, 17:28
Если Вы это по поводу математических вычислений, то могу посоветовать использовать библиотеку gsl.
Там уже в самой библиотеке предусмотрены возможные ошибки при вычислениях.
К тому же это очень полная библиотека с хорошей документацией + свободная.

http://www.gnu.org/software/gsl/
1791  Qt / Вопросы новичков / Re: Помощь при обучении (разработке) : Март 02, 2011, 16:49
Мне тоже такую штуку нужно: подсчёт символов в тексте. Но чтоб можно было считать символы из pdf документа.
Как напишете, опубликуйте) 
1792  Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот : Март 02, 2011, 16:11
Зарелизел третью версию libssc  Улыбающийся

Вненсены следующие изменения:
1) mem_fun_connection и fun_connection теперь ничего не знают о signal, что делает их более обособленными (самодостаточными)
2) В signal теперь список соединений содержит не указатели, а counted_ptr на base_connection, что повышает безопасность
3) Функции connect, disconnect перенесены в signal
4) в signal добавлены функции
Код
C++ (Qt)
void disconnect_all() // разрывает все сондинения
 
и
Код
C++ (Qt)
size_t slot_count() const // колличество всех соединений
 
5) Добавлены шаблонные классы messenger4, messenger3, messenger2, содержащие набор данных из 4, 3 и 2 полей соответственно:
Код
C++ (Qt)
template <class T_arg1, class T_arg2>
class messenger2
{
public:
   template <class T1, class T2>
   messenger2(const messenger2<T1, T2> &other)
       : arg1(other.arg1), arg2(other.arg2) {}
   messenger2() {}
   messenger2(const T_arg1 &_arg1, const T_arg2 &_arg2)
       : arg1(_arg1), arg2(_arg2) {}
   T_arg1 arg1;
   T_arg2 arg2;
};
//-----------------------------------------------------------------------------
 
template <class T1, class T2>
inline bool operator== (const messenger2<T1, T2> &p1, const messenger2<T1, T2> &p2)
{
   return ((p1.arg1 == p2.arg1) && (p1.arg2 == p2.arg2));
}
//-----------------------------------------------------------------------------
 
template <class T1, class T2>
inline bool operator!= (const messenger2<T1, T2> &p1, const messenger2<T1, T2> &p2)
{
   return ((p1.arg1 != p2.arg1) || (p1.arg2 != p2.arg2));
}
//-----------------------------------------------------------------------------
 

Пример использования:
Код
C++ (Qt)
#include <iostream>
#include <string>
#include "signal_slot.h"
#include "messenger.h"
 
using namespace std;
 
typedef ssc::messenger4<int, int, string, int> dataA;
typedef ssc::messenger4<float, double, string, int> dataB;
 
class A
{
public:
   A() {
       cout << "A()" << endl;
   }
   ~A() {
       cout << "~A()" << endl;
   }
 
   void run() {
       sig_a1(3.14);
       sig_a2(dataA(1, 2, "Hello!", 3));
   }
 
   ssc::signal<float> sig_a1;
   ssc::signal<const dataA &> sig_a2;
};
//-----------------------------------------------------------------------------
 
class B : public ssc::trackable
{
public:
   B() {
       cout << "B()" << endl;
   }
   ~B() {
       cout << "~B()" << endl;
   }
   void slot_b1(int x) {
       cout << "slot_b(int), i = " << x << endl;
   }
 
   void slot_b2(const dataB &x) {
       cout << "slot_b2(const dataB &)" << endl;
       cout << x.arg1 << endl;
       cout << x.arg2 << endl;
       cout << x.arg3 << endl;
       cout << x.arg4 << endl;
   }
   void slot_b2(const dataA &x) {
       cout << "slot_b2(const dataA &)" << endl;
       cout << x.arg1 << endl;
       cout << x.arg2 << endl;
       cout << x.arg3 << endl;
       cout << x.arg4 << endl;
   }
   void slot_b2() {
       cout << "slot_b2()" << endl;
   }
};
//-----------------------------------------------------------------------------
 
int main()
{
   A *a = new A;
   B *b = new B;
 
   a->sig_a1.connect(b, &B::slot_b1); // соединение с неперегруженным слотом
 
/* Слот slot_b2 - перегружен, поэтому необходимо указывать явно параметры шаблонов */
   a->sig_a2.connect<B, void, const dataB &>(b, &B::slot_b2);  /* Note: сигнал отправляет тип dataA, а
слот принимает тип dataB и это сработает!  */

   a->sig_a2.connect<B, void, const dataA &>(b, &B::slot_b2);
   a->sig_a2.connect<B, void>(b, &B::slot_b2);  // И этот слот также сработает
 
   a->run();
 
   delete a;
   delete b;
 
   return 0;
}
 

P.S. Протестировано Valgrind'ом, утечек не обнаружено.
1793  Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот : Февраль 28, 2011, 20:44
Ясненько)
Значит так просто я не смогу посылать сигналы из одного потока, скажем объекту в другом..
Вернее смогу но нет гарантий, что при выполнении слота, другой поток не прибьёт этот объект.
Или хранить в сигнале не указатели на объекты, а умные указатели (counted_ptr - он же smart_ptr в прошлом) 

Несколько обновил код, в частности,
1) smart_ptr теперь называется counted_ptr
2) метод void set(bool flag) в классе trigger перенёс в private:
Код
C++ (Qt)
class trigger
{
public:
   trigger() : _flag(true) {}
   bool get() const { return _flag; }
 
   friend class trackable;
 
private:
   void set(bool flag) { _flag = flag; }
   bool _flag;
};
 
чтоб никто, кроме trackable не мог изменить состояние объекта.
3) Всё же поскольку случай частный, оставил только передачу одного аргумета (в том числе и void)
не думаю что это вызовет неудобства, зато сразу кода скока поубавилось)

 
1794  Программирование / С/C++ / Re: Как правильно сделать преобразование для целых и вещественных чисел? : Февраль 28, 2011, 18:40
Ёлки зелёные))

И всё же почему в классе NNumeric не хранить переменную в double? Всё равно NNumeric у вас весит больше 4 байт.
А вместо операций, например в такой:
Код
C++ (Qt)
inline float Value() const {return this->data._value;}
 
 
делать следующее:
Код
C++ (Qt)
inline float Value() const {
   double d = fabs(this->data._value);
   bool sign = (this->data._value >= 0.0);
   if (d > std::numeric_limits<float>::max())
       return (sign) ? std::numeric_limits<float>::max() : -std::numeric_limits<float>::max();
   if (sign)
        return (d > std::numeric_limits<float>::min()) ? float(d) : float(0);
   return (d > std::numeric_limits<float>::min()) ? float(-d) : float(0);
}
 
double то Вам точно хватит)
1795  Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот : Февраль 28, 2011, 16:23
И ещё такой вопрос по поводу потокобезопасности:

Правильно ли то, чтобы гарантировать потокобезопасность соединения необходимо
сделать операцию
Код
C++ (Qt)
spy->set(false);
 
в деструкторе класса trackable атомарной?
Вот код trackable и trigger:
Код
C++ (Qt)
#ifndef TRACKABLE_H
#define TRACKABLE_H
 
#include "smart_ptr.h"
 
namespace ssc {
 
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;
};
//-----------------------------------------------------------------------------
 
} /* namespace ssc*/
 
#endif // TRACKABLE_H
 
Или нужно что то большее  Непонимающий
1796  Программирование / С/C++ / Re: Как правильно сделать преобразование для целых и вещественных чисел? : Февраль 28, 2011, 14:57
Если есть такая потребность в задаче делать подобные проверки (согласитесь не страндартный случай), то может просто написать свой класс мега астрономических чисел, который знал бы такие вещи как деление на ноль и всё такое? И вёл бы себя как обычное число, был бы совместим с double.
Почему нет?
1797  Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот : Февраль 27, 2011, 14:58
По этому принципу сделал ещё одно обобщение. Теперь можно соединять сигналы со слотами, у которых число аргументов может быть и меньше, чем число аргументов у сигнала.
Например сейчас можно подсоединить сигнал
Код
C++ (Qt)
ssc::signal<int, float> sig;
 
например с такими слотами:
Код
C++ (Qt)
void slot1();
void slot2(int);
void slot3(int, float); // (float, int); (double, double); (int, int) и т.д.    
 


Note: если имеется несколько перегруженных слотов, то чтоб компилятор понял какой имменно слот подключать к сигналу, нужно явно в шаблонной функции connect указать параметры шаблонов.
прмер:
Код
C++ (Qt)
#include <iostream>
#include <string>
#include "signal_slot.h"
#include <cmath>
 
class A
{
public:
   ssc::signal<int> sig_a2;
 
   ssc::signal<const double &, int> sig_a;
 
   void run() const {
 
      sig_a(M_PI, 123);
 
      sig_a2(1);
   }
};
 
class B : public ssc::trackable
{
public:
/* Класс B имеет 2 перегруженных слота */
 
   void slot_b(float x, int y) {
       std::cout << "slot_b, x = " << x << std::endl;
       std::cout << "slot_b, y = " << y << std::endl;
   }
 
   void slot_b() {
       std::cout << "slot_b" << std::endl;
   }
 
   void other_slot() {
       std::cout << "other slot" << std::endl;
   }
 
};
 
int main()
{
   A *a = new A;
   B *b = new B;
 
/* Для того, чтоб не смущать компилятор, нужно в этом случае явно указывать типы шаблонов */
   ssc::connect<B, void, float, int, const double&, int>(a->sig_a, b, &B::slot_b);
   ssc::connect<B, void, const double &, int>(a->sig_a, b, &B::slot_b);
 
/* А здесь всё как обычно, компилятор сам справится  */
   ssc::connect(a->sig_a2, b, &B::other_slot);
 
   a->run();
 
   delete b;
   delete a;
 
   return 0;
}
 
1798  Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот : Февраль 27, 2011, 01:01
А нельзя подключать с неполным совпадением прототипа? т.е. signal <int> к void slot (float)?
Теперь можно))
Решение неожиданно оказалось очень простым без всяких лишних введений посредника c.
Короче, теперь будет работать и так:
Код
C++ (Qt)
#include <iostream>
#include <string>
#include "signal_slot.h"
 
 
class A
{
public:
   ssc::signal<int> sig_a;
 
   ssc::signal<const std::string &> sig_a2;
 
   void run() const {
      sig_a(2011);
      sig_a2("Hello!");
   }
};
 
class B : public ssc::trackable
{
public:
   void slot_b(float x) {
       std::cout << "slot_b, x = " << x << std::endl;
   }
 
   void slot_b2(std::string str) {
       std::cout << str << std::endl;
   }
 
};
 
 
int main()
{
   A *a = new A;
   B *b = new B;
 
   connect(a->sig_a, b, &B::slot_b);
   connect(a->sig_a2, b, &B::slot_b2);
 
   a->run();
 
   delete b;
   delete a;
 
   return 0;
}
 

Исходники приаттачены..
1799  Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот : Февраль 26, 2011, 22:46
А нельзя подключать с неполным совпадением прототипа? т.е. signal <int> к void slot (float)?
Хотя чисто теоретически это возможно, но потребуется некий посредник - объект между сигналом и слотом, в котором и будут храниться все соединения. Тогда типы аргументов можно писать какими угодно..
Вот простой пример, демонстрирующий эту идею:
Код
C++ (Qt)
#include <iostream>
#include <string>
#include "signal_slot.h"
 
class A
{
public:
   ssc::signal<int> sig_a;
 
   void run() const {
      sig_a(2011);
   }
};
 
class B : public ssc::trackable
{
public:
   void slot_b(float x) {
       std::cout << "slot_b, x = " << x << std::endl;
   }
 
};
 
class C : public ssc::trackable
{
public:
   C() {}
   ssc::signal<float> sig_c;
   void slot_c(int x) {
       sig_c(x);
   }
};
 
int main()
{
   A *a = new A;
   B *b = new B;
   C *c = new C;   // перенаправляет сигнал
 
   connect(a->sig_a, c, &C::slot_c);
   connect(c->sig_c, b, &B::slot_b);
 
   a->run();
 
   delete b;
   delete a;
   delete c;
 
   return 0;
}
 
Вобщем идея в том, что соединения теперь нужно чтоб хранил отдельный шаблонный класс, который будет жить сам по седе и следить за всеми общающимися через него объектами..

Как то так)
1800  Qt / Кладовая готовых решений / Re: Частный случай механизма сигнал-слот : Февраль 26, 2011, 22:17
А нельзя подключать с неполным совпадением прототипа? т.е. signal <int> к void slot (float)?
Ну вообщето, то что стоит в <> и определяет тип параметра слота..
Однако, можно (но нужно ли?) сделать так, что передавать в сигнал тип, отличный от типа указанного в слоте и уж компилятор сам будет делать преобразование типов. Это делается так:
в класса signal вместо:
Код
C++ (Qt)
template <class T_arg1, class T_arg2 = void>
class signal
{
   ...
 
   void operator() (T_arg1 arg1, T_arg2 arg2) const {
       for (_const_iterator it = _list.begin(); it != _list.end(); it++) {
           if ((*it)->valid())
               (*it)->handle_evant(arg1, arg2);
       }
   }
 

можно заменить на
Код
C++ (Qt)
template <class T_arg1, class T_arg2 = void>
class signal
{
 ...
   template <class U1, class U2>
   void operator() (U1 arg1, U2 arg2) const {
       for (_const_iterator it = _list.begin(); it != _list.end(); it++) {
           if ((*it)->valid())
               (*it)->handle_evant(arg1, arg2);
       }
   }
 
Но я бы не стал так делать..

Короче сейчас с неполным совпадением аргументов не подключить..
А в boostЕ, кстати можно?
Страниц: 1 ... 118 119 [120] 121 122 ... 140

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