Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Класс исключения


Автор: CppDevelopeR 12.10.2008, 17:08
Написал простенький класс исключения. Вроде написан правильно, но хотелось бы послушать советов более опытных программеров, что оптимизировать можно, что подкорректировать. Вот код:
Код

#include<iostream>
#include<string>

using namespace std;

class Exception{

public:
     Exception(const string& msg) : msg_(msg) {}
     Exception( ) {}
     
     string getMessage( ) const {return(msg_);}
private:
     string msg_;
};

void f( ) {
     throw(Exception("Mr. Sulu"));
}

int main( ){
     try {
         f( );
}
catch(Exception& e){
       cout << "You threw an exception: " << e.getMessage() << endl; 
      }
}

Автор: Cycle 13.10.2008, 09:21
Если функциональность класса больше не будет развиваться, может проще использовать просто string? А вообще выбрасывание исключения типа string не для чего более, чем для вывода на экран не годится.

Попробуй следующий код:
Код

class BaseException{
public:
     virtual char* getMessage( ) const {return "Unknown exception";}
};

class FirstTypeException: BaseException{
public:
     Exception(int data) : m_data(data) {}

     virtual char* getMessage( ) const {return "FirstTypeException";}
     int getData( ) const {return m_data;}
private:
     int m_data;
};

class SecondTypeException: BaseException{
public:
     Exception(double  data) : m_data(data) {}

     virtual char* getMessage( ) const {return "SecondTypeException";}
     double getData( ) const {return m_data;}
private:
     double m_data;
};


Автор: Lycifer 13.10.2008, 09:59
Если мнение то это просто : 
 - Класс исключения обязан быт ьнаследникуом от exception из std;
 - Иметь виртуальный деструктор
 - Виртуальную функцию которая возврощает сообщения исключения

Это всё пиши есчё)

Автор: Mayk 13.10.2008, 10:24
Цитата(Lycifer @  13.10.2008,  13:59 Найти цитируемый пост)
Если мнение то это просто : 
 - Класс исключения обязан быт ьнаследникуом от exception из std;
 - Иметь виртуальный деструктор
 - Виртуальную функцию которая возврощает сообщения исключения

Это всё пиши есчё) 

Правла если всё это сделать с классом в начале сообщения, то получится близнец std::logic_error *crazy*.
другой вопрос зачем вообще городить близнеца logic_error'а?

Автор: Alek86 13.10.2008, 10:32
Цитата(Lycifer @  13.10.2008,  09:59 Найти цитируемый пост)
Класс исключения обязан быт ьнаследникуом от exception из std;

с чего бы это?
обоснуй

Цитата(Lycifer @  13.10.2008,  09:59 Найти цитируемый пост)
Иметь виртуальный деструктор

у std::exception это условие не соблюдается
в стандарте ошибка?

Автор: Lazin 13.10.2008, 10:49
а чем std::exception не устраивает, а так-же std::runtime_error, std::logic_error итд...
в своих программах я обычно использую 2 типа исключений, 1-й - после которого объект, метод которого бросил исключение можно использовать, он не потерял целостность, 2-й, после которого объект нельзя использовать.. в результате получается что-то вроде

Код

try
{
    object_collection[key]->do_something();
}
catch( const repairable_error& e )
{
    //метод объекта бросил исключение, но сам объект содержит "правильные" данные
    std::cerr << e.what() << std::endl;
}
catch( const fatal_error& e)
{
    object_collection.remove(key);//объект в невалидном состоянии больше использовать нельзя
    std::cerr << e.what() << std::endl;
}

Автор: Mayk 13.10.2008, 10:56
Цитата(Alek86 @  13.10.2008,  14:32 Найти цитируемый пост)

с чего бы это?
обоснуй

чтобы можно было сделать
Код

catch(std::exception& ex){ 
 messageBox(string("Мы старались но облажались: ") + ex.what() + " обратитесь к разработчику");
 return;
}

можно конечно сделать
Код

catch(std::exception& ex){ 
 messageBox(string("Мы старались но облажались: ") + ex.what() + " обратитесь к разработчику");
 return;
}
catch(IDoNotRespectStandard& ex){ 
 messageBox(string("Мы старались но облажались: ") + ex.what() + " обратитесь к разработчику");
 return;
}
catch(IDoNotRespectStandardVery& ex){ 
 messageBox(string("Мы старались но облажались: ") + ex.what() + " обратитесь к разработчику");
 return;
}
catch(IDoNotRespectStandardVeryMuch& ex){ 
 messageBox(string("Мы старались но облажались: ") + ex.what() + " обратитесь к разработчику");
 return;
}

правда не ясно нафига. Дай угадаю. наверное чтобы

Код

try{
vector.at(idx); 
}
catch(IDoNotRespectStandardVeryMuch& ex){ 
 messageBox(string("Мы старались но облажались: ") + ex.what() + " обратитесь к разработчику");
 return;
}

валилась terminate()'ом из-за необработанного исключения


Цитата(Alek86 @  13.10.2008,  14:32 Найти цитируемый пост)

у std::exception это условие не соблюдается
в стандарте ошибка?

Под рукой стандарта нет. Но в <exception>'е mingw'а деструктор виртуален. Ы?

Добавлено @ 11:01
апачевский stdcxx и rougewave excption юзают виртуальный деструктор
http://stdcxx.apache.org/doc/stdlibref/exception.html#idx630
http://www2.roguewave.com/support/docs/sourcepro/edition9-update1/html/stdlibref/exception.html
(кстати их справки схожи - но разбиратсья кто от кого отпочковался лень)

