Sanırım C++ ile uğraştığım iki miras hiyerarşim var. Biri std::exception
(yeni hiyerarşi) ve diğerleri ise Exception
(eski C++ Builder VCL temel kural dışı durum sınıfı) öğesinden devralınır. Ben hariç her iki tip atmak verebilecek kod dersek, bu gibi bir kod yazmak zorunda:Bir özel durum devralma hiyerarşisini diğerine sarın mı? - ya da bununla başa çıkmak için başka bir temiz yol var mı?
try {
// do stuff....
Function1();
Function2();
} catch (std::exception &ex) {
std::cout << "STL exception caught: " << ex.what() << std::endl;
} catch (Exception &ex) {
std::cout << "Legacy exception caught: " << ex.Message.c_str() << std::endl;
} catch (SomeOtherVendorLibraryException &ex) {
// etc.
}
sorun her arayan istisna her geçen türünü elde etmeye çalışmak için tüm bu yakalama maddelerini olması gerekir yani, C++ 'nın gerçek, zorlanmış özel durum taban sınıfına sahip olmasından dolayı, her şeyi bir örnek olarak kullanabilirsiniz (örneğin, C# System.Exception
sınıfı). (catch (...)
, neleri yakaladığınızı bilmenin bir yolu olmadığından başlatıcı değildir ve erişim ihlali gibi bazı tehlikeli sistem istisnası da yakalanabileceği gibi daha iyi durumda bırakılabilir.)
Bu "eski" istisnaları, std::exception
hiyerarşisinde bir sınıfa sarmak için. Üçüncü taraf istisnalarını kendi istisna sisteminize sarmak için yaptığınız bu kavram tamamen benzeri görülmemiştir. Örneğin, .NET Framework diğer sistemlerde geniş hata kümelerini (ör. COMException
) sarar. İdeal olarak, böyle bir şey görmek istiyorum:
class LegacyException : public std::runtime_error {
public:
// construct STL exception from legacy exception
LegacyException(const Exception &ex) : std::runtime_error(ex.Message.c_str()) {}
};
try {
// In reality, this throw will happen in some function we have no control over.
throw Exception("Throwing legacy exception!");
} catch (std::exception &ex) {
// Ideally, the compiler would use the LegacyException constructor
// to cast the thrown Exception to a LegacyException, which ultimately
// inherits from std::exception.
std::cout << ex.what() << std::endl;
}
Anlaşılacağı üzere, durum yakalandı hiçbir zaman - bu pek yakalamak için derleyici büyü biraz soran olacaktır.
Eski bir istisnayı sarmak için yukarıdakilere benzer bir çözüm var mı ve bu hedeflere ulaşıyor mu?
- Bir "yakalama" deyimi veya benzeri, genel kural dışı durum mantığının yalnızca bir kez yazılması gerekir.
- Bir özel durum türünden diğerine dönüştürme mantığı merkezileştirilmelidir.
- Mümkünse makroları engeller.
- Lambda işlevleri kullanılmaz.
Lambda işlevleri yok - C++ 11 özelliklerinden kaçınmanızın nedeni nedir? (Ben soruyorum yararlı olmayan lambda C++ 11 özellikleri olduğundan). –
Ayrıca, hangi derleyiciyi hedefliyorsunuz? Microsoft derleyicileri, erişim ihlallerini yakalamak için "catch (...)" özelliğine neden olan bir özelliğe sahiptir, ancak bu özellik VS2005'den beri varsayılan olarak devre dışı bırakılmıştır. Bu gerekçelerle "yakala (...)" seçeneğini çıkarırsanız, seçeneklerinizi daha da azaltırsınız. –
@JoeGauterin: C++ lambda işlevleri derleyicilerden biri tarafından desteklenmiyor, kodum hedefleniyor.Aksi takdirde, bu sorunu çözmek için onları 2 saniye içinde kullanacağım, eğer bu muazzam BCB derleyicisini kabul etmek için ikna edebilirsem: catch (...), daha sonra bir helper işlevini çağır ve std :: exception'u kabul eden bir lambda işlevini ilet. yardımcı. Yardımcı istisnayı yeniden düzenler, çeşitli türleri yakalar ve gerekirse dönüştürür, sonra lambda işlevini çağırır. Çok kötü C++ 11 kullanamıyorum. –