Benim API'mda std::exception
türetilmiş küçük bir özel durum hiyerarşisi var. Bir hata kodu, dosya, çizgi ve işlev sağlayan bir Exception
taban sınıfım var. Diğer daha özel istisnalar ise Exception
'dan türetilmiştir. Örneğin, türetilmiş bir sınıf, platforma özgü hata kodunu ve ayrıca hangi işlevin hata kodunu döndürdüğünü belirten bir alan ekler. Bu, system_error
'un basitleştirilmiş bir sürümü gibidir, ancak C++ 11 özelliklerini kullanamıyorum (VS2005 ile çalışıp sıkışıp kaldım).Günlük biçimlendirmesindeki ayrıcalık istisnası
Bu özel durumları günlüğe kaydetme sınıfımla günlüğe kaydetmem gerekiyor. İstisnaların belirli bir biçimde kaydedilmesini istiyorum. Çeşitli çevrimiçi forumları okuduktan ve Boost's Error and Exception Handling Guidelines'u okuduktan sonra, her özel durumun what
işlevinin veya Exception
içindeki herhangi bir sanal işlevin, günlüğe kaydetme için özel durumu biçimlendirmek için uygun bir yer olduğunu düşünmüyorum. Bu nedenle, what
işlevlerim yalnızca sınıfın adını döndürüyor.
İstisnai durumları yakalarken genellikle genellikle std::exception
çok genel kural dışı durumları yakalamak ve kaydediciye aktarmak istiyorum. Tek istisnaları sık sık yakalamak istemiyorum çünkü API'dan (API'mnın kamusal kısmı C) kaçmaktan istisnaları önlemeye çalışıyorum ve ortaya çıkabilecek bazı istisnalar olabilir. Ben böyle bir kod önlemek istiyorum: benim günlük sınıfında Yani
try { /* blah */ }
catch {DerivedException const& ex) { logger.log(ex); }
...
catch {Exception const& ex) { logger.log(ex); }
, benim log
işlevi std::exception
argüman kabul eder. Daha sonra, parametreyi çeşitli özel durum sınıflarıyla karşılaştırmak, uygun türe dökmek ve sonra bu tür bir özel durum için özelleştirilmiş bir günlük kaydı işlevini çağırmak için typeid
kullanır. Bu aslında in this other post tarif edilen aynı tekniktir. dynamic_cast
herhangi bir geçerli downCast için başarılı olabilir çünkü
typeid
yerine
dynamic_cast
kullanın ve kod bakım amacıyla, gerçekten
log
işlevinde benim
if
tabloların sırası önemli istemiyoruz.
Bu iyi bir tasarım mı? Böyle typeid
kullanarak bana yanlış geliyor, ama bunu yapmak için geçerli nedenler olduğunu düşünüyorum. “Civcivte” çok fazla istisna eylemi görmedim, çünkü öncelikle C ile çalışıyoruz, bu yüzden konuya çok fazla yaklaşım görmedim. Farkında olmaları gereken günlük biçimlendirmelerinden özel durumları ayırmanın başka yolları var mı?
DÜZENLEME: Ben ziyaretçi desen kullanarak öneri aldı, ama benim duruma uyarladı
uygulamaya karar ne. std::exception
'u yakalamak istedim, çünkü bunlar kendime ait olduğu kadar atılabilir, ancak günlük mesajını istisna tipine göre biçimlendirebilir.
Her özel durum sınıfım Exception
sınıfımdan türetilir ve sanal işlevi accept
uygular. visit
işlevlerini sağlayan bir ExceptionVisitor
arabirimini uygulayan bir ExceptionLogger
sınıfı oluşturdum.
LogFile
sınıfı ExceptionLogger
bir örneğini, hem de bir std::exception
parametre alır onun log
fonksiyonunun bir aşırı vardır. log
işlevinde, temel türüme, Exception
'u deneyin. Başarılırsa, özel durumun accept
işlevini ararım, aksi takdirde doğrudan ExceptionLogger::visit(std::exception const&)
işlevini çağırırım.std::exception
, accept
işlevimi uygulamıyorsa, dynamic_cast
'a ihtiyacım vardı, böylece daha ayrıntılı günlüğe kaydetmenin mümkün olup olmadığını belirleyebilirdim.
typeid
kontrol
if
tabloların bir dizi bunu seçtik çünkü:
- Bu bir sürdürücü Yeni bir istisna bundan türetilen eklerse ben
gelecek bakıcılarına başvurabilir adlandırılmış tasarım deseni
BenException
tabanımdan ancak bu istisna için yeni birvisit
işlevini uygulamayı unuttuğum için,Exception
tabanına uygulanan bir günlüğü kaydetmeye devam ediyorum - bir dosya, satır numarası ve işlev.if
tabloların dizi uygulamaya olsaydı, ben
what
sonuçlarını yazdırmak için adildirstd::exception
Günlüğün çalışma, geri düşmek ederdi, yoksa birException
birdynamic_cast
denedim olabilir .Elbette bu durumda derleyici hatası tercih ediyorum.
Alternatif, Ziyaretçi kalıbını uygulamak olacaktır. –
@DDrmmr - Ziyaretçi desenini kullanarak sona erdim. Bunu bir cevap haline getirin ve kabul edildi olarak işaretleyeceğim. –