так что если в стд не сказано про вирт деструктор - да, там ошибка. бывает

Автор: Alek86 13.10.2008, 11:16
Цитата(Mayk @  13.10.2008,  10:56 Найти цитируемый пост)
Под рукой стандарта нет. Но в <exception>'е mingw'а деструктор виртуален. Ы?

возможно и я проглючил
хотя чето упоминания про вирт деструтор в стардарте не вижу

свою иерархию, конечно, лучше сделать, но с чего вдруг наследоваться именно от std::exception? 

Автор: J0ker 13.10.2008, 21:25
Цитата(Alek86 @  13.10.2008,  11:16 Найти цитируемый пост)
хотя чето упоминания про вирт деструтор в стардарте не вижу

Виртуальность наследуема. У переопределенных методов необязательно указывать virtual - но желательно для удобства последующего наследования

Автор: UnrealMan 13.10.2008, 22:13
Цитата(CppDevelopeR @ 12.10.2008,  18:08)
Написал простенький класс исключения. Вроде написан правильно, но хотелось бы послушать советов более опытных программеров, что оптимизировать можно, что подкорректировать. Вот код:
Код

#include<iostream>
#include<string>

using namespace std;

class Exception{

public:
     Exception(const string& msg) : msg_(msg) {}
     Exception( ) {}
     
     string getMessage( ) const {return(msg_);}
private:
     string msg_;
};

void f( ) {
     throw(Exception("Mr. Sulu"));
}

int main( ){
     try {
         f( );
}
catch(Exception& e){
       cout << "You threw an exception: " << e.getMessage() << endl; 
      }
}

Ну, даже не знаю, как тебе и сказать... Короче... в общем... твой класс не безопасен по отношению к исключениям smile smile 
(Hint: в течение раскрутки стека объект исключения может копироваться)

Автор: J0ker 13.10.2008, 22:49
Цитата(UnrealMan @  13.10.2008,  22:13 Найти цитируемый пост)
Короче... в общем... твой класс не безопасен по отношению к исключениям

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

Автор: UnrealMan 13.10.2008, 22:58
Цитата(J0ker @  13.10.2008,  23:49 Найти цитируемый пост)
нужно ли избегать в обработчиках ошибок

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

Автор: Alek86 13.10.2008, 23:10
Цитата(J0ker @  13.10.2008,  22:49 Найти цитируемый пост)
нужно ли избегать в обработчиках ошибок использовать всякие сложные объекты которые могут сами вызывать исключения?

стараться нужно
но если прога часто использует RAII, то избежать не выйдет

Автор: J0ker 13.10.2008, 23:11
Цитата(UnrealMan @ 13.10.2008,  22:58)
Цитата(J0ker @  13.10.2008,  23:49 Найти цитируемый пост)
нужно ли избегать в обработчиках ошибок

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

ну меня тот-же string в объекте исключения интересует
при копировании (как и при создании) будет аллокация которая сама может вызвать исключение
так вот вопрос собственно из этого

Автор: UnrealMan 13.10.2008, 23:18
Цитата(J0ker @  14.10.2008,  00:11 Найти цитируемый пост)
при копировании (как и при создании) будет аллокация которая сама может вызвать исключение

Если исключение произойдёт при копировании, то будет terminate:

Цитата(15 Exception handling)
In the following situations exception handling must be abandoned for less subtle error handling techniques:
— when the exception handling mechanism, after completing evaluation of the expression to be thrown but
before the exception is caught (15.1), calls a user function that exits via an uncaught exception,134
............
In such cases,
void terminate();
is called

134) For example, if the object being thrown is of a class with a copy constructor, terminate() will be called if that copy constructor
exits with an exception during a throw.

Автор: J0ker 13.10.2008, 23:38
Цитата(UnrealMan @  13.10.2008,  23:18 Найти цитируемый пост)
Если исключение произойдёт при копировании, то будет terminate:

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

Автор: UnrealMan 13.10.2008, 23:52
Цитата(J0ker @  14.10.2008,  00:38 Найти цитируемый пост)
все-таки terminate там где ожидалась обработка и, возможно, восстановление от ошибки как-бы не очень кошерно 

Ну, как бы следует делать копирующий конструктор бессбойным. Для этого достаточно, к примеру, заменить std::string на boost::shared_ptr<std::string>.

Автор: Mayk 14.10.2008, 05:54
Цитата(J0ker @  14.10.2008,  03:11 Найти цитируемый пост)
будет аллокация которая сама может вызвать исключение
так вот вопрос собственно из этого 

При стандартном аллакотаре можно считать что исключений в выделений памяти  не бывает(см Саттера) 

Автор: J0ker 14.10.2008, 06:33
Цитата(Mayk @ 14.10.2008,  05:54)
Цитата(J0ker @  14.10.2008,  03:11 Найти цитируемый пост)
будет аллокация которая сама может вызвать исключение
так вот вопрос собственно из этого 

При стандартном аллакотаре можно считать что исключений в выделений памяти  не бывает(см Саттера)

что-то мне мое внутреннее чутье подсказывает что все-таки бывает
можно либо точно указать где смотреть либо пересказать своими словами?

Автор: Lazin 14.10.2008, 07:36
Цитата(Mayk @  14.10.2008,  05:54 Найти цитируемый пост)
При стандартном аллакотаре можно считать что исключений в выделений памяти  не бывает(см Саттера)

да можно тупо отнаследовать от std::exception и все

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)