Last modified: August 12, 2019
This article is written in: 🇵🇱
W programowaniu, wyjątki służą jako mechanizm do sygnalizowania i obsługi nieoczekiwanych sytuacji, które mogą wystąpić podczas działania programu. Choć wyjątki często są używane w odpowiedzi na błędy, nie każdy wyjątek musi wynikać z błędu. Wyjątek może być również środkiem do poinformowania innych części kodu o pewnych warunkach lub sytuacjach, które wymagają specjalnej uwagi.
for
powodująca nieskończoną iterację.Wyjątki w programowaniu służą do sygnalizowania takich problemów. Pozwalają programistom na określenie, jak program powinien reagować w takich sytuacjach, umożliwiając bardziej kontrolowane i eleganckie zarządzanie niespodziewanymi warunkami.
W momencie wystąpienia wyjątku w programie, normalny przepływ kontroli jest przerywany. Wyjątek, jeśli nie zostanie obsłużony w odpowiednim miejscu, może doprowadzić do zakończenia działania programu. Jednak dzięki mechanizmowi try-catch
można przechwytywać i obsługiwać te wyjątki.
Poniżej znajduje się przykład działania wyjątków w C++:
#include <iostream>
#include <stdexcept>
void funkcja() { throw std::runtime_error("Wystąpiła wyjątkowa sytuacja!"); }
int main() {
try {
funkcja();
} catch (const std::runtime_error &e) {
std::cout << "Przechwycono wyjątek: " << e.what() << std::endl;
}
std::cout << "Życie toczy się dalej" << std::endl;
return 0;
}
W powyższym kodzie, funkcja funkcja()
rzuca wyjątek typu std::runtime_error
. Ten wyjątek jest następnie przechwytywany i obsługiwany w bloku try-catch
w funkcji main()
. Dzięki temu program nie kończy swojego działania po wystąpieniu wyjątku, co potwierdza komunikat "Życie toczy się dalej".
Programiści mają możliwość korzystania z wielu wbudowanych typów wyjątków w C++, ale także mogą definiować własne typy wyjątków, dostosowane do specyficznych potrzeb swojego kodu.
Definiowanie własnych typów wyjątków w C++ jest prostym procesem, który polega na dziedziczeniu po istniejących klasach wyjątków. Najczęściej używaną klasą bazową dla własnych wyjątków jest std::exception
.
Oto jak można zdefiniować własny wyjątek:
class MojWyjatek : public std::exception
{
public:
MojWyjatek(const std::string& komunikat) : komunikat_(komunikat) {}
virtual const char* what() const throw() { return komunikat_.c_str(); }
private:
std::string komunikat_;
};
W tym przykładzie, klasa MojWyjatek
dziedziczy po std::exception
i umożliwia przekazanie indywidualnego komunikatu, który jest następnie zwracany przez przesłoniętą funkcję what()
. Tak zdefiniowany wyjątek może być rzucony i przechwycony w taki sam sposób, jak wbudowane typy wyjątków.
C++ posiada rozbudowaną hierarchię klas wyjątków, która ułatwia zarządzanie różnymi typami błędów. Na szczycie tej hierarchii znajduje się klasa std::exception
, z której dziedziczą inne klasy wyjątków.
#include <iostream>
#include <exception>
class BaseException : public std::exception {
public:
virtual const char* what() const throw() {
return "BaseException";
}
};
class DerivedException : public BaseException {
public:
virtual const char* what() const throw() {
return "DerivedException";
}
};
int main() {
try {
throw DerivedException();
} catch (const BaseException& e) {
std::cout << "Caught: " << e.what() << std::endl;
} catch (const std::exception& e) {
std::cout << "Caught: " << e.what() << std::endl;
}
return 0;
}
W powyższym przykładzie klasa DerivedException
dziedziczy po BaseException
, a BaseException
dziedziczy po std::exception
. Kiedy DerivedException
jest rzucany, może być przechwycony przez catch blok obsługujący BaseException
, ponieważ DerivedException
jest typem bardziej szczegółowym, dziedziczącym po BaseException
.
Wyjątki w programowaniu mają szerokie zastosowanie, począwszy od prostych przypadków obsługi błędów, aż po bardziej zaawansowane techniki, takie jak zapewnianie integralności danych czy zarządzanie zasobami.
Zalety:
Wady:
Aby skutecznie korzystać z wyjątków, warto stosować się do kilku najlepszych praktyk:
finally
w innych językach, aby upewnić się, że zasoby są zawsze poprawnie zwalniane.