Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Каждому классу свой тип исключения! Какие есть подходы? 
V
    Опции темы
Kipter
Дата 24.2.2010, 23:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 114
Регистрация: 2.5.2006

Репутация: нет
Всего: нет



Суть такова....

У каждого класса есть свой набор всевозможных ошибок которые могут происходить в его функциях.
например...

Код

class TCPClient {
public:
    enum SockErrors { ERR_INIT, ERR_CONNECTING, ERR_READING, ERR_WRITING, ERR_DISCONNECTED };

... трататата тело ...
}; 

class HTTPClient {
       enum HttpErrors { NOTFOUND, BADREQUEST, FORBIDDEN, SERVERERROR };

.... трататата тело...
};


Класс-исключение для всех классов вообщем то по коду одинаков и тупо копипастить его для каждого класса было бы наверное глупо.
Однако использовать его для всех классов не приемлемо ибо будут совпадать коды ошибок а в каком классе именно произошло исключение будет неясно.

Код

class XException : public std::exception {
public:
    XException(const char* message, const uInt inErrorCode = NULL);
    virtual ~XException() throw() {};

    virtual const char* what() const throw();
    virtual const uInt errorCode() const throw();

protected:
    uInt    mErrorCode;
    string    mMessage;
};


используется как

Код

throw XException("Ну вот упало потому что ананасы",  ERR_CONNECTING);


тогда я сделал так

Код

#define IMPL_EXCEPTION(newname, parent)                        \
class newname : public parent {                                \
public:                                                    \
    newname(const char* message, const uInt inErrorCode = NULL)    \
    : parent(message, inErrorCode) {};                        \
};                                                                                                   


Код

class TCPClient {
public:
      IMPL_EXCEPTION(except, XException);
      enum SockErrors { ERR_INIT, ERR_CONNECTING, ERR_READING, ERR_WRITING, ERR_DISCONNECTED };

... трататата тело ...
}; 

class HTTPClient {
       IMPL_EXCEPTION(except, XException);
       enum HttpErrors { NOTFOUND, BADREQUEST, FORBIDDEN, SERVERERROR };

.... трататата тело...
};

void main()
{
  HTTPClient client;
  try {
     client.downloadFile("http://toptoptop.top/fox.jpg");
  }
  catch(TCPClient::except &excp)
  {
    ... Исправляем ситуацию по кодам ошибок TCPClient ...
  }
  catch(HTTPClient::except &excp)
  {
    ... Исправляем ситуацию по кодам ошибок HTTPClient ...
  }
}


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

есть идеи?

P.S: 
Не хватает оператора что то вроде typedef но который бы делал не ассоциацию типа а вводил новый тип но только для правил компилятора =)


Это сообщение отредактировал(а) Kipter - 24.2.2010, 23:53
PM MAIL   Вверх
mes
Дата 25.2.2010, 00:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



почитайте про шаблоны (template<>)


--------------------
PM MAIL WWW   Вверх
Kipter
Дата 25.2.2010, 00:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 114
Регистрация: 2.5.2006

Репутация: нет
Всего: нет



Цитата(mes @  25.2.2010,  00:16 Найти цитируемый пост)
почитайте про шаблоны (template<>) 


Хе-хе, про шаблоны знаю.... но не получу ли я ими еще более излишнюю кодогенерацию? 
тогда для каждого класса будет сгенерирован не только излишний конструктор но и функции члены!

получим еще больше лишнего коду ради "удобства"

Да и ктомуже синтаксис красивше не станет! я бы сказал появится даже больше нагромождений.

Преимущество будет только в проверке типов, в макрос то можно всевозможную дряно пихать, но с другой тсороны ошибку получим сразу, взглянем на макрос и все поймем.
PM MAIL   Вверх
Kipter
Дата 25.2.2010, 01:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 114
Регистрация: 2.5.2006

Репутация: нет
Всего: нет



Цитата(mes @  25.2.2010,  00:16 Найти цитируемый пост)
почитайте про шаблоны (template<>) 


Хе-хе, про шаблоны знаю.... но не получу ли я ими еще более излишнюю кодогенерацию? 
тогда для каждого класса будет сгенерирован не только излишний конструктор но и функции члены!

получим еще больше лишнего коду ради "удобства"

Да и ктомуже синтаксис красивше не станет! я бы сказал появится даже больше нагромождений.

Преимущество будет только в проверке типов, в макрос то можно всевозможную дряно пихать, но с другой тсороны ошибку получим сразу, взглянем на макрос и все поймем.

Добавлено через 12 минут и 15 секунд
Вот вариант с использование Специализированных шаблонов о которых говорил mes
ссори за грязное исполнение в одном фаиле и реализацией по месту объявления, просто так быстрее =)

Код

template <typename T>
class XException {};

class XPrivateException : public std::exception {
public:
    XPrivateException(const char* message, const int inErrorCode = NULL) 
        : mErrorCode(inErrorCode), mMessage(message) {};
    virtual ~XPrivateException() throw() {};

    virtual const char* what() const throw() 
        { return mMessage.c_str(); }
    
