Как создать свое исключение c
Перейти к содержимому

Как создать свое исключение c

  • автор:

Как правильно создавать пользовательские исключения в C#

Данная статья предназначена прежде всего для новичков в мире .NET, но может быть полезна также и разработчикам с опытом, которые не до конца разобрались, как правильно строить свои user-defined exceptions с помощью C#.

Пример кода для данной статьи можно скачать здесь.

Создание простого исключения

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

К примеру, есть метод, призванный изменять имя пользователя:

private static void EditUser(string oldUserName, string newUserName)

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

Чтобы проинформировать о возникшей исключительной ситуации можно генерировать стандартное исключение, что не является рекомендуемой практикой:

private static void EditUser(string oldUserNane, string newUserName)

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

Создать свой Exception не сложно – нужно определить public-класс, который будет наследоваться от System.Exception или System.ApplicationException. Хотя это и не является хорошей практикой, кода внутри созданного класса исключения можно не писать вообще:

public class UserNotFoundException : ApplicationException

От чего лучше наследоваться, от System.Exception или от System.ApplicationException?

Каждый из этих типов предназначен для конкретной цели. Тогда как System.Exception является общим классом для всех user-defined exceptions, то System.ApplicationException определяет исключения, возникающие на уровне конкретного приложения.

К примеру, тестовое приложения из данной статьи является отдельной программой, поэтому вполне допустимо наследовать определенный нами exception от System.ApplicationException.

Теперь вместо Exception мы сгенерируем созданный нами UserNotFoundException:

private static void EditUser(string oldUserNane, string newUserName)

В таком случае в качестве сообщения о возникшем исключении будет: «Error in the application.». Что не очень информативно.

  • класс исключения должен наследоваться от Exception/ApplicationException;
  • класс должен быть помечен атрибутом [System.Serializable];
  • класс должен определять стандартный конструктор;
  • класс должен определять конструктор, который устанавливает значение унаследованного свойства Message;
  • класс должен определять конструктор для обработки “внутренних исключений”;
  • класс должен определять конструктор для поддержки сериализации типа.

Немного о предназначении отдельных конструкторов: конструктор для обработки “внутренних исключений” нужен для того, чтобы передать в него exception, послуживший причиной возникновения данного исключения. Подробнее, зачем нужен конcтруктор для поддержки сериализации типа под спойлером «Добавление дополнительных полей, их сериализация и десериализация» ниже.

Дабы избавить программиста от необходимости писать одинаковый код в Visual Studio есть сниппет «Exception», который генерирует класс исключения, соответствующий всем рекомендациям, перечисленным выше.

Итак, после воплощения рекомендаций в жизнь, код нашего исключения должен выглядеть примерно так:

public class UserNotFoundException : ApplicationException < public UserNotFoundException() < >public UserNotFoundException(string message) : base(message) < >public UserNotFoundException(string message, Exception inner) : base(message, inner) < >protected UserNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) < >> 

Теперь при генерации исключения мы можем указать причину его возникновения более подробно:

throw new UserNotFoundException("User \"" + oldUserName + "\" not found in system"); 

Добавление дополнительных полей, их сериализация и десериализация

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

[Serializable] public class UserNotFoundException : ApplicationException < private string _userNotFoundName; public string UserNotFoundName < get < return _userNotFoundName; >set < _userNotFoundName = value; >> public UserNotFoundException() < >public UserNotFoundException(string message) : base(message) < >public UserNotFoundException(string message, Exception inner) : base(message, inner) < >protected UserNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) < >> 

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

Для сериализации поля мы должны переопределить метод GetObjectData, описываемый интерфейсом ISerializable. Метод GetObjectData заполняет объект SerializationInfo данными для сериализации. Именно в SerializationInfo мы должны передать имя нашего поля и информацию, хранящуюся в нем:

public override void GetObjectData(SerializationInfo info, StreamingContext context)

Метод GetObjectData для базового класса нужно вызвать для того, чтобы добавить в SerializationInfo все поля нашего исключения по умолчанию (такие как Message, TargetSite, HelpLink и т.д.).

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

