Question

Je suis un étudiant dans ma première classe de programmation C ++, et je travaille sur un projet où nous devons créer plusieurs classes d'exception personnalisée, puis dans l'un de nos gestionnaires d'événements, utilisez un bloc try/catch pour les traiter de manière appropriée .

Ma question est: Comment puis-je attraper mes plusieurs exceptions personnalisées dans mon bloc try/catch? GetMessage() est une méthode personnalisée dans mes classes d'exception qui renvoie l'explication d'exception en tant que std::string. Ci-dessous j'ai inclus tout le code correspondant de mon projet.

Merci pour votre aide!

bloc try / catch


    // This is in one of my event handlers, newEnd is a wxTextCtrl
try {
    first.ValidateData();
    newEndT = first.ComputeEndTime();
    *newEnd << newEndT;
}
catch (// don't know what do to here) {
    wxMessageBox(_(e.GetMessage()), 
                 _("Something Went Wrong!"),
                 wxOK | wxICON_INFORMATION, this);;
}

ValidateData () Méthode


void Time::ValidateData()
{
    int startHours, startMins, endHours, endMins;

    startHours = startTime / MINUTES_TO_HOURS;
    startMins = startTime % MINUTES_TO_HOURS;
    endHours = endTime / MINUTES_TO_HOURS;
    endMins = endTime % MINUTES_TO_HOURS;

    if (!(startHours <= HOURS_MAX && startHours >= HOURS_MIN))
        throw new HourOutOfRangeException("Beginning Time Hour Out of Range!");
    if (!(endHours <= HOURS_MAX && endHours >= HOURS_MIN))
        throw new HourOutOfRangeException("Ending Time Hour Out of Range!");
    if (!(startMins <= MINUTE_MAX && startMins >= MINUTE_MIN))
        throw new MinuteOutOfRangeException("Starting Time Minute Out of    Range!");
    if (!(endMins <= MINUTE_MAX && endMins >= MINUTE_MIN))
        throw new MinuteOutOfRangeException("Ending Time Minute Out of Range!");
    if(!(timeDifference <= P_MAX && timeDifference >= P_MIN))
        throw new PercentageOutOfRangeException("Percentage Change Out of Range!");
    if (!(startTime < endTime))
        throw new StartEndException("Start Time Cannot Be Less Than End Time!");
}

Juste un de mes cours personnalisés d'exception, les autres ont la même structure que celui-ci


class HourOutOfRangeException
{
public:
        // param constructor
        // initializes message to passed paramater
        // preconditions - param will be a string
        // postconditions - message will be initialized
        // params a string
        // no return type
        HourOutOfRangeException(string pMessage) : message(pMessage) {}
        // GetMessage is getter for var message
        // params none
        // preconditions - none
        // postconditions - none
        // returns string
        string GetMessage() { return message; }
        // destructor
        ~HourOutOfRangeException() {}
private:
        string message;
};
Était-ce utile?

La solution

Si vous avez plusieurs types d'exceptions, et en supposant qu'il ya une hiérarchie des exceptions (et tous dérivés publiquement de certains sous-classe de std::exception,) commencer par le plus spécifique et continuer à plus générale:

try
{
    // throws something
}
catch ( const MostSpecificException& e )
{
    // handle custom exception
}
catch ( const LessSpecificException& e )
{
    // handle custom exception
}
catch ( const std::exception& e )
{
    // standard exceptions
}
catch ( ... )
{
    // everything else
}

D'autre part, si vous êtes intéressé par tout le message d'erreur - throw même exception, disons std::runtime_error avec des messages différents, puis catch que:

try
{
    // code throws some subclass of std::exception
}
catch ( const std::exception& e )
{
    std::cerr << "ERROR: " << e.what() << std::endl;
}

Rappelez-vous aussi - jeter par valeur, prise par référence [const]

.

Autres conseils

Vous devez créer une classe d'exception de base et toutes vos exceptions spécifiques en tirer:

class BaseException { };
class HourOutOfRangeException : public BaseException { };
class MinuteOutOfRangeException : public BaseException { };

Vous pouvez ensuite attraper tous dans un seul bloc catch:

catch (const BaseException& e) { }

Si vous voulez être en mesure d'appeler GetMessage, vous devrez soit:

  • placer cette logique dans BaseException, ou
  • make GetMessage une fonction membre virtuelle dans BaseException et le remplacer dans chacune des classes d'exception dérivés.

Vous pouvez également envisager d'avoir vos exceptions découlent de l'une des exceptions de la bibliothèque standard, comme std::runtime_error et utiliser la fonction de membre de idiomatiques what() au lieu de GetMessage().

Derive toutes vos exceptions d'une BaseException de classe de base commune qui a une GetMessage() méthode virtuelle.

