Fark: std :: runtime_error vs std :: exception ()


128

Arasındaki fark nedir std::runtime_errorve std::exception? Her biri için uygun kullanım nedir? İlk başta neden farklılar?

Yanıtlar:


153

std::exceptiontek amacı istisna hiyerarşisinde temel sınıf olarak hizmet etmek olan sınıftır. Başka kullanımı yoktur. Diğer bir deyişle, kavramsal olarak soyut bir sınıftır (terimin C ++ anlamında soyut sınıf olarak tanımlanmasa da).

std::runtime_errorstd::exceptionçeşitli çalışma zamanı hataları durumunda atılması amaçlanan daha özel bir sınıftır . Bunun ikili bir amacı vardır. Kendi başına fırlatılabilir veya daha özel çalışma zamanı hatası istisnaları std::range_error, std::overflow_errorvb. İçin temel bir sınıf olarak hizmet std::runtime_erroredebilir. inen sınıflar std::exception.

Tıpkı std::runtime_error, standart kütüphane içeren std::logic_errorayrıca inen, std::exception.

Bu hiyerarşiye sahip olmanın amacı, kullanıcıya C ++ istisna işleme mekanizmasının tam gücünü kullanma fırsatı vermektir. 'Catch' cümlesi polimorfik istisnaları yakalayabildiğinden, kullanıcı istisna hiyerarşisinin belirli bir alt ağacından istisna türlerini yakalayabilen 'catch' cümleleri yazabilir. Örneğin, alt ağaçtan catch (std::runtime_error& e)tüm istisnaları yakalayarak std::runtime_errordiğerlerinin geçmesine izin verir (ve çağrı yığınında daha da yukarı uçar).

PS Yararlı bir istisna sınıfı hiyerarşisi tasarlamak (kodunuzun her noktasında yalnızca ilgilendiğiniz istisna türlerini yakalamanıza izin verir) önemsiz olmayan bir görevdir. Standart C ++ kitaplığında gördüğünüz şey, dilin yazarları tarafından size sunulan olası bir yaklaşımdır. Gördüğünüz gibi, tüm istisna türlerini "çalışma zamanı hataları" ve "mantık hataları" olarak ayırmaya karar verdiler ve oradan kendi istisna türlerinizle devam etmenize izin verdiler. Elbette, bu hiyerarşiyi yapılandırmanın, tasarımınıza daha uygun olabilecek alternatif yolları vardır.

Güncelleme: Taşınabilirlik Linux vs Windows

Loki Astari ve unixman83'ün aşağıdaki cevaplarında ve yorumlarında belirttiği gibi, exceptionsınıfın kurucusu C ++ standardına göre herhangi bir argüman almaz. Microsoft C ++, exceptionsınıfta bağımsız değişkenler alan bir oluşturucuya sahiptir , ancak bu standart değildir. runtime_errorSınıfı bir yapıcı alma argümanları (sahip char*iki platformda, Windows ve Linux işletim sistemlerinde). Taşınabilir olmak için daha iyi kullanın runtime_error.

(Unutmayın, projenizin bir özelliği kodunuzun Linux'ta çalışması gerekmediğini söylediği için, hiçbir zaman Linux'ta çalışması gerekmediği anlamına gelmez.)


1
teşekkür ederim. mükemmel cevap. Yine de farklı türde bir istisnaya ihtiyaç olup olmadığını merak etsem de ... sadece bir düşünce.
sivabudh

1
İstisnanın yeniden ele alınabileceği bir olasılık varsa, istisnayı sorunu deneyecek ve düzeltecek işleyiciye yönlendirmek için istisna işleme mekanizmasını kullanabileceğimiz için farklı bir istisna türü faydalı olabilir. İyileşme şansı yoksa, standart istisnalardan biri uygundur.
Martin York

1
Bir kenara olarak: hiçbir yerde sizi türetmeye zorlayan hiçbir kural yoktur std::exception. Elbette, her stdşey bunun türetilmiş sınıflarını atar, ancak yalnızca std::exceptiontüretilmiş nesneleri fırlatmak için kesinlikle hiçbir neden yoktur .
rubenvb

1
@rubenvb Bunu bilmiyordum, ancak yalnızca istisnadan türetilen sınıfların nesneleri atılırsa gelecekteki bakım için kodu temizleyeceğini düşünüyorum. Örnek: Kod tabanımda hangi özel istisnaların uygulandığını bulmayı ve istisnadan türetilen sınıfları araştırmayı seviyorum.
this.myself

21

std::exceptionstandart istisna hiyerarşisinin soyut temeli olarak düşünülmelidir (dikkate alınmalıdır). Bunun nedeni, belirli bir mesajı iletecek bir mekanizmanın olmamasıdır (bunu yapmak için türetmeli ve uzmanlaşmalısınız what()). Std :: exception'ı kullanmaktan sizi alıkoyacak hiçbir şey yoktur ve basit uygulamalar için ihtiyacınız olan tek şey bu olabilir.

std::runtime_errordiğer yandan bir dizgeyi mesaj olarak kabul eden geçerli kuruculara sahiptir. Tüm what()olarak adlandırılan bir const char işaretçi döndürülür yapıcı içine geçirildi aynı dize sahip olan bir Cı-dizge noktaları.

try
{
    if (badThingHappened)
    {
         throw std::runtime_error("Something Bad happened here");
    }
}
catch(std::exception const& e)
{
    std::cout << "Exception: " << e.what() << "\n";
} 

1
Cevap martin için teşekkürler. Bununla birlikte, std :: exception () 'ı yukarıda tanımladığınız gibi kullanıyorum. yani std :: exception () kurucusu ayrıca bir std :: string () veya const char * alabilir.
sivabudh

14
Standarda göre değil. std :: exception, argüman almayan bir kurucuya sahiptir. Bir std :: string veya bir C-String kabul eden bir sürüm kullanmak taşınabilir değildir.
Martin York

10
Microsoft yüzünden fırlatmaya alıştım std::exception(std::string). Şimdi, kodumun std::runtime_errorLinux'ta (GCC) çalışmasını istiyorsam atmam gerektiğini anlıyorum.
unixman83
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.