Özel İstisna Hiyerarşileri
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 82 / 104.
Standart kütüphane std::runtime_error gibi kullanışlı istisna sınıfları sağlasa da, gerçek dünya uygulamaları genellikle özel istisna hiyerarşileri oluşturmaktan fayda sağlar. Standart istisnalardan miras alan kendi istisna sınıflarınızı tanımlayarak, ek bağlam taşıyan ve daha kesin hata yönetimi sağlayan alana özgü hata türleri oluşturabilirsiniz.
Özel bir istisna sınıfı genellikle std::exception sınıfından veya onun türetilmiş sınıflarından birinden miras alır ve what() metodunu geçersiz kılar (override eder):
#include <exception>
#include <string>
class DatabaseException : public std::exception {
std::string message;
public:
DatabaseException(const std::string& msg) : message(msg) {}
const char* what() const noexcept override { return message.c_str(); }
};
class ConnectionException : public DatabaseException {
public:
ConnectionException(const std::string& host)
: DatabaseException("Failed to connect to: " + host) {}
};
class QueryException : public DatabaseException {
public:
QueryException(const std::string& query)
: DatabaseException("Invalid query: " + query) {}
};Bu hiyerarşi, catch bloklarının istisnaları farklı özgünlük seviyelerinde ele almasına olanak tanır:
try {
// veritabanı işlemleri...
throw ConnectionException("localhost");
} catch (const ConnectionException& e) {
std::cout << "Connection issue: " << e.what() << "\n";
} catch (const DatabaseException& e) {
std::cout << "Database error: " << e.what() << "\n";
} catch (const std::exception& e) {
std::cout << "General error: " << e.what() << "\n";
}what() üzerindeki noexcept belirleyicisi önemlidir - metodun hata fırlatmayacağını garanti eder, ki bu temel sınıf arayüzü tarafından gereklidir. C++ ilk eşleşen işleyiciyi kullandığından, catch bloklarınızı en özelden en genele doğru sıralayın.
Görev
KolayFarklı türdeki dosyayla ilgili hataları işleyen özel bir istisna hiyerarşisine sahip bir dosya işleme sistemi oluşturalım. Farklı özgünlük seviyelerinde hassas hata işlemeye olanak tanıyan, temel bir istisna sınıfından miras alan alana özgü istisnalar oluşturacaksınız.
Kodunuzu üç dosya halinde düzenleyeceksiniz:
FileExceptions.h: Dosya işlemleri için özel istisna hiyerarşinizi tanımlayın.std::exceptionsınıfından miras alan temel birFileExceptionsınıfı oluşturun. Bu sınıf bir hata mesajı saklamalı vewhat()metodununoexceptbelirleyicisi ile geçersiz kılmalıdır (override).Ardından iki türetilmiş istisna sınıfı oluşturun:
FileNotFoundException— bir dosya adı alır ve şu mesajı oluşturur:"File not found: "+ dosya adıPermissionDeniedException— bir dosya adı alır ve şu mesajı oluşturur:"Permission denied: "+ dosya adı
Her türetilmiş sınıf, uygun mesajla üst sınıf kurucusunu çağırmalıdır.
FileProcessor.h: Dosya işlemlerini simüle eden ve özel istisnalarınızı fırlatan birFileProcessorsınıfı tanımlayın.FileProcessorsınıfınız, bir dosyayı açmayı simüle eden biropenFile(const std::string& filename)metoduna sahip olmalıdır:- Eğer dosya adı
"missing"içeriyorsa, birFileNotFoundExceptionfırlatın - Eğer dosya adı
"locked"içeriyorsa, birPermissionDeniedExceptionfırlatın - Aksi takdirde,
"Successfully opened: "+ dosya adı dizesini döndürün
- Eğer dosya adı
main.cpp: Girişten tek bir dosya adı okuyun.Bir
FileProcessoroluşturun ve dosyayı açmaya çalışın. En özelden en genele doğru sıralanmış işleyicilere sahip bir try-catch bloğu kullanın:FileNotFoundExceptionyakalayın ve şunu yazdırın:"File Error: "+ hata mesajıPermissionDeniedExceptionyakalayın ve şunu yazdırın:"Access Error: "+ hata mesajıFileExceptionyakalayın ve şunu yazdırın:"General File Error: "+ hata mesajı
Eğer hiçbir istisna fırlatılmazsa,
openFile()tarafından döndürülen başarı mesajını yazdırın.
Örneğin, report.txt girişi ile:
Successfully opened: report.txtmissing_data.csv girişi ile:
File Error: File not found: missing_data.csvlocked_config.ini girişi ile:
Access Error: Permission denied: locked_config.iniBu zorluk, özel istisna hiyerarşilerinin hataları uygun ayrıntı düzeyinde işlemenize nasıl olanak tanıdığını gösterir; hassas işlemeye ihtiyaç duyduğunuzda belirli istisnaları yakalayabilir veya tüm dosya hatalarını tek tipte işlemek istediğinizde temel istisnayı yakalayabilirsiniz.
Kopya kağıdı
Özel istisna sınıfları std::exception veya onun türetilmiş sınıflarından miras alır ve what() metodunu geçersiz kılar (override eder):
#include <exception>
#include <string>
class DatabaseException : public std::exception {
std::string message;
public:
DatabaseException(const std::string& msg) : message(msg) {}
const char* what() const noexcept override { return message.c_str(); }
};Özel temel istisnalardan miras alarak istisna hiyerarşileri oluşturun:
class ConnectionException : public DatabaseException {
public:
ConnectionException(const std::string& host)
: DatabaseException("Failed to connect to: " + host) {}
};Catch bloklarını en özelden en genele doğru sıralayarak istisnaları farklı özgünlük seviyelerinde ele alın:
try {
throw ConnectionException("localhost");
} catch (const ConnectionException& e) {
std::cout << "Connection issue: " << e.what() << "\n";
} catch (const DatabaseException& e) {
std::cout << "Database error: " << e.what() << "\n";
} catch (const std::exception& e) {
std::cout << "General error: " << e.what() << "\n";
}what() üzerindeki noexcept belirleyicisi, metodun istisna fırlatmayacağını garanti eder; bu, temel sınıf arayüzü tarafından zorunludur.
Kendin dene
#include <iostream>
#include <string>
#include "FileExceptions.h"
#include "FileProcessor.h"
using namespace std;
int main() {
string filename;
cin >> filename;
FileProcessor processor;
// TODO: İstisnaları işlemek için bir try-catch bloğu kullanın
// İşleyicileri en özelden en genele doğru sıralayın:
// 1. FileNotFoundException yakalayın - yazdırın: "File Error: [message]"
// 2. PermissionDeniedException yakalayın - yazdırın: "Access Error: [message]"
// 3. FileException yakalayın - yazdırın: "General File Error: [message]"
// Eğer istisna yoksa, openFile() fonksiyonundan gelen başarı mesajını yazdırın
try {
// TODO: processor.openFile() fonksiyonunu çağırın ve sonucu işleyin
}
// TODO: Catch bloklarını en özelden en genele doğru sırayla ekleyin
return 0;
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarC++ Build ve DerlemeBaşlık Dosyaları ve Kaynak DosyalarıAd Alanları ve KapsamC++'ta OOP'ye GirişSınıflar ve Nesneler'this' İşaretçisiMetotlar (Üye Fonksiyonlar)Öznitelikler (Veri Üyeleri)Ctor ve Dtor TemelleriÖzet - Basit Hesap Makinesi4Sınıf Özellikleri
Örnek ve Statik ÜyelerGetter ve Setter MetotlarıConst Üye FonksiyonlarMutable Anahtar KelimesiStatik Metotlar ve DeğişkenlerFriend Fonksiyonlar ve SınıflarÖzet - Banka Hesabı Yöneticisi7Kalıtım
Temel KalıtımKalıtım Erişim SeviyeleriCtor ve Dtor Çağrılma SırasıMetot Geçersiz KılmaSanal Fonksiyonlar ve VTableÇoklu KalıtımSanal KalıtımÖzet - Çalışan Hiyerarşisi10STL Genel Bakış
STL Genel Bakış ve FelsefesiSTL KonteynerleriİteratörlerSTL AlgoritmalarıFunctor'lar ve Lambda İfadeleriÖzet - Kelime Frekansı13Tasarım Kalıpları 1. Bölüm
Tasarım Kalıplarına GirişSingleton KalıbıFactory ve Abstract FactoryBuilder KalıbıObserver KalıbıStrategy Kalıbı2Bellek Yönetimi
Stack ve Heap Bellekİşaretçiler ve ReferanslarDinamik Bellek (new/delete)C++'ta Akıllı İşaretçilerC++'ta RAIIÖzet - Dinamik Dizi Yöneticisi5Kapsülleme
C++'da Erişim BelirleyicilerDerinlemesine Erişim BelirleyicilerBilgi GizlemeStruct vs Classİç İçe ve Dahili SınıflarÖzet - Öğrenci Kayıt Sistemi8Çok Biçimlilik
Derleme ve Çalışma Zamanı Çok BiçimliliğiFonksiyon Aşırı YüklemeSanal Fonksiyonlara Yeniden BakışSaf Sanal FonksiyonlarSoyut SınıflarC++'ta Arayüz TasarımıDynamic Casting ve RTTIÖzet - Şekil Hesaplayıcı11İleri Düzey OOP Kavramları
Kompozisyon ve Kalıtım KarşılaştırmasıCRTP ile Mixin YapılarıPimpl İdiyomuTür Silme (Type Erasure)Enum Sınıfları ve Güçlü TiplendirmeOOP'de İstisna YönetimiÖzel İstisna Hiyerarşileri3Yapıcılar ve Yıkıcılar
Varsayılan YapıcıParametreli YapıcıKopya YapıcıTaşıma YapıcısıYapıcı İlklendirme ListeleriTemsilci YapıcılarYıkıcılara Derinlemesine BakışÜç / Beş / Sıfır KuralıÖzet - String Sınıfı6Operatör Aşırı Yükleme
Operatör Aşırı Yüklemeye GirişAritmetik Operatör Aşırı YüklemeKarşılaştırma Operatörü Aşırı YüklemeStream OperatörleriAtama Operatörü Aşırı Yükleme[] ve () Operatör Aşırı YüklemeTip Dönüşüm OperatörleriÖzet - Matris Sınıfı9Şablonlar
Fonksiyon ŞablonlarıSınıf ŞablonlarıŞablon ÖzelleştirmeVariadic ŞablonlarSFINAE ve Type Traits TemelleriÖzet - Generic Konteyner