protected UserNotFoundException(SerializationInfo info, StreamingContext context) : base(info, context) < if (info != null) < this._userNotFoundName = info.GetString("UserNotFoundName"); >> 

И последний штрих – добавление в XML-документацию (если вы, конечно, ее используете) нашего метода информации о том, что он может выбросить исключение определенного типа:

Итак, наш user-defined exception готов к применению. Вы можете добавить к нему все что душе угодно: дополнительные поля, описывающие состояние исключения, содержащие дополнительную информацию и т.д.

P.S.: Добавил информацию о том, как сериализовать и десериализовать дополнительные поля класса исключения. Подробности под спойлером «Добавление дополнительных полей, их сериализация и десериализация».

P.P.S: Благодарю за комментарии и здоровую критику. Тем, кто прочитал статью до конца — прочитайте также комментарии, там есть полезная информация.

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

Как написать собственное исключение в отдельном классе и вызывать его при надобности? Заранее спасибо! Можете ли описать что и куда вписывать? Я пока еще новичок и не особо понимаю. Вот само исключение, оно проверяет является ли вектор нулевым (v1 и v2 это векторы, а len1 и len2 их длины):

//exeption try < len1 = v1.Length(); len2 = v2.Length(); if (len1 == 0 || len2 == 0) < throw new Exception("Вектор не может быть нулевым"); >> catch (Exception e)

Отслеживать
задан 19 апр 2016 в 16:29
435 2 2 серебряных знака 13 13 бронзовых знаков
Если вам дан исчерпывающий ответ, отметьте его как верный (галка напротив выбранного ответа).
20 апр 2016 в 7:52

3 ответа 3

Сортировка: Сброс на вариант по умолчанию

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

Далее, чтобы ваше исключение соответствовало общепринятым стандартам, вам нужно иметь как минимум три конструктора: по умолчанию (без параметров), конструктор с сообщением, конструктор с сообщением и оригинальным исключением. Последний теоретически может быть опущен, но являетсмя обязательным, если вы «оборачиваете» какие-то системное исключением своим исключением.

(Для продвинутых: если исключение будет передаваться через границы, то обязательно нужно включить конструктор для сериализации. Подробнее в правиле FxCop’а.)

Кроме того, вы вольны включать в исключение любую дополнительную информацию, которая может помочь коду, обрабатывающему ваше исключение, принять нужное решение.

[Serializable] // опционально public class GoodException : Exception < public GoodException() < // . >public GoodException(string message) : base(message) < // . >public GoodException(string message, Exception innerException) : base (message, innerException) < // . >// опционально protected GoodException(SerializationInfo info, StreamingContext context) : base(info, context) < // логика сериализации >public string AdditionalInfo < get; set; >> 

Как создать свое исключение c

сейчас занимаюсь написанием библиотеки для работы с матрицами
хочу сделать сам, ибо для диплома

так надо генерить и обрабатывать свои специфические исключения
типа, матрицы при перемножении несоответственные

так как конкретно это сделать

заранее очень благодарен

Re: Как написать свой класс исключений?

От: SchweinDeBurg http://zarezky.spb.ru/
Дата: 04.01.03 10:41
Оценка:

Здравствуйте, FireWorm, Вы писали:

FW>subj собственно

FW>так надо генерить и обрабатывать свои специфические исключения
FW>типа, матрицы при перемножении несоответственные

Если юзается STL, то надо рожать от exception, ИМХО. А так — своя рука владыка.

— Искренне ваш, Поросенок Пафнутий ~ ICQ#116846877
In Windows, there’s always a catch… © Paul DiLascia

Re: Как написать свой класс исключений?

От: Vladimir Bezugliy
Дата: 04.01.03 10:43
Оценка:

FW>так надо генерить и обрабатывать свои специфические исключения
FW>типа, матрицы при перемножении несоответственные
FW>так как конкретно это сделать

Исключения — это обычные классы.
Ты, например, можешь создать базовый класс

СDiplomaException

