Создание пользовательского исключения в Visual C++ 2019

MFC определяет функции для создания предопределенных исключений. Например, вы используете ::AfxThrowFileException() для создания исключения типа CFileException. Но что, если я определю свой собственный класс исключений, производный от CException? Каков предпочтительный способ бросить его?

Есть ли проблемы, если я просто сделаю это:

if (!m_Settings.IsValid())
    throw new CMyException(_T("This operation failed."));

В Visual Studio 2019 приведенный выше код генерирует следующее предупреждение Intellisense. Но я еще не видел примеров, вызывающих исключение с использованием make_unique.

Warning C26409 Avoid calling new and delete explicitly, use std::make_unique instead (r.11).

Может ли кто-нибудь объяснить это или сослаться на какую-то текущую документацию?

Вы использовали свой собственный «набор правил». У меня были такие предупреждения. Как только я вернулся к «Рекомендуемому набору правил», эти типы предупреждений прекратились.

Andrew Truckle 09.04.2019 22:48

@AndrewTruckle: Поскольку я не знаю, что такое набор правил, я бы сказал нет.

Jonathan Wood 09.04.2019 22:52

Перейдите в настройки вашего проекта, найдите раздел Анализ кода слева. Разверните узел Общий. На них находится настройка для набора правил. У вас установлено значение Собственные рекомендуемые правила Microsoft?

Andrew Truckle 09.04.2019 22:59

Он был установлен в Все правила Майкрософт. Я изменил его на Собственные рекомендуемые правила Microsoft. Это, кажется, удалило предупреждение - спасибо. Но я все еще не уверен, как лучше всего создать пользовательское исключение.

Jonathan Wood 09.04.2019 23:16

Просто бросьте их. Я использовал, например, throw new CChristianLifeMinistryEntryException(strError);.

Andrew Truckle 09.04.2019 23:23

Ну, я пока. Я не уверен, что полностью понимаю причину таких функций, как AtlThrowFileException(). Но я просто выброшу их, пока не найду вескую причину не делать этого.

Jonathan Wood 09.04.2019 23:35

Насколько я понимаю, это генерировать системное исключение, если оно соответствует вашим обстоятельствам. В противном случае бросайте свои. См.: docs.microsoft.com/en-us/cpp/mfc/…

Andrew Truckle 09.04.2019 23:39

Да, но опять же, когда вы создаете предоставленное исключение, рекомендуется использовать функцию ::AfxThrow...(). Мой комментарий заключался в том, что я не был уверен, что полностью понял цель функции, а не просто выдал исключение.

Jonathan Wood 09.04.2019 23:52

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

Andrew Truckle 09.04.2019 23:59
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
9
1 003
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

  • Размещайте объекты-исключения в свободном магазине.
  • Бросайте по указателю.
  • Поймать по указателю.
  • Любое предложение catch, которое обрабатывает исключение, требуется для освобождения ресурсов, связанных с объектом исключения.

Напротив, идиоматический способ обработки исключений C++ следует следующим рекомендациям:

  • Выбрасывать объекты-исключения с автоматической продолжительностью хранения по значению.
  • Ловить по (const) ссылке.
  • Очистка ресурсов выполняется автоматически.

С MFC вы можете использовать любой из вышеперечисленных. MFC предоставляет макросы исключений, которые помогают сделать первый менее подверженным ошибкам, хотя нет строгих требований к использованию какого-либо из них. Фактически, макросы исключений в версии 3.0 перешли к почти исключительно использованию обработки исключений C++ под капотом.

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

throw new CMyException(_T("This operation failed."));

или

THROW( (CException*) new CMyException(_T("This operation failed.")) );

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

Если, с другой стороны, вызывающий код использует обработку исключений C++, нет проблем с выбросом ни по значению, ни по указателю, например.

throw CMyException(_T("This operation failed."));
// or
throw new CMyException(_T("This operation failed."));

и ловить по const ссылке или указателю:

catch( CException const& ) {
    // no cleanup required
}
// or
catch( CException* e ) {
    // manual cleanup still required, unless the exception is re-thrown
    e->Delete();
}

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

В некоторой степени даже разрешено смешивать обработку исключений C++ и макросы исключений MFC (Исключения: использование макросов MFC и исключений C++). Информация предоставлена ​​только для полноты. Не рекомендуется смешивать исключения C++ и макросы исключений MFC, если только для этого нет веской причины, например. при постепенном переходе существующего кода с использования макроса исключений MFC на обработку исключений C++.

Другие вопросы по теме