Alors catch(const BaseException& e).

J'ai eu aujourd'hui le même problème, mais il est avéré que je ne l'ai pas besoin de ma solution pour résoudre mon problème. Honnêtement, je ne pouvais pas penser à des cas d'utilisation (exploitation forestière?), Et je ne trouve pas beaucoup d'utilisation pour dans mon code.

Quoi qu'il en soit, c'est une approche avec des listes de type (nécessite 11 C ++). Je pense que l'avantage de cette approche est qu'il n'y a pas besoin d'avoir une classe de base commune pour les exceptions personnalisées (sauf pour std :: exception, peut-être?). En d'autres termes, il n'est pas intrusif à votre hiérarchie d'exception.

Il pourrait y avoir des erreurs subtiles que je ne suis pas au courant.

#include <type_traits>
#include <exception>

/// Helper class to handle multiple specific exception types
/// in cases when inheritance based approach would catch exceptions
/// that are not meant to be caught.
///
/// If the body of exception handling code is the same
/// for several exceptions,
/// these exceptions can be joined into one catch.
///
/// Only message data of the caught exception is provided.
///
/// @tparam T  Exception types.
/// @tparam Ts  At least one more exception type is required.
template <class T, class... Ts>
class MultiCatch;

/// Terminal case that holds the message.
/// ``void`` needs to be given as terminal explicitly.
template <>
class MultiCatch<void> {
 protected:
  explicit MultiCatch(const char* err_msg) : msg(err_msg) {}
  const char* msg;
};

template <class T, class... Ts>
class MultiCatch : public MultiCatch<Ts...> {
  static_assert(std::is_base_of<std::exception, T>::value, "Not an exception");

 public:
  using MultiCatch<Ts...>::MultiCatch;

  /// Implicit conversion from the guest exception.
  MultiCatch(const T& error) : MultiCatch<Ts...>(error.what()) {}  // NOLINT

  /// @returns The message of the original exception.
  const char* what() const noexcept {
    return MultiCatch<void>::msg;
  }
};

/// To avoid explicit ``void`` in the type list.
template <class... Ts>
using OneOf = MultiCatch<Ts..., void>;

/// Contrived example.
void foo() {
  try {
    bar();  // May throw three or more sibling or unrelated exceptions.
  } catch (const OneOf<IOError, OutOfMemory>& err) {
    log() << "External failure: " << err.what();

    throw;  // Throw the original exception.
  }
}

Lorsque les modèles ne peuvent pas, les macros sauver la journée. La solution est tirée de Boost . Il se résume à 7 lignes de code.

/// @file multicatch.hpp
#include <boost/preprocessor/variadic/to_list.hpp>
#include <boost/preprocessor/list/for_each.hpp>

/// Callers must define CATCH_BODY(err) to handle the error,
/// they can redefine the CATCH itself, but it is not as convenient. 
#define CATCH(R, _, T) \
  catch (T & err) {    \
    CATCH_BODY(err)    \
  }
/// Generates catches for multiple exception types
/// with the same error handling body.
#define MULTICATCH(...) \
  BOOST_PP_LIST_FOR_EACH(CATCH, _, BOOST_PP_VARIADIC_TO_LIST(__VA_ARGS__))
// end of file multicatch.hpp

/// @file app.cc
#include "multicatch.hpp"

// Contrived example.
/// Supply the error handling logic.
#define CATCH_BODY(err)                        \
  log() << "External failure: " << err.what(); \
  throw;

void foo() {
  try {
    bar();  // May throw three or more sibling or unrelated exceptions.
  }
  MULTICATCH(IOError, OutOfMemory)
}

#undef CATCH_BODY

Je rencontre le même problème et voici ce que j'ai fini avec:

  std::shared_ptr<MappedImage> MappedImage::get(const std::string & image_dir,
                                                const std::string & name,
                                                const Packet::Checksum & checksum) {
    try {
      return std::shared_ptr<MappedImage>(images_.at(checksum));
    } catch (std::out_of_range) {
    } catch (std::bad_weak_ptr) {
    }
    std::shared_ptr<MappedImage> img =
      std::make_shared<MappedImage>(image_dir, name, checksum);
    images_[checksum_] = img;
    return img;
  }

Dans mon cas, la fonction retourne quand il ne reçoit pas une exception. Donc, je n'ai pas vraiment faire quoi que ce soit à l'intérieur de la pêche, mais peut faire le travail en dehors de la tentative.

#include <iostream> void test(int x)` { try{ if(x==1) throw (1); else if(x==2) throw (2.0); } catch(int a) { cout<<"It's Integer"; } catch(double b) { cout<<"it's Double"; } } int main(){ cout<<" x=1"; test(1); cout<<"X=2"; test(2.0); return 0; }`
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top