2015-02-21 12 views
9

Ich kam in den folgenden Code auf VS2008Ausnahmeklasse mit einem char * Konstruktor

if (!CreateProcess(NULL, 
        const_cast<LPWSTR>(ss.str().c_str()), 
        NULL, 
        NULL, 
        FALSE, 
        CREATE_NO_WINDOW|NORMAL_PRIORITY_CLASS, 
        NULL, 
        NULL, 
        &si, 
        &pi)) 
{ 
    throw std::exception("Unable to format Device"); 
} 

Jetzt bin ich um den Code zu mingw gcc Portierung und erhalte ich die Fehler

error: no matching function for call to 'std::exception::exception(const char [23])' 

das Problem Untersuchung I bemerkte, dass Visual Studio eine Dateiausnahme hat, die eine Ausnahmeklasse hat und char * aufnimmt. Einige der Definitionen wie folgt aussehen

__CLR_OR_THIS_CALL exception(); 
    __CLR_OR_THIS_CALL exception(const char *const&); 
    __CLR_OR_THIS_CALL exception(const char *const&, int); 
    __CLR_OR_THIS_CALL exception(const exception&); 
    exception& __CLR_OR_THIS_CALL operator=(const exception&); 
    virtual __CLR_OR_THIS_CALL ~exception(); 
    virtual const char * __CLR_OR_THIS_CALL what() const; 

Meine Frage ist, wie soll ich das Build-Problem auf mingw gcc umgehen? Soll ich eine neue Klasse erstellen, die von std :: runtime_error erbt und diese stattdessen wirft?

+1

'std :: Ausnahme :: Ausnahme (const Char *)' ist kein C++ - Standard, eher eine MS spezifische Implementation http://en.cppreference.com/w/cpp/error/exception/exception –

Antwort

33

Meinung spielt hier eine Rolle. Das Problem ist, dass std::exception keinen Konstruktor hat, der ein Zeichenfolgenargument verwendet; Dies ist eine MSVC-Erweiterung. Ich sehe zwei Möglichkeiten, um darüber zu gehen:

  1. Sie nicht ein String-Argument
  2. passieren nicht std::exception

Der erste Fall ist einfach Verwenden Sie; verwenden Sie einfach

throw std::exception(); 

Der Nachteil ist, dass Sie keine beschreibende Fehlermeldung erhalten. Wenn die Fehlermeldung wichtig ist, ist die direkte Verwendung von std::exception keine Option. In diesem Fall könnten Sie entweder std::logic_error oder std::runtime_error verwenden, die std::exception erben und tun Konstrukteure haben ein String-Argument nehmen, so

throw std::runtime_error("Unable to format Device"); 

vielleicht schon das Problem lösen. catch Klauseln, die die std::exception gefangen haben, fangen auch die std::runtime_error. Es gibt jedoch ein mögliches Problem: catch Klauseln, die std::runtime_error fangen, hätten das std::exception nicht gefangen, aber fangen dieses ein.

Dies scheint ein bisschen ein Eckfall, und es ist durchaus möglich, dass es kein Problem für Sie ist. Wenn jedoch die Möglichkeit besteht, dass es entlang der Aufrufliste eine catch-Klausel gibt, die std::runtime_error abfängt, aber die durch diesen Code ausgelöste Ausnahme nicht abfangen soll, können Sie eine eigene Ausnahmeklasse von std::exception ableiten, die ein Zeichenfolgenargument verwendet. Da die Klasse neu ist, wird sie nicht von vorhandenen Klauseln catch erfasst. Zum Beispiel:

class descriptive_exception : public std::exception { 
public: 
    descriptive_exception(std::string const &message) : msg_(message) { } 
    virtual char const *what() const noexcept { return msg_.c_str(); } 

private: 
    std::string msg_; 
} 

Und dann

throw descriptive_exception("Unable to format Device"); 

Dies ist wohl nicht sehr schön, und es ist unwahrscheinlich, dass es notwendig ist, so dass die wahrscheinlichere Lösung ist std::runtime_error oder std::logic_error (oder eine Klasse zu verwenden, abgeleitet von einem von ihnen).

Ob std::logic_error oder std::runtime_error ist geeigneter ist nicht sehr klar; In diesem Fall würde ich wahrscheinlich mit std::runtime_error gehen, weil der Fehler nicht einmal theoretisch vorhersehbar scheint, aber angesichts std::domain_error und std::future_error von std::logic_error abgeleitet, wäre es nicht völlig fehl am Platz in dieser Hierarchie. Das ist, denke ich, eine Frage der Meinung.

+0

Oh, guter Fang. Das war natürlich ein Tippfehler, jetzt behoben. Vielen Dank. – Wintermute

Verwandte Themen