2015-02-21 12 views
9

mi sono imbattuto il seguente codice in VS2008classe Exception con un char * costruttore

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

Ora sto porting del codice per MinGW gcc e ottengo l'errore

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

Analizzare il problema I ho notato che Visual Studio ha un'eccezione di file che ha una classe di eccezione e accetta char *. Alcune delle definizioni apparire così

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

mia domanda è come dovrei aggirare questo problema generazione su mingw gcc? Dovrei creare una nuova classe che eredita da std :: runtime_error e lanciare quella invece?

+1

'std :: exception :: exception (const char *)' non è uno standard C++, piuttosto un impianto specifico MS http://en.cppreference.com/w/cpp/error/exception/exception –

risposta

33

L'opinione ha un ruolo qui. Il problema è che std::exception non ha un costruttore che accetta un argomento stringa; questa è un'estensione MSVC. Vedo due modi per andare su di esso:

  1. non si passa un argomento stringa
  2. Non utilizzare std::exception

Il primo caso è molto semplice; basta usare

throw std::exception(); 

Lo svantaggio è che non si ottiene un messaggio di errore descrittivo.

Se il messaggio di errore è importante, utilizzare direttamente std::exception non è un'opzione. In questo caso, è possibile utilizzare uno o std::logic_errorstd::runtime_error, che eredita std::exception e hanno costruttori prendono un argomento stringa, quindi

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

potrebbe già risolvere il problema. Le clausole catch che hanno rilevato il numero std::exception cattureranno anche lo std::runtime_error. C'è un potenziale problema, tuttavia: le clausole catch che catturano std::runtime_error non avrebbero catturato lo std::exception ma prenderanno questo.

Questo sembra un caso angusto, ed è del tutto possibile che non sia un problema per voi. Se, tuttavia, esiste una possibilità che lungo lo stack di chiamate ci sia una clausola catch che cattura std::runtime_error ma non rilevi l'eccezione generata da questo codice, è possibile derivare la propria classe di eccezioni da std::exception che accetta un argomento stringa. Poiché la classe è nuova, non verrà intercettata dalle clausole catch esistenti. Per esempio:

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

E poi

throw descriptive_exception("Unable to format Device"); 

Questo è probabilmente non è molto carina, ed è improbabile che sia necessario, per cui la soluzione più probabile è quella di utilizzare std::runtime_error o std::logic_error (o di una classe derivato da uno di loro).

Se sia std::logic_error o std::runtime_error è più appropriato non è molto chiaro; in questo caso probabilmente andrei con std::runtime_error perché l'errore non sembra nemmeno teoricamente prevedibile, ma dato che std::domain_error e std::future_error derivano da std::logic_error, non sarebbe del tutto fuori posto in quella gerarchia. Questa è, penso, una questione di opinione.

+0

Oh, buona pesca. Ovviamente era un errore di battitura/penso, ora risolto. Grazie. – Wintermute

Problemi correlati