А потом пронаследовать еще несколько классов.
Допустим

CMatrixMismatch : public ССDiplomaException < . >; CMatrixTratata : public ССDiplomaException < . >;

Ну и когда нужно будешь бросать CMatrixMismatch, CMatrixTratata.
При отлавливании исключений будет 2 варианта:
1. Ловишь конкретное исключение(например CMatrixMismatch);
catch(CMatrixMismatch m)
2. Ловишь все твои исключения связанные с матрицами
catch(СDiplomaException ex)

Re[2]: Как написать свой класс исключений?

От: FireWorm
Дата: 04.01.03 10:51
Оценка:

Здравствуйте, Vladimir Bezugliy, Вы писали:

VB> .
VB>Владимир Безуглый.

а что в самих классах писать
что-нить определенное, или что хочу в том смысле, как хочу так и обрабатываю?

Re: Как написать свой класс исключений?

От: Mozhay www.mozhay.chat.ru
Дата: 04.01.03 10:53
Оценка: 5 (2)

Здравствуйте, FireWorm, Вы писали:

FW>так надо генерить и обрабатывать свои специфические исключения
FW>типа, матрицы при перемножении несоответственные

FW>так как конкретно это сделать

В принципе можно просто написать пустые классы.

class MatrixException <>; class IncompatibleMatrices : public MatrixException <>; . 

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

#include #include using namespace std; struct MatrixException < string msg; MatrixException(const string& msg) : msg(msg) <> >; int main() < try < throw MatrixException("Invalid matrix"); > catch (MatrixException& e) < cout '\n'; > return 0; >

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

Re[3]: Как написать свой класс исключений?

От: Vladimir Bezugliy
Дата: 04.01.03 10:59
Оценка: 5 (2)

FW>а что в самих классах писать
FW>что-нить определенное, или что хочу в том смысле, как хочу так и обрабатываю?

Можно вообще ничего не писать.
Но если хочешь — можно какие-то данные добавить.

CMatrixMismatch : public ССDiplomaException < public: long GetSizeFirstMatrix()return nSizeFirstMatrix;> long GetSizeSecondMatrix()return nSizeSecondMatrix;> private: long nSizeFirstMatrix; long nSizeSecondMatrix; >;

Re[3]: Как написать свой класс исключений?

От: Mozhay www.mozhay.chat.ru
Дата: 04.01.03 11:08
Оценка:

Здравствуйте, FireWorm, Вы писали:

FW>а что в самих классах писать
FW>что-нить определенное, или что хочу в том смысле, как хочу так и обрабатываю?

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

Re[2]: Как написать свой класс исключений?

От: WolfHound
Дата: 04.01.03 11:41
Оценка:

Здравствуйте, Vladimir Bezugliy, Вы писали:

СDiplomaException:public std::exeption < public: . virtual ~СDiplomaException()<> >

Так ИМХО правильней.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[3]: Как написать свой класс исключений?

От: Vladimir Bezugliy
Дата: 04.01.03 11:48
Оценка:
СDiplomaException:public std::exeption < public: . virtual ~СDiplomaException()<> >

WH>Так ИМХО правильней.

А разве где-то говорится(например в стандарте), что ВСЕ исключения должны быть производными от std::exeption ?

Re[4]: Как написать свой класс исключений?

От: WolfHound
Дата: 04.01.03 15:55
Оценка:

Здравствуйте, Vladimir Bezugliy, Вы писали:

VB>А разве где-то говорится(например в стандарте), что ВСЕ исключения должны быть производными от std::exeption ?

Вроде нет но практика показывает что лучше наследовать.

Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: Как написать свой класс исключений?

От: Кодт
Дата: 07.01.03 11:28
Оценка:

Здравствуйте, WolfHound, Вы писали:

VB>>А разве где-то говорится(например в стандарте), что ВСЕ исключения должны быть производными от std::exeption ?

WH>Вроде нет но практика показывает что лучше наследовать.

