Ist es in Ordnung, einen Standardkonstruktor unbrauchbar zu machen?

14

Speziell nach dem Standardkonstruktor fragen

Wenn der Konstruktor alle Daten für ein Objekt initialisiert und eine Klasse erstellt, die ohne ordnungsgemäße Initialisierung nicht verwendet werden kann, ist der Standardkonstruktor dann nicht nutzlos? Erwägen:

// A class for handling lines in a CSV file
class CSV_Entry {
private:
    unsigned num_entries;
    std::string string_version;
    std::vector<std::string> vector_version;
    ...etc
public:
    CSV_Entry();
    CSV_Entry(const std::string& src_line);

    // returns a vector copy of the original entry
    std::vector<std::string> get_vector_snapshot();
}

int main( void ) {
    ...etc

    CSV_Entry example = CSV_Entry();
    std::vector<std::string> current_entry = example.get_vector_snapshot();

    ...etc
}

Diese Variable current_entryist im Wesentlichen nutzlos, nein? Wenn jemand später versucht, es zu verarbeiten, wird er wahrscheinlich Fehler bekommen. dann würden sie Code erstellen, um solche Fehler zu behandeln ...

So verringern Sie diesen zusätzlichen, unnötigen Code: Machen Sie den Standardkonstruktor nicht unbrauchbar. Wie so

...etc

CSV_Entry() {
    throw Verbose_Exception( "CSV_Entry: do not use the default constructor" );
}

...etc

PS: Wenn es in Ordnung ist, nur den Standardkonstruktor unbrauchbar zu machen, ist es in Ordnung, diesen Throw in den Header zu setzen, da ohnehin keine anderen Implementierungsdetails enthüllt werden?

user2738698
quelle

Antworten:

34

Ja, es ist in Ordnung (eigentlich ist es gut ), den Standardkonstruktor unbrauchbar zu machen, wenn es keine sinnvolle Möglichkeit gibt, das Objekt ohne Argumente zu initialisieren. Deaktivieren Sie es jedoch nicht, indem Sie eine Ausnahme auslösen. Machen Sie es stattdessen privat. Idealerweise enthält Ihre Schnittstelle keine Methoden oder Konstruktoren, die von Menschen "nicht empfohlen" werden.

Doval
quelle
1
Wenn Sie es also als privat kennzeichnen, wird dem Benutzer, der versucht, den Standardkonstruktor zu verwenden, beim Kompilieren ein Fehler angezeigt.
user2738698
@ user2738698 Richtig.
Doval
8
Wenn Sie C ++ 11 verwenden können, dann ist es ausdrücklich markiert als gelöscht: CSV_Entry() = delete;.
bstamour
13
Ist es nicht noch einfacher? Wenn nicht standardmäßige Konstruktoren definiert sind, erstellt der Compiler keinen impliziten Standardkonstruktor. Für diese Klasse ist ein nicht standardmäßiger Konstruktor definiert (was ich übrigens empfehlen würde explicit). Also, wenn Sie es einfach nicht definieren, wird es nicht existieren.
Fred Larson
7
@FredLarson Das explizite Löschen drückt die Absicht aus, es zu löschen, sodass niemand denkt, dass es ein Fehler war.
Darkhogg