Delphi - сбориник статей

       

Безобидные(?) Hints


Ниже приведен код простой функции, которая не содержит синтаксических ошибок, но при её компиляции будет получено три Hint'а (в коде они отмечены красным). Давайте разберем их подробно.

Function FunctonName( Code : String) : Integer; Var i,j : Integer; ‹—— Variable 'i' is declared but never used in 'FunctonName' Begin j:=0; ‹—— Value assigned to 'j' never used For j:=0 To -1 Do Writeln(j); ‹—— FOR or WHILE loop executes zero times - deleted Result:=StrToInt(Code); End;
Variable 'i' is declared but never used in 'FunctonName' Переменная 'i' определена, но никогда не используется в 'FunctonName' — это одно из самых часто встречающихся сообщений. Чаще всего оно просто говорит о неаккуратном коде. Однако, наличие таких переменных в принципе может означать потенциальную ошибку в реализации алгоритма, ведь зачем-то она была объявлена. Именно поэтому компилятор обращает ваше внимание на эту переменную: вдруг вы просто забыли доделать задуманное?
Простейшее решение — удалить все неиспользованные переменные. А заодно и проверить, действительно ли они не нужны :о)

Value assigned to 'j' never used Значение, присвоенное 'j' никогда не используется. Это сообщение не означает, что программа неправильная — оно означает только то, что компилятор обнаружил, что после присвоения переменной j значения 0, эта переменная не участвует более ни в каких операциях. Что делает это присвоение абсолютно бессмысленным. И, если используется оптимизатор, оно будет удалено в откомпилированном коде.
Так же, как и предыдущий Hint, это сообщение чаще всего является признаком "мусора" в коде, от которого следует избавляться, чтобы не пропустить потенциальные ошибки. Опасность в том, что в реальности может оказаться, что это присвоение было сделано не той переменной, которой нужно. Например, надо было присвоить что-то переменной i, а присвоили j.



FOR or WHILE loop executes zero times - deleted Цикл FOR или WHILE исполняется ноль раз — удалено. Собственно, текст этого сообщения полностью объясняет ситуацию. Конечно же это не специально, это "рука дрогнула", "глаз замылился" или что-то в таком духе. И компилятору остается только сказать спасибо.

Итак, получается, что Hint'ы обращают наше внимание на странности и несуразицы в коде с точки зрения "правильного" компилятора. Конечно, приведенный пример очень прост и надуман и может не убедить вас, но если в коде функции, которая содержит не один десяток операторов, появляется hint, стоит обратить на него внимание, поверьте.

Рассмотренные выше ситуации можно и нужно исправлять. Но бывают случаи, когда нет возможности исправить код так, чтобы не получать Hint's при компиляции. Рассмотрим небольшой пример по созданию собственных классов:

Type TLists = class(TList) Protected procedure Clear; override; ‹—— Overriding virtual method 'TLists.Clear' has a lower visibility (private) than base class (public) End; TExLists = class(TList) Private Function FutureTools(Sender : TObject) : Boolean; ‹—— Private symbol 'FutureTools' declared but never used Public ... End;
Overriding virtual method 'TLists.Clear' has a lower visibility (private) than base class (public) Переопределенный виртуальный метод 'TLists.Clear' имеет видимость ниже, чем в базовом классе Это не то, чтобы ошибка, но на практике понижение видимости свойств и методов класса встречается довольно редко и говорит об ошибках на этапе проектирования базовых классов. Это понижение видимости может создать в проблему в будущем, если от класса TLists будут наследоваться при создании новых классов.

Private symbol 'FutureTools' declared but never used Приватный символ 'FutureTools' определен, но никогда не используется. Это сообщение сродни уже описанному Variable '<name>' is declared but never used...
Так как этот метод приватный, то он по определению не может быть доступен нигде более, как внутри класса. Тем не менее, компилятор там его использования не обнаруживает. Из чего следует естественный вывод, что функция 'FutureTools' нигде не будет использоваться.

Допустим, что в этом случае все не так просто, как это видится компилятору и функция FutureTools, например, нигде не используется вовсе не потому, что вы о ней забыли или она никому не нужна. Возможно это задел на будущее. Можно, конечно, закомментировать и объявление функции и код ее реализации до поры до времени. Но можно сделать и иначе, несколько изящнее.

Возможно, что по условию конкретной задачи понижение видимости метода в классе TLists оправдано, а корректировать код базового класса нет возможности, тогда придется попросить компилятор не принимать во внимание эту ситуацию.

Как раз для таких случаев предусмотрена сцециальная дирректива компилятора: {$HINTS OFF}. Она отключает проверку кода на предмет обнаружения Hint'ов до тех пор, пока в коде не встретится обратная дирректива — {$HINTS ON}. Если в обрамленном этими специальными комментариями коде и будут "опасные" Hint-ситуации, они будут игнорироваться компилятором.

Воспользовавшись этими диррективами, мы получим код, который компилируется не только без ошибок, но и без Hint'ов:

Type {$HINTS OFF} TLists = class(TList) Private procedure Clear; override; End; {$HINTS ON} TExLists = class(TList) Private {$HINTS OFF} Function FutureTools(Sender : TObject) : Boolean; {$HINTS ON} Public ... End;

Примечание:
Не поддавайтесь искушению раз и навсегда "заткнуть" с помощью {$HINTS OFF} упрямый компилятор, пользы от этого вам, как программисту, не будет никакой...



Содержание раздела