В отличие от языков, где исключения входят в состав рантайма (т.е. Дельфи, Явка. ), на С++ можно кидать исключения ЛЮБОГО ТИПА.

try < . vec.setsize(12345678); . . hr = pObject->DoIt(); if(FAILED(hr)) throw hr; . . x = 0; y = 1/x; . . std::vectorlong> vec; vec.setsize(12345678); . . CString s; s.GetBuffer(12345678); . . throw "hello"; . > catch(std::exception ex) // поймает ошибку выделения памяти в векторе < >catch(int x) // поймает HRESULT < >catch(CException* ex) // поймает исключение MFC < >catch(const char* str) // поймает строку < >catch(. ) // поймает все остальное 

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

Но, конечно, бардак разводить в своей программе не стоит, поэтому используй или MFC, или STL.
Дело в том, что в противном случае можно случайно открутить стек на невиданную высоту.

int main_thread_startup() // из недр восстав. < . try < . retcode = main(argc, argv); >catch(. ) // последний предел для всех исключений < retcode = -1; >. > ///////// void something() < throw 123; // вот пуля просвистела и ага > void somewhere() < try < something(); >catch(std::exception ex) // ему я руку протянул: std::exception < // он руку не берет: int > >

Перекуём баги на фичи!
Re[2]: Как написать свой класс исключений?

От: Jack http://tr.dn.ua/~dionis/
Дата: 08.01.03 13:52
Оценка:

Здравствуйте, Mozhay, Вы писали:

M>

M>#include M>#include M>using namespace std; M>struct MatrixException M> < M>string msg; M> MatrixException(const string& msg) : M> msg(msg) M> <> M>>; M>int main() M> < M>try M> < M>throw MatrixException("Invalid matrix"); M> > M> catch (MatrixException& e) M> < M>cout '\n'; M> > M> return 0; M>> M>

Но ведь, по идее, так делать нельзя! MatrixException создается в стке в блоек try и удаляется до вызова catch, т.е. объекта уже не существует(срабатывает диструктор). Если бы в классе был указатель на строку и он бы удалялся в дисртукторе, то в катче мы бы уже ничего не увидели!
У себя я использовал следующую конструкцию(ничего лучшего я просто не придумал)

 try < throw new MatrixException("Invalid matrix"); > catch (MatrixException* e) < cout msg '\n'; delete e;//точнее e->Destroy(); >

Искренне Ваш, Джек.
Re[3]: Как написать свой класс исключений?

От: Можаев Михаил www.mozhay.chat.ru
Дата: 08.01.03 14:09
Оценка:

Здравствуйте, Jack, Вы писали:

J>Здравствуйте, Mozhay, Вы писали:

M>>

M>>#include M>>#include M>>using namespace std; M>>struct MatrixException M>>< M>> string msg; M>> MatrixException(const string& msg) : M>> msg(msg) M>> <> M>>>; M>>int main() M>>< M>> try M>> < M>> throw MatrixException("Invalid matrix"); M>> > M>> catch (MatrixException& e) M>> < M>> cout '\n'; M>> > M>> return 0; M>>> M>>

J>Но ведь, по идее, так делать нельзя! MatrixException создается в стке в блоек try и удаляется до вызова catch, т.е. объекта уже не существует(срабатывает диструктор). Если бы в классе был указатель на строку и он бы удалялся в дисртукторе, то в катче мы бы уже ничего не увидели!

Throwing and catching an exception object both use copy initialization.

При этом, чтобы избежать лишнего (второго) копирования исключение передается по ссылке.

По этой же причине в классе исключения нужно определять copy-constructor, если недостаточно того, что по умолчанию.

Поправьте меня, если что не так.

Re[3]: Как написать свой класс исключений?

От: Дмитрий Наумов
Дата: 08.01.03 14:10
Оценка:

Здравствуйте, Jack, Вы писали:

J>Здравствуйте, Mozhay, Вы писали:

M>>

