Ich würde nicht mit dem ungültigen Objekt Ansatz im Allgemeinen gehen, weil ich dies als schlechtes Designs in Betracht ziehen würde. Nach der Konstruktion muss das Objekt in einem Zustand sein, in dem die Invarianten eingerichtet sind (das ist der einzige Zweck, den ein Konstruktor bedienen sollte). Betrachten Sie eine Klasse strange_vector
, die etwas wie std::vector
implementiert, aber nach dem Aufruf von strange_vector<int>(10, 0)
wäre das Objekt in einem unbrauchbaren Zustand, weil die Zuweisung fehlgeschlagen ist.
Stattdessen würde ich die Konstrukteursprivat erklären und eine Factory-Methode verwenden, die eine optionale zurückgibt:
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;
};
Einer der größten Vorteile der Ausnahmebehandlung ist (neben Entkopplung der Fehlerbehandlung und normalen Codepfad), dass man nicht ignoriere sie versehentlich. Wenn Sie das möchten, könnten Sie Ihre eigene Klasse ähnlich optional
erstellen, die, wenn sie nicht mit einem gültigen Objekt initialisiert wird, eine Fehlermeldung protokolliert und Ihr Programm (oder jede andere angemessene Fehlerbehandlung) beendet. Ich denke, es gibt eine talk from A. Alexandrescu about systematic error handling, wo er eine Klasse Expected<T>
implementiert, die entweder einen Wert des Typs T
oder eine Ausnahme enthält. Sie können dies als Basis verwenden und statt der Ausnahme fügen Sie dort Ihre Fehlerbehandlung hinzu.
std::optional
ist noch nicht Teil des Standards, aber Sie können Implementierungen entweder als Teil der letzten Compiler, in Boost oder in anderen Bibliotheken erhalten.
Wenn ich Ausnahmen aus irgendeinem Grund nicht verwenden kann, erstelle ich Initialisierungsmethoden für Objekte, die Konstruktion fehlschlagen können. Also würde der Konstruktor nichts anderes als eine triviale Einrichtung tun. Dann kann ich eine Init-Methode haben, die die tatsächliche Ressourcenerfassung durchführt und dementsprechend true/false zurückgibt. –
Sagen deine Richtlinien nichts über solche Situationen? Es ist * ein sehr allgemeines C++ Idiom schließlich. Und wenn die Richtlinien dies zulassen, könnten Sie immer ein System verwenden, das der [Standard-E/A-Bibliothek] (http://en.cppreference.com/w/cpp/io) und seinen Streams, z. dass die Streams in Bedingungen verwendet werden können, um nach Fehlern zu suchen, oder wie die Dateiströme eine 'is_open'-Funktion haben. –
@JoachimPileborg Ich denke nicht, dass es in den Richtlinien berücksichtigt wurde, sie können eine Aktualisierung erfordern (obwohl es ein eingebettetes Echtzeitsystem ist und Ausnahmen nicht gemocht werden!) Unabhängig davon ist mein Gefühl, dass es nicht möglich ist, also nur für Um dieser Frage willen möchte ich mich bestätigt fühlen! :-) – Joe