Programiści C ++ nie szukają specyfikacji wyjątków. Szukają gwarancji wyjątku.
Załóżmy, że fragment kodu zgłosił wyjątek. Jakie założenia może przyjąć programista, że nadal będą aktualne? Co ze sposobu pisania kodu gwarantuje kod po wyjątku?
Czy też jest możliwe, że pewien fragment kodu może zagwarantować, że nigdy nie wyrzuci (tj. Nic poza zakończeniem procesu systemu operacyjnego)?
Słowo „wycofać” pojawia się często w dyskusjach na temat wyjątków. Możliwość przywrócenia do prawidłowego stanu (który jest wyraźnie udokumentowany) jest przykładem gwarancji wyjątku. Jeśli nie ma gwarancji wyjątku, program powinien zakończyć się na miejscu, ponieważ nie ma nawet gwarancji, że kod, który wykona później, będzie działał zgodnie z przeznaczeniem - powiedzmy, jeśli pamięć ulegnie uszkodzeniu, dalsze działanie jest technicznie niezdefiniowanym zachowaniem.
Różne techniki programowania w C ++ promują wyjątki. RAII (zarządzanie zasobami oparte na zakresie) zapewnia mechanizm wykonywania kodu czyszczenia i zapewnia, że zasoby są zwalniane zarówno w normalnych, jak i wyjątkowych przypadkach. Wykonanie kopii danych przed wykonaniem modyfikacji na obiektach pozwala przywrócić stan tego obiektu, jeśli operacja się nie powiedzie. I tak dalej.
Odpowiedzi na to pytanie StackOverflow dają wgląd w to, jak długo programiści C ++ rozumieją wszystkie możliwe tryby awarii, które mogą się zdarzyć w ich kodzie, i starają się strzec poprawności stanu programu pomimo awarii. Analiza kodu C ++ wiersz po wierszu staje się nawykiem.
Podczas programowania w C ++ (do użytku produkcyjnego) nie można pozwolić sobie na połysk szczegółów. Ponadto binarny obiekt blob (nie open-source) jest zmorą programistów C ++. Jeśli będę musiał wywołać jakiś binarny obiekt blob, a ten obiekt zawiedzie, wówczas inżynieria odwrotna jest tym, co zrobiłby programista C ++.
Odniesienie: http://en.cppreference.com/w/cpp/language/exceptions#Exception_safety - patrz punkt Bezpieczeństwo wyjątków.
C ++ nieudana próba zaimplementowania specyfikacji wyjątków. Późniejsza analiza w innych językach wskazuje, że specyfikacje wyjątków po prostu nie są praktyczne.
Dlaczego jest to nieudana próba: aby ją ściśle egzekwować, musi być częścią systemu typów. Ale tak nie jest. Kompilator nie sprawdza specyfikacji wyjątku.
Dlaczego C ++ to wybrało i dlaczego doświadczenia z innych języków (Java) dowodzą, że specyfikacja wyjątków jest dyskusyjna: gdy ktoś modyfikuje implementację funkcji (na przykład musi wywołać inną funkcję, która może rzucić nowy rodzaj wyjątek), ścisłe wymuszanie specyfikacji wyjątków oznacza, że musisz również zaktualizować tę specyfikację. To się rozprzestrzenia - może być konieczne zaktualizowanie specyfikacji wyjątków dla dziesiątek lub setek funkcji, co jest prostą zmianą. Gorzej jest z abstrakcyjnymi klasami podstawowymi (odpowiednik interfejsów C ++). Jeśli specyfikacja wyjątków zostanie wymuszona na interfejsach, implementacje interfejsów nie będą mogły wywoływać funkcji, które generują różne typy wyjątków.
Odniesienie: http://www.gotw.ca/publications/mill22.htm
Począwszy od wersji C ++ 17, [[nodiscard]]
atrybutu można użyć w przypadku zwracanych wartości funkcji (patrz: https://stackoverflow.com/questions/39327028/can-ac-function-be-declared-such-that-the-return-value -nie można ignorować ).
Więc jeśli dokonam zmiany kodu i wprowadzę nowy rodzaj warunku awarii (tj. Nowy typ wyjątku), czy jest to zmiana przełomowa? Czy powinien był zmusić dzwoniącego do zaktualizowania kodu, czy przynajmniej zostać ostrzeżony o zmianie?
Jeśli zaakceptujesz argumenty, że programiści C ++ szukają gwarancji wyjątku zamiast specyfikacji wyjątku, wówczas odpowiedź jest taka, że jeśli nowy rodzaj warunku niepowodzenia nie złamie żadnego z wyjątków gwarantujących poprzednio obiecany kod, nie będzie to zmiana przełomowa.