M>>#include M>>#include M>>using namespace std; M>>struct MatrixException M>>< M>> string msg; M>> MatrixException(const string& msg) : M>> msg(msg) M>> <> M>>>; M>>int main() M>>< M>> try M>> < M>> throw MatrixException("Invalid matrix"); M>> > M>> catch (MatrixException& e) M>> < M>> cout '\n'; M>> > M>> return 0; M>>> M>>

J>Но ведь, по идее, так делать нельзя! MatrixException создается в стке в блоек try и удаляется до вызова catch, т.е. объекта уже не существует(срабатывает диструктор). Если бы в классе был указатель на строку и он бы удалялся в дисртукторе, то в катче мы бы уже ничего не увидели!
J>У себя я использовал следующую конструкцию(ничего лучшего я просто не придумал)
J>

J> try J> < J>throw new MatrixException("Invalid matrix"); J> > J> catch (MatrixException* e) J> < J>cout msg '\n'; J> delete e;//точнее e->Destroy(); J> > J>

То что ты написал («бросание» и ловля исключений через указатель, имеет преимущества, и тут все правильно), но конкретно про деструктурирование исключения и тд обратимся к Мейерсу —
that’s why C++ specifies that an object thrown as an exception is always copied.
Таким образом, если вдруг, по какой то причине ты все же решил бросать исключение по значению, все будет в порядке.

Re[4]: Как написать свой класс исключений?

От: Можаев Михаил www.mozhay.chat.ru
Дата: 08.01.03 14:33
Оценка:

Здравствуйте, Можаев Михаил, Вы писали:

ММ>Цитата из Guru Of The Week #36:
ММ>

Throwing and catching an exception object both use copy initialization.

Вот еще кое-что из Стандарта:

8.5 Initializers, clause 12

The initialization that occurs in argument passing, function return, throwing an exception (15.1), handling
an exception (15.3), and brace-enclosed initializer lists (8.5.1) is called copy-initialization and is equivalent
to the form

T x = a;

12.2 Temporary objects, clause 1

Temporaries of class type are created in various contexts: binding an rvalue to a reference (8.5.3), returning
an rvalue (6.6.3), a conversion that creates an rvalue (4.1, 5.2.9, 5.2.11, 5.4), throwing an exception (15.1),
entering a handler (15.3), and in some initializations (8.5). [Note: the lifetime of exception objects is
described in 15.1. ]

И самое главное:
15.1 Throwing an exception, clauses 3,4,5

A throw-expression initializes a temporary object, the type of which is determined by
. skipped .
The temporary is used to initialize the variable named in the matching handler (15.3)
. skipped .
Except for these restrictions and the restrictions on type matching mentioned in 15.3, the operand of throw is treated exactly as a function argument in a call (5.2.2) or the operand of a return statement.

The memory for the temporary copy of the exception being thrown is allocated in an unspecified way, except as noted in 3.7.3.1. The temporary persists as long as there is a handler being executed for that exception. In particular, if a handler exits by executing a throw; statement, that passes control to another handler for the same exception, so the temporary remains. When the last handler being executed for the exception exits by any means other than throw; the temporary object is destroyed and the implementation may deallocate the memory for the temporary object; any such deallocation is done in an unspecified way. The destruction occurs immediately after the destruction of the object declared in the exception-declaration in the handler.

If the use of the temporary object can be eliminated without changing the meaning of the program except for the execution of constructors and destructors associated with the use of the temporary object (12.2), then the exception in the handler can be initialized directly with the argument of the throw expression. When the thrown object is a class object, and the copy constructor used to initialize the temporary copy is not accessible, the program is ill-formed (even when the temporary object could otherwise be eliminated). Similarly, if the destructor for that object is not accessible, the program is ill-formed (even when the temporary
object could otherwise be eliminated).

Re[4]: Как написать свой класс исключений?

От: Jack http://tr.dn.ua/~dionis/
Дата: 09.01.03 09:04
Оценка:

Здравствуйте, Можаев Михаил, Вы писали:

ММ>Здравствуйте, Jack, Вы писали:

J>>Здравствуйте, Mozhay, Вы писали:

M>>>

