Kiedy / dlaczego miałbym jawnie usunąć mój konstruktor? Zakładając, że powodem jest niedopuszczenie do jego użycia, dlaczego po prostu tego nie zrobić private?
W pewnym sensie dobrze się z tym łączy = default, nawet klasa nie może z tego korzystać, a ja osobiście wolę zobaczyć użycie usuniętej funkcji. nad Funkcja jest prywatna. Pierwsza z nich wyraźnie stwierdza, że „tego nie należy używać”. Jeśli cokolwiek z tego wyniknie, klasa, która nie jest w stanie tego użyć, ma znaczenie semantyczne.
chris
16
Szczerze myślę, że ludzie zaczynają być agresywni przy zbliżających się głosowaniach. Nie rozumiem, dlaczego to nie jest konstruktywne.
Luchian Grigore
4
@LuchianGrigore: Zgoda. Zastanawiałem się, dlaczego społeczność stała się o wiele bardziej sztywna. Nie widzę sensu.
Ed S.,
11
Ponieważ rzadko używam C ++ 11, jest to dla mnie bardziej pouczające, niż prawdopodobnie zdaje sobie sprawę OP. I nawet nie wiesz, że mógłby oznaczyć konstruktora delete. Zarówno pytanie, jak i odpowiedź Luchiana łatwo kwalifikują się jako konstruktywne. Każdy, kto nie oddycha subtelnymi punktami C ++ 11, ale wkrótce będzie musiał wyciągnąć coś z obu.
Zasadniczo są to różne rzeczy. privatemówi ci, że tylko członkowie klasy mogą wywołać tę metodę lub mieć dostęp do tej zmiennej (lub oczywiście przyjaciele). W takim przypadku staticmetoda tej klasy (lub dowolnego innego elementu członkowskiego) może wywołać privatekonstruktor klasy. Nie dotyczy to usuniętych konstruktorów.
Nie musisz w ogóle deklarować Foo (), jeśli deklarujesz Foo (int). Foo () nie zostanie wygenerowane i dlatego Foo f i tak jest niepoprawne. Więc twój przykład nie pokazuje przypadku dla usuniętego konstruktora. Przekonaj się
zaznacz
1
@mark Napisałem 2 konstruktorów, aby to udowodnić. Będę edytować, aby każdy był jasny
Luchian Grigore
1
Rozumiem różnicę, po prostu nie rozumiem wartości dodanej instrukcji delete w ogóle, aw szczególności dla konstruktora. W końcu mógłbym określić prywatnego konstruktora domyślnego bez treści. Wtedy kod również zawodzi, tylko podczas linkowania. Cóż, widzę, że usuwanie wyraźniej przekazuje intencję, ale to wszystko.
znak
11
@mark Tak, to byłby sposób robienia rzeczy w C ++ 98. Ale IMHO, jasne przekazywanie intencji jest w rzeczywistości bardzo ważną rzeczą w programowaniu w ogóle. W tym przypadku niektórzy czytelnicy mogą zobaczyć prywatnego niezdefiniowanego konstruktora i założyć, że jest on przypadkowy i po prostu dodać do niego definicję, zwłaszcza jeśli definicja jest tak banalna jak domyślny konstruktor (Tak, komentarz pomaga, ale wolelibyśmy kompilator egzekwowanie zamiast wymuszania komentarzy). Mając wyraźniejszy zamiar, otrzymujemy również znacznie lepszy komunikat o błędzie, który mówi „jawnie usunięte” zamiast „niezdefiniowane odniesienie”.
mpark
2
Naprawdę nie rozumiem, jak to odpowiada na główne pytanie. Pytanie w tytule i pierwsze pytanie OP w poście brzmiało: Kiedy / dlaczego chciałbym jawnie usunąć mojego konstruktora?
Alexander Bolinsky,
13
po co jawnie usunąć konstruktora?
Kolejny powód:
używam, deletegdy chcę się upewnić, że klasa jest wywoływana z inicjatorem. Uważam to za bardzo elegancki sposób na osiągnięcie tego bez kontroli w czasie wykonywania.
Usunięta deklaracja jest tutaj zbędna. Jest automatycznie usuwany za pomocą dowolnego konstruktora dostarczonego przez użytkownika
Mike'a Lui
5
Aby wyjaśnić komentarz @MikeLui, usunięta deklaracja jest niepotrzebna kompilatorowi . Istnieje wiele przypadków, w których taki kod powinien zostać dołączony, aby zadeklarować zamiar innym programistom .
Jeff G
Wraz z zadeklarowaniem swojego zamiaru tworzy oczywiste miejsce na udokumentowanie powodu usunięcia w interfejsie publicznym, a dodatkowo błędem kompilatora będzie coś w rodzaju „użycia usuniętej funkcji”. Gdyby Foomiał wiele konstruktorów, ale nie Foo foo;byłby to domyślny, spowodowałoby znacznie dłuższy błąd, wymieniając wszystkie niejawnie zdefiniowane, chronione i prywatne konstruktory, których nie udało się dopasować.
sigma
Nadal nie rozumiem, jak dodatkowa linia z deklaracją konstruktora, która słowo kluczowe „= delete” deklaruje zamiar idei „brak domyślnego konstruktora” lepiej niż ... po prostu brak domyślnego konstruktora? Przykład: Nie chcę deklarować zmiennej „a” w swoim kodzie - co jest lepsze, aby napisać „// int a; // nie ma potrzeby definiowania zmiennej a” lub po prostu nie pisać nic o tej zmiennej w kodzie?
Ezh
2
Spotkałem się z domyślnymi kontrolerami zadeklarowanymi jako „usunięte” w kodzie źródłowym LLVM (na przykład w AlignOf.h). Powiązane szablony klas znajdują się zwykle w specjalnej przestrzeni nazw o nazwie „llvm :: detail”. Myślę, że głównym celem było to, że uważali tę klasę tylko za klasę pomocniczą. Nigdy nie zamierzali ich tworzyć; tylko po to, aby używać ich w kontekście innych szablonów klas z pewnymi sztuczkami metaprogramowania, które działają w czasie kompilacji.
Na przykład. istnieje szablon klasy AlignmentCalcImpl, który jest używany tylko w innym szablonie klasy o nazwie AlignOf jako parametr dla operatora sizeof (.). To wyrażenie można ocenić w czasie kompilacji; i nie ma potrzeby tworzenia instancji szablonu -> więc dlaczego nie zadeklarować domyślnego usuwania ctora, aby wyrazić ten zamiar.
= default
, nawet klasa nie może z tego korzystać, a ja osobiście wolę zobaczyć użycie usuniętej funkcji. nad Funkcja jest prywatna. Pierwsza z nich wyraźnie stwierdza, że „tego nie należy używać”. Jeśli cokolwiek z tego wyniknie, klasa, która nie jest w stanie tego użyć, ma znaczenie semantyczne.delete
. Zarówno pytanie, jak i odpowiedź Luchiana łatwo kwalifikują się jako konstruktywne. Każdy, kto nie oddycha subtelnymi punktami C ++ 11, ale wkrótce będzie musiał wyciągnąć coś z obu.Odpowiedzi:
Co powiesz na:
//deleted constructor class Foo { public: Foo() = delete; public: static void foo(); }; void Foo::foo() { Foo f; //illegal }
przeciw
//private constructor class Foo { private: Foo() {} public: static void foo(); }; void Foo::foo() { Foo f; //legal }
Zasadniczo są to różne rzeczy.
private
mówi ci, że tylko członkowie klasy mogą wywołać tę metodę lub mieć dostęp do tej zmiennej (lub oczywiście przyjaciele). W takim przypadkustatic
metoda tej klasy (lub dowolnego innego elementu członkowskiego) może wywołaćprivate
konstruktor klasy. Nie dotyczy to usuniętych konstruktorów.Próbka tutaj .
źródło
po co jawnie usunąć konstruktora?
Kolejny powód:
używam,
delete
gdy chcę się upewnić, że klasa jest wywoływana z inicjatorem. Uważam to za bardzo elegancki sposób na osiągnięcie tego bez kontroli w czasie wykonywania.Kompilator C ++ sprawdza to za Ciebie.
class Foo { public: Foo() = delete; Foo(int bar) : m_bar(bar) {}; private: int m_bar; }
Ten - bardzo uproszczony - kod zapewnia, że nie ma takiej instancji:
Foo foo;
źródło
Foo
miał wiele konstruktorów, ale nieFoo foo;
byłby to domyślny, spowodowałoby znacznie dłuższy błąd, wymieniając wszystkie niejawnie zdefiniowane, chronione i prywatne konstruktory, których nie udało się dopasować.Spotkałem się z domyślnymi kontrolerami zadeklarowanymi jako „usunięte” w kodzie źródłowym LLVM (na przykład w AlignOf.h). Powiązane szablony klas znajdują się zwykle w specjalnej przestrzeni nazw o nazwie „llvm :: detail”. Myślę, że głównym celem było to, że uważali tę klasę tylko za klasę pomocniczą. Nigdy nie zamierzali ich tworzyć; tylko po to, aby używać ich w kontekście innych szablonów klas z pewnymi sztuczkami metaprogramowania, które działają w czasie kompilacji.
Na przykład. istnieje szablon klasy AlignmentCalcImpl, który jest używany tylko w innym szablonie klasy o nazwie AlignOf jako parametr dla operatora sizeof (.). To wyrażenie można ocenić w czasie kompilacji; i nie ma potrzeby tworzenia instancji szablonu -> więc dlaczego nie zadeklarować domyślnego usuwania ctora, aby wyrazić ten zamiar.
Ale to tylko moje przypuszczenie.
źródło