    virtual const int errorCode() const throw() 
        { return mErrorCode; }

protected:
    int          mErrorCode;
    string    mMessage;
};


class TCPClient;

template<>
class XException<TCPClient> : public XPrivateException {
public:
    XException(const char* message, const int inErrorCode = NULL) 
        : XPrivateException(message, inErrorCode) {};
};

class TCPClient {
public:
    enum SockErrors { ERR_INIT, ERR_CONNECTING, ERR_READING, ERR_WRITING, ERR_DISCONNECTED };
    
    void Start() { throw XException<TCPClient>("TCP", 1); }
}; 


class HTTPClient;

template<>
class XException<HTTPClient> : public XPrivateException {
public:
    XException(const char* message, const int inErrorCode = NULL) : XPrivateException(message, inErrorCode) {};
};

class HTTPClient {
public:
    enum HttpErrors { NOTFOUND, BADREQUEST, FORBIDDEN, SERVERERROR };

    void Start1() { tcp.Start(); }
    void Start2() { throw XException<HTTPClient>("HTTP", 3); }

    TCPClient tcp;
};


void main()
{
    HTTPClient client;
    try {
        client.Start1();
    }
    catch(XException<TCPClient> &excp)
    {
        cout << "XException<TCPClient>" << endl;
        cout << excp.what() << endl;
    }
    catch(XException<HTTPClient> &excp)
    {
        cout << "XException<HTTPClient>" << endl;
        cout << excp.what() << endl;
    }
}


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

В плане кодогенерации получаем тоже самое что и с макросом + код конструктора каждому классу.

Но теперь нам необходимо выкидывать исключения вот так: throw XException<HTTPClient>("HTTP", 3); 
заместо возможного throw XException("HTTP", 3); c макросом.

и писать перед каждым классом 

Код

template<>
class XException<HTTPClient> : public XPrivateException {
public:
    XException(const char* message, const int inErrorCode = NULL) : XPrivateException(message, inErrorCode) {};
};


можно конечно сунуть в макро-определение, но опять таки получим масло масленое, за что боролись на то и напоролись оО
Вообщем пока что такой вариант мне не приглядывается - выигрыша мало, нагромождения есть.
PM MAIL   Вверх
mes
Дата 25.2.2010, 01:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Kipter @  25.2.2010,  00:20 Найти цитируемый пост)
Хе-хе, про шаблоны знаю.... но не получу ли я ими еще более излишнюю кодогенерацию? 
тогда для каждого класса будет сгенерирован не только излишний конструктор но и функции члены!

не больше чем макросом smile 
Цитата(Kipter @  25.2.2010,  00:20 Найти цитируемый пост)
Вот вариант с использование Специализированных шаблонов о которых говорил mes

нет, я говорил о несколько другом варианте, вот набросок :
Код

template <class Code> XException : public XBaseException
{
    XException (const char  *msg, Code code) ...
};

struct TestClass
{
   enum ECode { eTestCode = 100 };
   typedef XEception<ECode> Exception;
 
  void test_except () { throw Exception ("test msg", eTestCode ); }
      
};
...
   TestClass test;
    try {
        test.test_except ();
    }
    catch(TestClass::Exception &excp)
    {
        cout << "TestClass::Exception" << endl;
        cout << excp.what() << endl;
    }


ну а дальше уже делайте вариацию под Ваши цели smile





--------------------
PM MAIL WWW   Вверх
Kipter
Дата 25.2.2010, 02:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 114
Регистрация: 2.5.2006

Репутация: нет
Всего: нет



mes,  smile 

Чорт, действительно, красива.... 

Надо высыпаться то то бредни в голову к вечеру лезут.

Спасибо++
PM MAIL   Вверх
bilbobagginz
Дата 25.2.2010, 23:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Naughtius Maximus
****


Профиль
Группа: Экс. модератор
Сообщений: 8813
Регистрация: 2.3.2004
Где: Israel

Репутация: 3
Всего: 317



mes, а зачем сразу шобло ны ? может лучше просто создать базовый классик. с частично виртуальными методами.
а в сыновьих классах эти виртуалки реализовать в соответствии с требованиями.
я не знаю что выгоднее - шаблоны или наследование ?

UPD: 
сначала я понял будто у каждого из классов будут особенные эксепшены, разных типов - разным количеством данных на выходе, разными what(), и т.п.
а сейчас взглянул на примеры, и получается, что никаких принципиально разных эксепшенов ему тут не надо. 
можно обойтись действительно с шаблонами... довольно читабельно, и ручками писАть меньше.



Это сообщение отредактировал(а) bilbobagginz - 25.2.2010, 23:12


--------------------
Я ещё не демон. Я только учусь.
PM WWW   Вверх
Lazin
Дата 25.2.2010, 23:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 41
Всего: 154



Цитата(Kipter @  24.2.2010,  23:48 Найти цитируемый пост)
тогда я сделал так

а вот зачем интересно
обычно для каждого класса не нужно городить свой класс исключения, все равно в большинстве случаев будешь ловить через std::exception  smile 
PM MAIL Skype GTalk   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0841 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.