Czy można sprawić, że domyślny konstruktor będzie bezużyteczny?

14

W szczególności pytanie o domyślny konstruktor

Biorąc pod uwagę, że konstruktor inicjuje wszystkie dane dla obiektu, jeśli utworzę klasę, której nie można użyć bez odpowiedniej inicjalizacji, czy nie jest tak, że domyślny konstruktor jest bezużyteczny? Rozważać:

// 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
}

Ta zmienna current_entryjest zasadniczo bezużyteczna nie? Jeśli ktoś spróbuje go później przetworzyć, prawdopodobnie wystąpią błędy; wtedy stworzyliby kod do obsługi takich błędów ...

Aby złagodzić taki dodatkowy, niepotrzebny kod: dlaczego nie uczynić domyślnego konstruktora bezużytecznym? Tak jak

...etc

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

...etc

PS: na marginesie, jeśli można po prostu sprawić, że domyślny konstruktor nie nadaje się do użytku, czy dobrze jest umieścić ten rzut w nagłówku, ponieważ i tak nie ujawniono żadnych innych szczegółów implementacji?

użytkownik2738698
źródło

Odpowiedzi:

34

Tak, w porządku (właściwie jest dobrze ) sprawić, że domyślny konstruktor będzie bezużyteczny, jeśli nie ma rozsądnego sposobu na zainicjowanie obiektu bez żadnych argumentów. Ale nie „wyłączaj” go, zgłaszając wyjątek. Zamiast tego ustaw go jako prywatny. Idealnie byłoby, gdyby twój interfejs nie zawierał żadnych metod ani konstruktorów, których ludzie „nie powinni” wywoływać.

Doval
źródło
1
Tak więc, czyniąc to prywatnym, użytkownik próbujący użyć domyślnego konstruktora otrzyma błąd w czasie kompilacji?
user2738698,
@ user2738698 Prawidłowo.
Doval
8
Jeśli można użyć c ++ 11, a następnie wyraźnie oznaczyć go jako usunięte: CSV_Entry() = delete;.
bstamour
13
Czy to nie jest nawet łatwiejsze niż to? Jeśli zdefiniowane zostaną konstruktory inne niż domyślne, kompilator nie utworzy domyślnie konstruktora domyślnego. Ta klasa ma zdefiniowany konstruktor inny niż domyślny (który poleciłbym explicitBTW). Więc jeśli tego nie zdefiniujesz, nie będzie istniał.
Fred Larson
7
@FredLarson Jawne usunięcie wyraża zamiar usunięcia, więc nikt nie myśli, że to pomyłka.
Darkhogg