Smá trix með exceptions í C++

Ég rakst á þetta C++ exception trix fyrir tilviljun á vefnum um daginn og langar að skrifa örlítið um það, man ekki hvar ég sá þetta. Kannski hefði ég átt að vera búinn að læra þetta fyrir löngu og hugsanlega vita allir almennilegir C++ forritarar af þessu nú þegar.

Exceptions í C++ eru höndlaðar með try-catch klausum.

void foo() {
    try {
        sull()
    }
    catch(const std::exception& ex)
    {
        cout << ex.what() << endl;
    }
}

Eins og sést er þetta tiltölulega einfalt, ef fallið sull sendir frá sér exception sem erfir frá std::exception er hún gripin og prentuð út. Venjulega myndi maður gera eitthvað örlítið meira, en þetta er bara trivial sýnidæmi. Þetta getur maður gert í öllum föllum, operatorum eða smiðum. Maður þarf ekki að senda tilvik af klösum sem exceptions í C++ og í dæmunum hér fyrir neðan notast ég einfaldlega við strengi.

Trixið sem ég sá um daginn felst í því að hægt er að setja try-catch út fyrir fallið, þ.e.a.s. þetta er löglegur C++ kóði.

void foo() 
try
{
    sull()
}
catch(const std::exception& ex)
{
   cout << ex.what() << endl;
}

Með þessari aðferði getum við gripið exceptions sem við gætum annars ekki gripið, t.d. exceptions frá default handlerum í smið member breyta og þess háttar.

class Foo
{
public:
    Foo() { throw std::string("aarrgghhh");}
    Foo(int i) { throw std::string("arrgght, 2");}
    Foo(const std::string str) {;}  // einn smiður sem ekki klikkar
};

class Sull 
{
public:
    Sull();
    Sull(int);
    ~Sull();
private:
    Foo f; // sjálfkrafa er kallað á smið fyrir Foo þegar tilvik af Sull er smíðað
};


// "venjuleg útfærsla á smið - exception er kastað
// "þegar member breytan er smíðuð en villan er
// "ekki gripin hér, þarsem member breytan er smíðuð
// "áður en farið er inn í þennan smið.
Sull::Sull()
{
	try
	{
		cout << "Sull::Sull()" << endl;
	}
	catch(const std::string& villa)
	{
		cout << villa << endl;
	}
}

// try - catch utan um smiðinn - villan er gripin og höndluð hér
// þar sem try -catch nær líka utan um þegar member breytan er smíðuð
Sull::Sull()
try
{
	cout << "Sull::Sull()" << endl;
}
catch(const std::string& villa)
{
	cout << villa << endl;
}

// try - catch utan um smiðinn - kallað á smið fyrir member breytu
// áður en farið er inn í þennan smið
Sull::Sull(int i)
try
: f(i)
{
	cout << "Sull::Sull()" << endl;
}
catch(const std::string& villa)
{
	cout << villa << endl;
}

Sull::~Sull()
try
{
}
catch(const std::string& villa)
{
    cout << villa << endl;
}

Reyndar hunsar Visual Studio exceptions sem er kastað úr destructor, enda er engin einföld leið til að höndla slíkt tilvik, þar sem það getur gerst þegar verið er að vinda ofan af stakknum eftir aðra exception. Skemmtilegt, ekki satt ?

27.01.2004 23:43 c++
Mynd sem Kolla teiknaði af mér

Nýjar athugasemdir

www.flickr.com