Frage

Ich bin ein Student in meinem ersten C ++ Programmierung Klasse, und ich arbeite an einem Projekt, wo wir mehr benutzerdefinierten Exception-Klassen erstellen müssen, und dann in einem unseren Event-Handler, verwenden Sie einen try/catch Block sie angemessen zu handhaben .

Meine Frage ist: Wie kann ich ein mehr benutzerdefinierte Ausnahmen in meinem try/catch Block fangen? GetMessage() ist eine benutzerdefinierte Methode in meiner Ausnahmeklassen, die die Ausnahme Erklärung als std::string zurückgibt. Unten habe ich alle relevanten Code aus meinem Projekt enthalten.

Vielen Dank für Ihre Hilfe!

try / catch-Block


    // 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 () Methode


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!");
}

Nur eine meiner benutzerdefinierten Ausnahmeklassen, die anderen haben die gleiche Struktur wie diese


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;
};
War es hilfreich?

Lösung

Wenn Sie mehrere Ausnahmetypen haben, und unter der Annahme, es gibt eine Hierarchie von Ausnahmen (und alle öffentlich von einer Unterklasse von std::exception abgeleitet) startet aus den speziellsten und weiterhin allgemeinen:

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
}

Auf der anderen Seite, wenn Sie gerade in der Fehlermeldung interessiert sind - throw gleiche Ausnahme, sagt std::runtime_error mit verschiedenen Nachrichten, und dann catch dass:

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

Auch nicht vergessen, -. Wurf von Wert, Fang durch [const] Referenz

Andere Tipps

Sie sollten eine Basisausnahmeklasse erstellen und haben alle Ihre spezifischen Ausnahmen leiten daraus:

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

Sie können dann alle in einem einzigen catch-Block fangen:

catch (const BaseException& e) { }

Wenn Sie Anruf GetMessage der Lage sein wollen, werden Sie entweder müssen:

  • Stelle, dass die Logik in BaseException oder
  • make GetMessage eine virtuelle Member-Funktion in BaseException und außer Kraft setzt es in jedem der abgeleiteten Ausnahmeklassen.

Sie auch interessieren könnten, die Ihre Ausnahmen von einem der Standardbibliothek Ausnahmen ableiten, wie std::runtime_error und verwenden Sie die idiomatische what() Memberfunktion statt GetMessage().

Leite alle Ihre Ausnahmen von einer gemeinsamen Basisklasse BaseException, die eine virtuelle Methode GetMessage() hat.

Dann catch(const BaseException& e).

Ich hatte ein ähnliches Problem heute, aber es stellte sich heraus, dass ich nicht brauchte meine Lösung mein Problem zu lösen. Ehrlich gesagt, ich konnte nicht denken von realen Anwendungsfällen (Logging?), Und ich habe nicht viel Verwendung für sie in meinem Code finden.

Wie auch immer, dies ist ein Ansatz mit Typ-Listen (erfordert C ++ 11). Ich denke, der Vorteil dieses Ansatzes ist, dass es keine Notwendigkeit, eine gemeinsame Basisklasse für benutzerdefinierte Ausnahmen haben (mit Ausnahme von std :: exception, vielleicht?). Mit anderen Worten, ist es zu einem Ausnahme-Hierarchie nicht aufdringlich.

Es könnte einige subtile Fehler sein, dass ich bin mir nicht bewusst.

#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.
  }
}

Wenn Vorlagen können nicht, Makros speichern den Tag. Die Lösung wird genommen von Boost-. Es läuft darauf hinaus, 7 Zeilen 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

Ich laufe in das gleiche Problem und hier ist das, was ich am Ende mit:

  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;
  }

In meinem Fall die Funktion zurückkehrt, wenn es keine Ausnahme erhalten. Also ich muß etwas in dem Fang nicht wirklich tun, aber die Arbeit außerhalb des try tun kann.

#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; }`
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top