C++'da Özel Durumlar ve Yığını Geriye Doğru İzleme
C++ özel durum mekanizmasında denetim, throw deyiminden throw türünü işleyebilen ilk catch deyimine geçer. Catch deyimine ulaşıldığında, throw ve catch deyimleri arasındaki kapsamdaki tüm otomatik değişkenler yığın geri sarma olarak bilinen bir işlemde yok edilir. Yığın geriye doğru izleme işleminde, yürütme aşağıdaki gibi olur:
Denetim, normal sıralı yürütme ile deyimine
try
ulaşır. Bloktakitry
korunan bölüm yürütülür.Korunan bölümün yürütülmesi sırasında özel durum oluşturulursa,
catch
bloğu izleyentry
yan tümceler yürütülür. Yürütme, ilişkilitry
bloğu izleyen soncatch
yan tümceden sonra deyiminde devam eder.Korunan bölümün yürütülmesi sırasında veya korunan bölümün doğrudan veya dolaylı olarak çağırdığı herhangi bir yordamda özel durum oluşursa, işlenen tarafından
throw
oluşturulan nesneden bir özel durum nesnesi oluşturulur. (Bu, bir kopya oluşturucus un dahil olabileceğini gösterir.) Bu noktada derleyici, daha yüksek bircatch
yürütme bağlamında, oluşan türün özel durumunu işleyebilen veya herhangi bir özel durum türünü işleyebilen bir işleyici için bircatch
yan tümce arar. İşleyicilercatch
, blok sonrasındakitry
görünümlerine göre incelenir. Uygun işleyici bulunamazsa, sonraki dinamik olarak kapsayantry
blok incelenmiş olur. Bu işlem, en dıştaki kapalı blok incelenenetry
kadar devam eder.Eşleşen bir işleyici hala bulunamazsa ya da geriye doğru işlem sırasında işleyici denetimi almadan önce bir özel durum oluşursa, önceden tanımlanmış çalışma zamanı işlevi
terminate
çağrılır. Özel durum, geriye doğru izleme başlamadan önce ve bir özel durum oluştuktan sonra oluşursa,terminate
çağrılır.Eşleşen
catch
bir işleyici bulunursa ve değere göre yakalarsa, özel durum nesnesi kopyalanarak resmi parametresi başlatılır. Başvuruya göre yakalarsa, parametre özel durum nesnesine başvurmak için başlatılır. Biçimsel parametre başlatıldıktan sonra, yığını geriye doğru izleme işlemi başlar. Bu, işleyiciyle ilişkili bloğun başlangıcıtry
ilecatch
özel durumun oluşturma sitesi arasında tamamen yapılandırılmış ancak henüz yok edilmeyen tüm otomatik nesnelerin yok edilmesini içerir. Yok etme işlemi oluşturma işleminin ters sırasıyla yapılır. İşleyicicatch
yürütülür ve program yürütmeyi son işleyiciden sonra sürdürür; diğer bir deyişle, işleyicicatch
olmayan ilk deyimde veya yapıda. Denetim bir işleyiciyi yalnızca bir deyimi veya deyimindekiswitch
birgoto
etiket aracılığıyla değil, atılan bircase
özel durum aracılığıyla girebilircatch
.
Yığın geri sarmayı kaldırma örneği
Aşağıdaki örnekte bir özel durum oluştuğunda yığının nasıl kaldırıldığı gösterilmektedir. İş parçacığı üzerindeki yürütme, C
içindeki throw deyiminden main
içindeki catch deyimine atlar ve yol boyunca her işlevi geriye doğru alır. Dummy
nesnelerinin oluşturulduğu ve ardından kapsam dışına çıkarken yok edildikleri sıralamaya dikkat edin. Ayrıca, catch deyimini içeren main
haricinde, hiçbir işlevin tamamlamadığına dikkat edin. A
işlevi B()
için yaptığı çağrıdan, B
işlevi de C()
için yaptığı çağrıdan hiçbir zaman dönmez. Dummy
işaretçisine ve ilişkili delete deyiminin tanımına ilişkin açıklamayı kaldırır ve ardından programı çalıştırırsanız, işaretçinin asla silinmediğine dikkat edin. Bu, işlevler özel durum sağlamadığında neler olabileceğini gösterir. Daha fazla bilgi için bkz . Nasıl yapılır: Özel Durumlar için Tasarım. Catch deyimi için açıklama satırı yaparsanız, işlenmemiş bir özel durum nedeniyle bir program sonlandığında ne olacağını görebilirsiniz.
#include <string>
#include <iostream>
using namespace std;
class MyException{};
class Dummy
{
public:
Dummy(string s) : MyName(s) { PrintMsg("Created Dummy:"); }
Dummy(const Dummy& other) : MyName(other.MyName){ PrintMsg("Copy created Dummy:"); }
~Dummy(){ PrintMsg("Destroyed Dummy:"); }
void PrintMsg(string s) { cout << s << MyName << endl; }
string MyName;
int level;
};
void C(Dummy d, int i)
{
cout << "Entering FunctionC" << endl;
d.MyName = " C";
throw MyException();
cout << "Exiting FunctionC" << endl;
}
void B(Dummy d, int i)
{
cout << "Entering FunctionB" << endl;
d.MyName = "B";
C(d, i + 1);
cout << "Exiting FunctionB" << endl;
}
void A(Dummy d, int i)
{
cout << "Entering FunctionA" << endl;
d.MyName = " A" ;
// Dummy* pd = new Dummy("new Dummy"); //Not exception safe!!!
B(d, i + 1);
// delete pd;
cout << "Exiting FunctionA" << endl;
}
int main()
{
cout << "Entering main" << endl;
try
{
Dummy d(" M");
A(d,1);
}
catch (MyException& e)
{
cout << "Caught an exception of type: " << typeid(e).name() << endl;
}
cout << "Exiting main." << endl;
char c;
cin >> c;
}
/* Output:
Entering main
Created Dummy: M
Copy created Dummy: M
Entering FunctionA
Copy created Dummy: A
Entering FunctionB
Copy created Dummy: B
Entering FunctionC
Destroyed Dummy: C
Destroyed Dummy: B
Destroyed Dummy: A
Destroyed Dummy: M
Caught an exception of type: class MyException
Exiting main.
*/
Geri Bildirim
https://aka.ms/ContentUserFeedback.
Çok yakında: 2024 boyunca, içerik için geri bildirim mekanizması olarak GitHub Sorunları’nı kullanımdan kaldıracak ve yeni bir geri bildirim sistemiyle değiştireceğiz. Daha fazla bilgi için bkz.Gönderin ve geri bildirimi görüntüleyin