Różnica między składnią try-catch dla funkcji

Natknąłem się ostatnio na tę składnię dla try-catch dla funkcji.

struct A
{
  int a;

  A (int i) : a(i)  // normal syntax
  {
    try {}
    catch(...) {}
  }

  A ()   // something different
  try : a(0) {}
  catch(...) {}

  void foo ()  // normal function
  try {}
  catch(...) {}
};

Obie składnie są poprawne. Czy istnieje jakakolwiek techniczna różnica między tymi składniami oprócz stylu kodowania ? Czy jedna składnia jest lepsza od drugiej pod jakimkolwiek względem ?

Author: Alok Save, 2011-07-20

4 answers

Pierwsza Składnia:
Zakres bloku try rozpoczyna się po zakończeniu listy inicjalizacji członka, więc każdy wyjątek wyrzucony podczas inicjalizacji członka nie zostanie przechwycony przez ten blok try-catch.

Druga składnia:
Zapewnia to, że jeśli wyjątek zostanie wyrzucony podczas listy inicjalizacji członka, możesz go złapać.

Trzecia Składnia:
Zapewnia, że każdy wyjątek wyrzucony z betwen nawias startowy bloku try wewnątrz ciała funkcji zostanie odpowiednio przechwycony, oznaczałoby to, że każdy wyjątek spowodowany podczas przekazywania argumentu (jeśli taki może wystąpić) nie zostanie przechwycony w tym bloku try-catch.

Więc tak, są one zupełnie inne w tym, co funkcjonalność zapewniają.


EDIT:
Niektóre wskazówki, które należy wziąć pod uwagę przy użyciu drugiej składni(function-try-block) w konstruktorach i destruktorach:

Zgodnie ze standardem C++ ,

Jeśli blok catch nie rzuca (albo odrzuca oryginalny wyjątek, albo rzuca coś nowego), a kontrola dociera do końca bloku catch konstruktora lub destruktora, wtedy oryginalny wyjątek jest automatycznie retrospektywny.

W prostych słowach:
funkcja konstruktora lub destruktora-try-block ' s handler code musi zakończyć emitując jakiś wyjątek.

Wytyczne 1:
funkcja konstruktora-try-block Obsługa ma tylko jeden cel-przetłumaczyć wyjątek. (I może zrobić logowanie lub jakieś inne skutki uboczne.) Nie są użyteczne w żadnym innym celu.

Rzucanie wyjątków od destruktorów to zły pomysł, Zobacz proszę. żeby wiedzieć dlaczego.
wytyczne 2:
funkcja Destructor-try-bloki w ogóle nie mają praktycznego zastosowania. Nigdy nie powinno być dla nich nic do wykrycia, a nawet jeśli było coś do wykrycia z powodu złego kodu, handler nie jest zbyt przydatny do robienia czegokolwiek z tym, ponieważ nie może tłumić wyjątku.

Wytyczne 3:
Zawsze oczyszczaj niezarządzane pozyskiwanie zasobów w lokalnych procedurach obsługi try-block wewnątrz konstruktora lub destruktora, nigdy w procedurach obsługi konstruktora lub destruktora-try-block.


Dla Standardowych Fanów:

C++ standard, klauzula 15.3, paragraf 15:

Jeśli instrukcja return pojawia się w funkcji obsługi function-try-block konstruktora, program jest źle uformowany.

C++ standard, klauzula 15.3, paragraf 16:

Obsługa wyjątku jest retrospektywna, jeśli kontrola dotrze do końca obsługi bloku function - try-konstruktora lub destruktora. W przeciwnym razie funkcja powraca, gdy kontrolka dotrze do końca obsługi funkcji-try-block (6.6.3). Wypływający z końca bloku funkcji-try-jest równoznaczny ze zwrotem bez wartości; to powoduje nieokreślone zachowanie funkcji zwracającej wartość (6.6.3).


Referencje:
Zajrzyj do tego must read resource proszę. aby uzyskać więcej szczegółów i wyjaśnień.

 44
Author: Alok Save,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-24 12:39:17

Function-try-block jest przydatna głównie w konstruktorach, ponieważ nie ma innego sposobu na przechwytywanie WYJĄTKÓW na liście inicjalizacyjnej. W destruktorach należy uważać, aby powrócić w bloku catch, ponieważ wyjątek zostanie automatycznie ponownie wyrzucony. (A w dobrej konstrukcji destruktory nie mogą rzucać.) W normalnych funkcjach funkcja ta nie jest przydatna. Edit: stary, ale nadal dobry artykuł: http://drdobbs.com/184401316

 9
Author: Gene Bushuyev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-20 05:28:19

Równie dobrze można przytoczyć specyfikację... Lub przynajmniej Projekt .

Sekcja 15 (4):

A function-try-block kojarzy a handler-seq z ctor-initializer , jeśli istnieje, i compound-statement . Wyjątek rzucony podczas wykonywania instrukcji złożonej lub, dla konstruktorów i destruktorów, podczas inicjalizacji lub zniszczenia, odpowiednio, podobiektów klasy, przenosi kontrolę na obsługa w function-try-block w taki sam sposób jak wyjątek rzucany podczas wykonywania try-block przenosi kontrolę do innych programów obsługi.

(tutaj handler-seq jest elementem po catch, a {[1] } jest ciałem funkcji.)

Tak więc "function try block" na konstruktorze lub destruktorze wychwytuje wyjątki rzucane przez inicjatory ctor oraz przez budowę lub zniszczenie podobiektów.

Na funkcji innej niż konstruktor lub Destruktor, jest to to samo, co po prostu zawijanie ciała funkcji. (Cóż, z tego co wiem po przeczytaniu spec.)

Ciekawa funkcja, i nowa dla mnie. Dzięki, że o tym wspomniałeś.

 3
Author: Nemo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-20 04:28:46

Przykład "coś innego"umieszcza przetwarzanie listy inicjalizatorów w obszarze bloku try.

 2
Author: Adam Mitz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-20 04:18:11