C++ имеет непринужденный подход к тому, где переменные области видимости могут быть объявлены или определены. В то время как в C нужно было объявлять все переменные в начале области видимости, в C++ их можно объявлять где угодно по пути, руководствуясь эмпирическим правилом делать это как можно позже. Это более эффективно — подумайте о вызовах конструктора/деструктора, которые вы можете защитить — и увеличивает вероятность того, что вы сможете объявить его const.
Ада делает строгое различие между разделами, в которых разрешены объявления, и разделами, которые могут содержать логику выполнения. В этом смысле это больше похоже на C, что в начале области необходимо делать объявления.
Давайте посмотрим на небольшой пример:
declare I : Integer; begin I := 1; end;
В этом простом случае объявляется переменная I, а затем ей присваивается значение 1.
Но блок declare также позволяет определять переменные (т. е. присваивать им начальное значение).
declare I : Integer := 42; begin I := I / 2; end;
Таким образом вполне возможно выполнять код в блоке declare. И исполняемый код может в конечном итоге привести к возникновению исключения. Затем мы могли бы ввести обработчик исключений, чтобы справиться с этим.
declare I : Integer := Function_That_Might_Raise_An_Exception; begin I := I + 1; exception when E : others => Put_Line (Exception_Information (E)); end;
Выглядит хорошо, но не делает то, что мы хотим. Он будет обрабатывать исключения только из блока begin, но не из этого блока declare. Примечание: I хорошо виден в блоке обработчика исключений.
Чтобы покрыть эти случаи, нужно ввести еще один слой.
begin declare I : Integer := Function_That_Might_Raise_An_Exception; begin I := I + 1; end; exception when E : others => Put_Line (Exception_Information (E)); end;
Это уже сложно читать, и становится еще хуже, когда вы рассматриваете подпрограммы, потому что у них есть декларативный раздел по умолчанию, но нет функционального блока попытки, как в C++.
procedure Foo is -- This declarative block is lost. begin declare I : Integer := Function_That_Might_Raise_An_Exception; begin I := I + 1; end; exception when E : others => Put_Line (Exception_Information (E)); end Foo;
Сравните это со случаями C++:
void Foo try { int i{function_that_might_throw_an_exception()}; i += 1; } catch (std::exception& e) { std::cout << e.what() << std::endl; }
Или это:
try { int i{function_that_might_throw_an_exception()}; i += 1; } catch (std::exception& e) { std::cout << e.what() << std::endl; }
Такие инструменты, как CodePeer, которые могут выполнять глобальный статический анализ программ на языке Ada, должны уметь обнаруживать случаи, когда блок объявления может вызвать исключение, и помечать их, чтобы можно было соответствующим образом разместить обработчики исключений.