M>>>#include M>>>#include M>>>using namespace std; M>>>struct MatrixException M>>>< M>>> string msg; M>>> MatrixException(const string& msg) : M>>> msg(msg) M>>> <> M>>>>; M>>>int main() M>>>< M>>> try M>>> < M>>> throw MatrixException("Invalid matrix"); M>>> > M>>> catch (MatrixException& e) M>>> < M>>> cout '\n'; M>>> > M>>> return 0; M>>>> M>>>

J>>Но ведь, по идее, так делать нельзя! MatrixException создается в стке в блоек try и удаляется до вызова catch, т.е. объекта уже не существует(срабатывает диструктор). Если бы в классе был указатель на строку и он бы удалялся в дисртукторе, то в катче мы бы уже ничего не увидели!

ММ>Цитата из Guru Of The Week #36:
ММ>

Throwing and catching an exception object both use copy initialization.

ММ>При этом, чтобы избежать лишнего (второго) копирования исключение передается по ссылке.
ММ>По этой же причине в классе исключения нужно определять copy-constructor, если недостаточно того, что по умолчанию.
ММ>Поправьте меня, если что не так.
Если исключение передовать по значению, то все правильно. Но ведь в вышеприведенном прримере передача происходит по сылке. Объект MatrixException удаялется в блоке try, но в блоке catch он не создается и никакой котруктор копаирования здесь не поможет. Опять же, иногда это работает, если класс MatrixException достаточно прост. Но если внутри него что-то создаеься в куче, а затем в диструкторе удаляется, то, могут возникнуть проблемы.

Искренне Ваш, Джек.
Re[5]: Как написать свой класс исключений?

От: Михаил Можаев www.mozhay.chat.ru
Дата: 09.01.03 09:27
Оценка:

Здравствуйте, Jack, Вы писали:

J>Здравствуйте, Можаев Михаил, Вы писали:

J> Если исключение передовать по значению, то все правильно. Но ведь в вышеприведенном прримере передача происходит по сылке. Объект MatrixException удаялется в блоке try, но в блоке catch он не создается и никакой котруктор копаирования здесь не поможет. Опять же, иногда это работает, если класс MatrixException достаточно прост. Но если внутри него что-то создаеься в куче, а затем в диструкторе удаляется, то, могут возникнуть проблемы.

Автор: Можаев Михаил
Дата: 08.01.03

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

Re[5]: Как написать свой класс исключений?

От: __Nicolay
Дата: 09.01.03 17:59
Оценка:

Здравствуйте, Jack, Вы писали:

J> Если исключение передовать по значению, то все правильно. Но ведь в вышеприведенном прримере передача происходит по сылке. Объект MatrixException удаялется в блоке try, но в блоке catch он не создается и никакой котруктор копаирования здесь не поможет. Опять же, иногда это работает, если класс MatrixException достаточно прост. Но если внутри него что-то создаеься в куче, а затем в диструкторе удаляется, то, могут возникнуть проблемы.

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

Как создать класс-исключение?

Написать шаблонный класс согласно варианту. Описать класс-исключение или иерархию классов-исключений. Генерировать исключения в соответствующих исключительных ситуациях.

Задание: очередь из максимальных элементов типа T.
Параметры шаблона: int T, class T.
Исключения: переполнение очереди. Изъятие элемента из пустой очереди.

Как написать шаблонный класс — это понятно. Но как создать класс-исключение?

Вот мой набросок, который не работает.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
template class T, int N> class Queue { private: T *que; int size, i; public: Queue() { que = new T[N]; size = N; i = 0; }; void push(T a) { try { if (i>=N) { throw "Невозможно добавить элемент. Очередь заполнена.\n"; } que[i] = a; cout  <"Элемент "   <" успешно добавлен в стек под номером "   ; i++; } catch(string str){ cout   ; } } void pop() { try { if (i == -1) { throw "Невозможно изъять элемент. Стек пуст.\n" } que.pop_back(); i--; cout  <"Элемент "  [i]  <" успешно изъят из стека\n"; } catch (string *str) { cout   ; } }

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *