non volevo andare con l'approccio oggetto non valido in generale, perché vorrei considerare questo come cattivo design. Dopo la costruzione, l'oggetto deve trovarsi in uno stato in cui sono stabiliti gli invarianti (che è l'unico scopo che un costruttore deve servire). Considerare una classe strange_vector
che implementa qualcosa come std::vector
, ma dopo aver chiamato strange_vector<int>(10, 0)
, l'oggetto si troverebbe in uno stato inutilizzabile perché l'allocazione non è riuscita.
Invece vorrei dichiarare costruttori privati e utilizzare un metodo factory che restituisce un optional:
class file
{
public:
~file() {fclose(m_file);}
static std::optional<file> open(std::string const& filename)
{
auto f = fopen(filename.c_str(), "r");
if (f)
{
return std::make_optional<file>(f);
}
else
{
return std::nullopt;
}
}
private:
file(FILE* file);
FILE* m_file;
};
Uno dei maggiori vantaggi di gestione delle eccezioni è (oltre disaccoppiamento gestione degli errori e normale percorso di codice) che non si può ignorali accidentalmente. Se lo si desidera, è possibile creare una classe personalizzata simile a optional
che, quando non è inizializzata con un oggetto valido, registra un messaggio di errore e termina il programma (o qualsiasi altra ragionevole gestione degli errori). Penso che ci sia un talk from A. Alexandrescu about systematic error handling dove implementa una classe Expected<T>
che contiene un valore di tipo T
o un'eccezione. Puoi usare questa base e invece di aggiungere il tuo errore di gestione lì.
std::optional
non fa ancora parte dello standard, ma è possibile ottenere facilmente implementazioni come parte di compilatori recenti, in boost o in altre librerie.
Quando non riesco ad utilizzare eccezioni per qualsiasi motivo, finisco per creare metodi di inizializzazione per oggetti che possono fallire nella costruzione. Quindi il costruttore non farebbe altro che una banale installazione. Quindi posso avere un metodo Init che fa l'effettiva acquisizione delle risorse e restituisce vero/falso di conseguenza. –
Le tue linee guida non dicono nulla riguardo a situazioni del genere? Dopo tutto, è * un * linguaggio C++ molto comune. E se le linee guida lo consentono, puoi sempre utilizzare un sistema simile alla [libreria I/O standard] (http://en.cppreference.com/w/cpp/io) e ai suoi flussi, ad es. che i flussi possono essere usati in condizioni per verificare la presenza di errori o come i flussi di file che hanno una funzione 'is_open'. –
@JoachimPileborg Non penso che sia stato considerato nelle linee guida, potrebbero richiedere un aggiornamento (anche se è un sistema embedded in tempo reale, e le eccezioni non sono piaciute!) In ogni caso, la mia sensazione è che non è possibile, quindi solo per Per questa domanda vorrei che il mio sentimento fosse confermato! :-) – Joe