Of — Ключевое слово Delphi

Содержание

Что такое ключевое слово inline в delphi

может кто-нибудь сказать, что такое использование встроенного ключевого слова в delphi

Это подсказка компилятору о том, что функция/процедура должна быть (если возможно) встроенной, т.е. когда вы ее вызываете, она должна быть расширена, как макрос, вместо вызова.

Это оптимизация для (очень) малых функций, где накладные расходы на вызов будут значительными. Вы найдете много примеров, например, для windows.pas

Что на самом деле происходит, зависит от сложности функции, открытого/закрытого доступа и версии Delphi.

Он сообщает компилятору генерировать код для встроенного; рутина на том месте, где она называется, вместо того, чтобы прыгать к рутине и обратно.

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

Если процедура слишком длинная, это может быть тормозом при работе, хотя и сильно взорвать ваш код.

Другие ответили, что делает inline, но я просто хотел указать, что есть опция Compiler для установки встроенного, выключенного или автоматического. Ознакомьтесь с «Процедурами и функциями вызова» в документах D2009 для очень хорошего объяснения механики встроенного. Здесь ссылка на онлайн-документы:

Он заимствован из C в том смысле, что он сообщает компилятору, что это короткая подпрограмма, которая часто вызывается, и рекомендует компилятору рассматривать эту функцию как макрос и интегрирует код функции непосредственно в программу в указанной точке, а не используйте вызов функции.

Это дает более быстрый код, поскольку накладные расходы на функциональные вызовы отсутствуют, но за счет более крупной программы. Заметим также, что, как в C, это рекомендация для компилятора, на самом деле это не обязательно, и оптимизатор может переопределить вас.

Где это сделать? Ну, как петля, она разматывает эту технику, которая очень редко используется в наши дни. Классическое место для использования этого — глубокая вложенная структура, которая является критически важной в реальном времени, например, рендеринг кода в графическом приложении, где несколько машинных вызовов, сбритых на каждой итерации, могут увеличить частоту обновления экрана.

Нажмите Ctrl + Alt + C (полное окно отладки CPU) во время отладки в Delphi, прежде чем вызывать свою встроенную функцию. И вы увидите, что встроенные функции запускаются без «вызова» и wo перехода на другой адрес. Это функция оптимизации.

Ключевое слово Delphi

Я изучаю Delphi, читаю книгу Марко Канту, и она супер полная. Это очень ясно, но я сомневаюсь в ключевом слове self . У меня уже есть опыт работы с ООП, и у меня есть основы этого. Мой вопрос очень прост. Можно ли сравнить ключевое слово self (Delphi) с ключевым словом this (Java)?

Когда я прочитал книгу о self используемой внутренней записи, я понял, что-то вроде self : Delphi = this : Java . Посмотрите на код, который я создал для проведения теста:

Я собираюсь отрезать большую часть кода, я просто показываю конструктор здесь:

Используя ключевое слово self здесь, я имею в виду символ записи , а не символ, переданный в методе. Правильно ли это использовать себя? Может ли это быть братом Java this ?

Зарезервированные слова Delphi

var A, B : Integer; begin A:=3; B:=4; A:=A*A+B*B; end;

if (условие) then (действие) else (альтернатива) ;

Слова if (если), then (тогда), else (иначе) — зарезервированные. Действие и else альтернатива — это любые операторы Delphi, или несколько операторов, заключённых в логические скобки begin/end, или вызов подпрограммы. Если условие истинно, то выполняется действие, если ложно, то выполняется альтернатива.

(применяется, когда известно количество повторений цикла)

for счётчик := выражение-1 to выражение-2 do действие ;

Возможна работа оператора цикла, при котором переменная-счётчик будет не увеличиваться, а уменьшаться. В этом случае ключевое слово to заменяется на downto:

for счётчик := выражение-1 downto выражение-2 do действие ;

Цикл с предусловием (применяется, когда неизвестно количество повторений цикла)

while условие do тело цикла ;

Этот цикл будет выполняться до тех пор, пока истинно условие (логическое выражение, возвращающее значение типа Boolean). При этом если это выражение сразу равно false, тело цикла не будет выполнено ни разу. Нужно очень внимательно следить за написанием условия и контролем завершения цикла, так как в результате ошибки цикл while будет повторяться бесконечное количество раз, что приведёт к «зацикливанию» и «зависанию» программы.

Цикл с постусловием

(применяется, когда неизвестно количество повторений цикла)

repeat тело цикла until условие ;

Повторения сначала выполняет тело цикла, а затем уже проверяет выполнение условия: Таким образом, этот вариант цикла гарантирует, что тело цикла будет выполнен по крайней мере один раз. И будет выполняться до тех пор, пока условие не станет истинным (т.е. true). Стоит отметить, что это единственный оператор Delphi, в котором тело цикла не требуется заключать в логические скобки begin/end. Начало и конец тела цикла определяются по ключевым словам repeat и until.

Позволяет изменить последовательность выполнения программы. В качестве метки может использоваться любой допустимый идентификатор или число в диапазоне от 0 до 9999. Метку предварительно необходимо объявить в разделе описания переменных, но с помощью не ключевого слова var, а ключевого слова label:

Of — Ключевое слово Delphi

На текущий момент мы уже умеем создавать приложения Delphi. Тем самым все готово для того, чтобы приступать к изучению языка Object Pascal. Прежде всего, мы ознакомимся с синтаксисом языка — его алфавитом, структурой, ключевыми словами, а так же с правилами составления выражений и типами данных.

Алфавит и словарь языка

В программах Object Pascal могут использоваться любые символы из множества символов языка Object Pascal. К этому множеству относятся буквы латинского алфавита, арабские цифры, пробельные символы, разделители и специальные символы.

Прописные и строчные латинские буквы, а так же знак подчеркивания:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z _

0 1 2 3 4 5 6 7 8 9

Пробельные символы (разделители):

Пробел, табуляция, перевод строки, возврат каретки

Составные символы, образуемые сочетанием двух специальных:

ПРИМЕЧАНИЕ
Все прочие символы, включая символы кириллицы, также могут использоваться в Object Pascal, но только внутри строковых переменных и комментариев.

Последовательности, составленные из знаков алфавита, образуют слова. Слова отделяются друг от друга разделителями и несут в программе определенный смысл. В качестве разделителей могут использоваться как пробельные символы, так и некоторые специальные символы (например, ;), и комментарии. Сами слова можно разделить на такие группы, как ключевые слова; стандартные идентификаторы и пользовательские идентификаторы.

Что касается комментариев, то никакого смысла в программе они не несут, и могут использоваться для того, чтобы разработчик мог вставить пояснительный текст в код программы. Комментарии бывают двух видов — однострочные и многострочные. Для однострочных комментариев обычно используют составной символ «//», помещая его перед текстом самого комментария:

// эта строка полностью закомментирована x=5; // эта часть строки — комментарий

Для многострочных комментариев применяют символы < и >, либо (* и *):

Комментарии разных типов можно вкладывать друг в друга:

С помощью комментариев удобно исключать отдельные инструкции или целые блоки программы в процессе ее отладки.

Ключевые слова

Ключевые, слова являются неотъемлемой частью языка. Все они имеют однозначно определенный смысл, изменить который невозможно. Кроме собственно ключевых слов бывают еще и зарезервированные, т.е. те, которые могут стать ключевыми в последующих версиях языка. Полный список ключевых слов Delphi приведен в таблице 3.1.

Таблица 3.1. Зарезервированные и ключевые слова в Delphi

Слово Слово Слово Слово
absolute export nil requires
abstract exports nodefault resident
and external not resourcestring
array far object safecall
as file of set
asm finalization on shl
assembler finally or shr
at for out stdcall
automated forward overload stored
begin function override string
case goto package then
cdecl if packed threadvar
class implementation pascal to
const implements private try
constructor in procedure type
contains index program unit
default inherited property until
destructor initialization protected uses
dispid inline public var
dispinterface interface published virtual
div is raise while
do label read with
downto library readonly write
dynamic message record writeonly
else mod register xor
end name reintroduce
except near repeat

Важно запомнить, что данные слова можно использовать только по их прямому назначению. Соответственно, вы не можете создавать какие-либо собственные идентификаторы (например, названия переменных), таким образом, чтобы если они совпадали с каким-либо ключевым словом.

Переменные и константы

Если ключевые слова имеют заранее предопределенный смысл, то значения констант и переменных определяет программист. Но прежде, чем приступить к исследованию констант и переменных, рассмотрим знак, используемый для некоторых операций, поскольку без этого невозможно дальнейшее продвижение. Речь идет о знаке равенства (=), который используется в Delphi в двух значениях — как оператор присваивания и как оператор сравнения.

В случае применения в качестве оператора присваивания, знак равенства используется совместно с символом двоеточия и имеет следующий общий синтаксис:

При присваивании используется 2 операнда, при этом подразумевается, что левому операнду (переменной) будет присвоено значение правого. Такая запись называется выражением.

ПРИМЕЧАНИЕ
Более точно выражение можно определить следующим образом: выражение — это набор данных, переменных, операторов и других выражений, которые приводятся к общему значению.

Другой вариант — это использование знака равенства для сравнения 2 операндов. В таком случае он используется самостоятельно:

Такая запись означает, что сравниваются левое (операнд1) и правое (операнд2) значения выражения. Однако специально для констант предусмотрен третий вариант, при котором константе присваивается значение правого операнда (как в случае обычного присваивания), но используется знак равенства без двоеточия:

Таким образом, мы переходим к самим константам и переменным, и начнем мы с констант, как наиболее типичного примера подстановки.

Суть использования констант состоит в том, что вместо какого-либо явного значения указывается его условное обозначение — константа. Допустим, что вы пишете программу, в которой неоднократно следует вычислять НДС. Разумеется, вы можете использовать в выражениях явное значение — 0.18 (18%). Но скорее всего, в программе найдется несколько мест, где в вычислениях требуется значение НДС. Таким образом, если НДС в очередной раз изменят, то вам придется отыскивать в программе все эти строки и вносить правку. В таких случаях на помощь приходят константы — достаточно один раз ее определить, а затем во всех тех местах, где требуется ее значение, указывать имя константы.

Определяются константы при помощи ключевого слова const (от англ. constant):

Теперь во всех выражениях, где требуется значение НДС, просто используется эта константа:

VATsumm := price * VAT;

В этом выражении задействована константа VAT и 2 переменных — VATsumm, которой присваивается значение, и price, которая используется для его вычисления. Впрочем, price в данном случае тоже может быть константой, в отличие от VATsumm. Дело в том, что константы определяются в момент написания программы, а при компиляции в код автоматически подставляются их действительные значения. Соответственно, для вычисляемых значений, равно как и для значений, которые может вводить пользователь, нужны не константы, а переменные. Так, если бы константа VAT была переменной, то можно было бы предусмотреть в программе опцию изменения значения НДС.

Переменные определяются при помощи ключевого слова var (от англ. variable):

Обратите внимание, что для переменных нужно указывать не только ее имя, но и тип данных. Собственно говоря, константы тоже получают тот или иной тип данных, только это происходит автоматически, в момент компиляции. Так что рассмотри типы данных, предусмотренных в Object Pascal.

ПРИМЕЧАНИЕ
Начиная с Delphi 4, в Object Pascal поддерживаются типизированные константы, значения которых можно изменять по ходу выполнения программы. Объявление констант такого типа производится следующим образом: «const : тип = значение». От обычных переменных они отличаются различиями в обработке компилятором, а так же тем, что для них всегда имеется какое-либо предопределенное значение.

Типы данных

Прежде, чем приступить к рассмотрению типов данных, постараемся понять, для чего это вообще надо. Прежде всего, Object Pascal, равно как и его предшественник — язык Pascal, а так же C и C++ относятся к строго типизированным языкам программирования. Типизированные языки, в отличие от нетипизированных (начиная с BASIC и заканчивая различными языками сценариев вроде JavaScript), имеют то преимущество, что уже на этапе синтаксической проверки кода компилятор не допустит заведомо неверных операций. К примеру, вы не сможете сложить строку с числом. Кроме того, типизация положительно сказывается на быстродействии программ: благодаря тому, что компилятор заранее «знает», что за данные ему следует обработать в каждом конкретном случае, он может подбирать оптимальные инструкции при генерации машинного кода.

Теперь рассмотрим собственно типы данных, имеющиеся в Object Pascal. Прежде всего отметим, что они бывают простыми (числа, символы), структурными (массивы, записи), процедурными и вариантными. Знакомство со структурными и процедурными типами мы отложим до соответствующей главы, а пока что перечислим категории простых типов данных:

  • Целочисленные (Integer);
  • Вещественные (Real);
  • Булевы (Boolean);
  • Символьные (Character);
  • Строковые (String).

Практически в каждой категории имеется несколько типов данных. В свою очередь это так же вызвано необходимостью более эффективного использования ресурсов компьютера. Например, если для какой-то переменной достаточно диапазона значений от 1 до 100, то зачем для нее выделять память, достаточную для хранения миллиардных значений? Так что начнем подробное с целочисленных типов, как наиболее простых и наглядных.

Всего в современных версиях Delphi предусмотрено 7 различных типов данных для целых чисел, все они приведены в таблице 3.2.

Таблица 3.2. Типы целочисленных данных

Тип Диапазон Байт (бит) памяти Отрицательные значения
Byte от 0 до 255 1 (8) Нет
ShortInt от -128 до 127 1 (8) Да
Word от 0 до 65535 2 (16) Нет
SmallInt от -32768 до 32767 2 (16) Да
LongWord от 0 до 4294967295 4 (32) Нет
LongInt от -2147483648 до 21474483647 4 (32) Да
Int64 от -9223372036854775808 до 9223372036854775807 8 (64) Да

ПРИМЕЧАНИЕ
Здесь следует сразу оговориться про понимание памяти в программировании. Так, память считают в байтах. Каждый байт состоит из 8 бит. Бит — это минимальная единица информации, бит может принимать только 2 значения, 0 или 1. Каждая переменная, в зависимости от типа, занимает то или иное количество байт в памяти. Отметим так же, что 2 байта образуют слово (word), а 4 байта — двойное слово.

Помимо перечисленных основных типов, в Delphi имеется еще 2 автоматических целочисленных типа — Integer и Cardinal. Первое, в типичном случае, является синонимом для LingInt, хотя может быть приведено и к типу Int64. Например, если объявит переменную типа Integer и попробовать записать в нее значение, превышающее максимально допустимый размер для типа LongInt, то она автоматически преобразуется в Int64:

var x: integer; . x: = 21474483647; // здесь x имеет тип LongInt x: = x + 1;

Что касается Cardinal, то это — устаревшее определение для LongWord, вы сможете встретить его, если будете просматривать исходные коды, написанные во времена первых версий Delphi. Самым распространенным на практике целочисленным типом данных является Integer.

Перейдем к вещественным типам. Для них так же предусмотрены фиксированные типы (правда, в отличие от целочисленных, их не 7, а 6), и один автоматический. Рассмотрим основные типы в таблице 3.3.

Таблица 3.3. Типы вещественных данных

Тип Диапазон Байт памяти Точность
Real48 от ±2.9*10^-39 до 1.7*10^38 6 11.дек
Single от ±1.5*10^-45 до 3.4*10^38 4 07.авг
Double от ±5.0*10^-324 до 1.7*10^308 8 15-16
Extended от ±3.4*10^-4951 до 1.1*10^4932 10 19-20
Comp от -2^63+1 до 2^63 -1 8 19-20
Currency от -922337203685477.5808 до 922337203685477.5807 8 19-20
Илон Маск рекомендует:  Сайт на php с базой данных и админкой

Имеется так же и автоматический тип — Real, введенный для совместимости с программами, написанными в Delphi 2 или 3. Сейчас тот тип, что был в ранних версиях Delphi, называется Real48 и практически не используется. Вместо него рекомендуется использовать такие типы, как Single или Double. Если же задать тип Real в программе, то он будет автоматически приведен к типу Double.

Нечто подобное можно сказать и про тип Comp — этот 64-разрядный вещественный тип данных изжил себя с момента появления целочисленного типа Int64, и присутствует лишь в целях совместимости со старым программным кодом.

Зато тип Currency активно используется, особенно при работе с базами данных. Как следует из его названия (Currency — валюта), данный тип предпочтительно использовать для финансовых расчетов. И хотя Currency относится к вещественным типам данных, компилятор обращается с ним как с целым, что позволяет добиться меньших ошибок при округлениях.

В целом, что касается целых и вещественных типов, достаточно запомнить всего две вещи: вещественным типам данных можно присваивать любые численные значения, а целочисленным — только целые:

var x: integer; y: double; . x := 5; y := 5.25; // обратите внимание, что дробная часть отделяется точкой y := x + y; // так делать можно x := x + y; // а так — нельзя, поскольку результатом должно быть целое

Булевы, или логические типы данных представлены в Delphi типами Boolean, ByteBool, WordBool и LongBool. Все они отличаются только размером памяти, выделяемым для хранения значения, причем значений может быть только 2 — false (ложь) и true (истина):

var x, y: Boolean; . x := true; y := false;

Основным типом является 1-байтовый Boolean (он же ByteBool), 2-байтовый WordBool и 4-байтовый LongBool предусмотрены лишь для совместимости в целях взаимодействия с другими языками и платформами.

Что касается символьных типов данных, то в Delphi предусмотрено 2 их типа — ANSIChar и WideChar. Первый является однобайтовым и может хранить в себе 1 символ из множества символов ANSI, коих насчитывается 256. Второй же тип является 2-байтовым и предназначен для хранения 2-байтовых же символов Unicode. Как и в других случаях, Delphi имеет синоним для символьных типов — Char, который на сегодня является аналогом ANSIChar. Что касается присвоения значений, то обычные символы (буквы и цифры) присваивают переменным символьного типа как есть, лишь заключая их в одиночные кавычки. А специальные символы, например, возврат каретки (Enter) назначают при помощи их номера в таблице ANSI, и выделяют знаком решетки:

var x, y: Char; // x и y получают тип ANSIChar . x := a; // обычные символы y := #13; // возврат каретки в таблице ANSI имеет номер 13

Наконец, еще одним, причем, в общем-то, уже не совсем простым типом данных являются строки. Строковые типы данных отличаются от символьных тем, что могут хранить не единичный символ, а множество символов. В Delphi имеется 3 типа строк: ShortString, AnsiString и WideString. Первый тип строк — ShortString — достался в наследство от языка Pascal и 16-битной Delphi 1.0. Такие строки могут иметь не более 255 символов, и занимают от 2 до 256 байт памяти, в зависимости от размера: Что касается современных строковых типов — AnsiString и WideString, то они могут иметь практически неограниченную длину (AnsiString — до 2 млрд. символов, WideString — до 1 млрд.) и занимать, соответственно, от 4 байт до 2 Гигабайт памяти. При этом по аналогии с символьными типами, тип AnsiString предназначен для хранения обычных строк, а WideString — для строк в формате Unicode. Ну и еще один тип строк — String является синонимом для типа AnsiString:

var str1: ShortString; // короткая строка var str2: AnsiString; // длинная строка var str3: String; // тоже длинная строка . str1 := Начало.; // Строковые значения заключаются в одинарные кавычки str2 := Конец.; str3 := str1 + str2; // получим длинную строку, содержащую Начало.Конец.

В целом, несмотря на кажущееся разнообразие типов данных, на практике чаще всего ограничиваются всего лишь 5-6 основными типами. Это: Integer, Double, Boolean, Char, String, и иногда — еще и Currency.

Данные и значения

Очевидно, что сами по себе типы данных ничего не означают. Главное их предназначение — хранить те или иные значения, или данные. Так, для хранения числовых данных применяют целочисленные или вещественные типы, в зависимости от того, какого типа числа следует использовать. На практике это означает, что будут применяться типы Integer и Double.

ПРИМЕЧАНИЕ
Хотя вещественные типы и являются более универсальными, использовать их надо только при реальной необходимости, поскольку они гораздо менее удобны компьютеру для вычислений. Говоря конкретнее, математические операции над вещественными числами выполняются гораздо медленнее, чем над целыми, а ряд иных операций (например, побитовые, инкремент или декремент) вообще недопустимы.

Строковые данные требуют для своего хранения строковых же типов, т.е. String. Исключение может составить тот случай, когда следует сохранить один и только один символ — в таком случае предпочтительно (а иногда — необходимо) использовать тип Char. Ну а в том случае, если требуется привести какое-то значение к однозначному выводу, используют логический тип Boolean. Например, если сравнивать одно число с другим на предмет того, является ли оно больше, то результатом сравнения будет либо «да», либо «нет», т.е. true или false:

var x: boolean; . x := 5 > 6; // получаем false, т.к. 5 не больше 6

Важно отметить, что переменные одного типа могут хранить данные только такого же типа. Кроме того, произведение каких-либо манипуляций над данными возможно только в том случае, если они относятся к одной категории. Исключение составляют разве что такие пары, как строки-символы и вещественные-целые числа. При этом результирующая переменная должна иметь тип строки для первой пары и вещественного числа — для второй. Впрочем, подробнее все это будет рассмотрено в контексте операций языка Object Pascal.

Операции и их типы

В любом языке программирования имеются знаки операций. Кроме того, некоторые ключевые слова, например такие, как div или mod также обозначают операции. Все операции в Object Pascal можно разделить на следующие типы: логические, арифметические, логические, операции присвоения и отношения, а так же специальные операции. Для их обозначения используются математические символы или ключевые слова. Участвующие в операциях значения (переменные) называются операндами. При этом та или иная операция может работать с операндами определенного типа. А результатом может быть данные как такого же типа, та и другого (например, для того же сравнения).

Начнем ознакомление с арифметических операций, как наиболее распространенных (не только и не столько в программировании, сколько в реальной жизни). С полным их перечнем, а так же с типами исходных и результирующих данных можно ознакомиться в таблице 3.4.

Таблица 3.4. Арифметические операции

Операция Название, тип Описание Операнды Результат
+ Сложение, бинарная Возвращает сумму левого и правого операндов integer, real integer, real
Вычитание, бинарная Возвращает разницу левого и правого операндов integer, real integer, real
* Умножение, бинарная Возвращает произведение левого операнда на правый операнд integer, real integer, real
/ Деление, бинарная Возвращает результат деления левого операнда на правый операнд. Результат может быть дробным integer, real real
mod Остаток от деления, бинарная Возвращает остаток от деления левого операнда на правый операнд integer integer
div Деление нацело, бинарная Возвращает целую часть числа, получившуюся в результате деления integer integer
Унарный минус Возвращает число, противоположное операнду integer, real integer, real
+ Унарный плюс Явно указывает знак числа integer, real integer, real

Можно отметить, что практически для всех арифметических операций результатом будут данные того же типа, что и операнды. Единственное исключение — это операция деления, результатом которой всегда будет вещественное число.

Другой распространенный тип операций — логические. В Object Pascal имеются все 4 типа логических операций: не, и, или, исключающее или (таблица 3.5).

Таблица 3.5. Логические операции

Операция Название Описание
not Логическое отрицание (НЕ) Возвращает false, если выражение может быть приведено к истине, в противном случае возвращает true
and Логическое (И) Возвращает true, когда оба выражения истинны. В противном случае возвращает false
or Логическое (ИЛИ) Возвращает true, когда хотя бы одно из выражений истинно. В противном случае возвращает false
xor Логическое (исключающее ИЛИ) Возвращает true, когда только одно из выражений истинно. В противном случае возвращает false

Варианты возвращаемых значений для логических операций приводятся ниже:

not true // возвращает false not false // возвращает true true and true // возвращает true true and false // возвращает false false and false // возвращает false true or true // возвращает true true or false // возвращает true false or false // возвращает false true xor true // возвращает false true xor false // возвращает true false xor false // возвращает false

Логическому сравнению подлежат не только булевские значения, но и любые другие выражения, которые могут быть к ним приведены. Например, выражение «3=4» может быть использовано в качестве логически сравниваемой единицы, поскольку результатом его оценки будет булево значение ложь (false).

Те же самые знаки операций, что используются в логических операциях, задействованы и в другом типе операций — побитовых. Побитовые операции выполняются над числами, представленными в двоичном виде (т.е. только нули и единицы). Однако сами операнды могут быть десятичными, шестнадцатеричными, или восьмеричными целыми числами. Например, десятичное число 5 представляется как двоичное 101, десятичное 6 — как 110, а шестнадцатеричное F3 — как двоичное 11110011.

Хотя побитовые операции выполняются над двоичными данными, возвращаемые значения являются стандартными числами. Список всех побитовых операций приводится в таблице 3.6.

Таблица 3.6. Побитовые операции

Операция Название Описание
and Побитовое И Возвращает число, являющееся результатом побитового сравнения «И»
or Побитовое ИЛИ Возвращает число, являющееся результатом побитового сравнения «включающее ИЛИ»
xor Побитовое исключающее ИЛИ Возвращает число, являющееся результатом побитового сравнения «исключающее ИЛИ»
not Побитовое НЕ Возвращает число, с битами, расположенными в обратном порядке
shl Сдвиг влево Сдвигает первый операнд влево на число разрядов, заданных вторым операндом. Освобождающиеся правые биты заполняются нулями
shr Сдвиг вправо Сдвигает первый операнд вправо на число разрядов, заданных вторым операндом. Освобождающиеся левые биты отбрасываются

Чтобы явно представить себе, как работают побитовые операции, обратимся к следующему примеру. Допустим, имеется 2 переменных — x и y:

var x, y: integer; . x := 3; y := 5;

В двоичном представлении число 3 будет выглядеть как 0011, а 5 — как 0101. Теперь посмотрим, какие результаты даст каждая из побитовых операций сравнения и операции отрицания над этими числами:

x or y // Получим 7: 0011 | 0101 = 0111 x and y // Получим 1: 0011 & 0101 = 0001 x xor y // Получим 6: 0011 ^ 0101 = 0110 not x // Получим 12:

Что касается операций побитового сдвига, то они дадут следующие результаты:

y shl 2 // Получим 20: 0101 shl 2 = 10100 y shr 2 // Получим 1: 0101 shr 2 = 01 -y shr 2 // Получим -2: -0101 shr 2 = -10

Теперь нам остается исследовать еще один тип операций — операции сравнения. Эти операции всегда требуют наличия двух операндов: они сравнивают значения левого и правого операндов, и возвращают результат сравнения в виде логического значения, которое может принимать значение false или true (ложь или истина). Все имеющиеся в Object Pascal операции сравнения приведены в таблице 3.7.

Таблица 3.7. Операции сравнения

Операция Название Описание Пример, дающий true
= Равно Возвращает истину (true), когда левый и правый операнды равны. 1=1
<> Не равно Возвращает истину, когда левый и правый операнды не равны. 1<>2
> Больше Возвращает истину, когда левый операнд больше правого. 2>1
= Больше или равно Возвращает истину, когда левый операнд больше правого или равен ему. 1>=0; 1>>1
var x: Char; z: Boolean; . x := ‘b’; z := x in [a..d];

В данном случае в качестве результата (z) мы получим истину, поскольку символ b является членом указанного множества [a..d], в которое входят символы a, b, c и d. Наконец, в Object Pascal имеется еще 2 операции — as и is. Они служат для приведения типа и проверки типа, соответственно. Например, если мы хотим проверить, является ли некая переменная «x» целым, то можно написать такое выражение:

b := x is Integer; // b получит значение true, если x — целое

Ну а операция as используется для приведения данных одного типа к другому, причем, преимущественно, при работе с объектами:

При использовании операции as следует быть осторожным, поскольку приведение одного типа к другому возможно далеко не всегда.

Выражения и приоритет операций

Как нам уже известно, выражения — это, прежде всего, набор данных, переменных и операторов. Развивая это определение, можно сказать, что выражения состоят из значений и операций над ними, например:

a := b + c; d := e * f; g := a — d div 2;

Так же, как и в обычной математике, при составлении выражений в Object Pascal, следует учитывать приоритет выполнения операций. Например, операции умножения или деления должны выполняться раньше, чем сложение и вычитание. Так, в 3-й строке из приведенных выше примеров выражений, согласно математическим правилам, сначала выполняется операция деления нацело (d div 2), затем результат этой операции вычитается из a, и итоговое значение присваивается переменной g. Все те же правила действуют и в программировании, но поскольку перечень операций не ограничивается арифметическими, а в рамках одного выражения могут быть использованы различные типы операций, то было бы неплохо внести полную ясность в этот вопрос.

Прежде всего, приоритет выполнения определяется принадлежностью конкретной операции к тому или иному типу. Так, первыми выполняются унарные операции, затем — операции умножения (включая деление и побитовые), далее обрабатываются сложение и вычитание (опять, таки включая побитовые or и xor), и, наконец, в последнюю очередь — операции отношения. Для удобства представим все операции, классифицированные по уровню приоритета, в виде таблицы (табл. 3.8).

Таблица 3.8. Приоритет выполнения операций

Операторы Уровень приоритета Категория
@, not Высший Унарные
*, /, div, mod, and, shl, shr, as Высокий Умножение
+, -, or, xor Средний Сложение
=, <>, >, =, in, is Низкий Отношение

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

И нам требуется сначала выполнить вычитание, то достаточно заключить участвующие в операции вычитания операнды в круглые скобки:

Таким образом, сначала здесь из a вычитается d, и лишь затем производится операция деления нацело.

Структура программы

Теперь, когда мы уже знаем об основных языковых конструкциях языка — «словах» (ключевые слова, переменные, операторы и т.д.) и выражениях, рассмотрим, как все это объединяется в общий код программы.

Итак, программа состоит из: заголовка, за которым следуют список подключаемых модулей, объявления меток, констант, типов данных и переменных, описания процедур и функций. Вслед за этой заголовочной частью располагаются собственно программные инструкции. На практике все это выглядит таким образом:

program ; uses ; label ; const ; type ; var ; ; begin ; end.

В структуре той или иной программы часть этих разделов может быть опущена за ненадобностью. Обязательными являются всего 3 ключевых слова — program (вместе с названием), а так же begin и end. Разумеется, между begin и end должны находиться какие-либо инструкции. Так, возвращаясь к примеру «Hello, World», в нем можно обнаружить лишь название программы и блок инструкций:

program hello; // название <$APPTYPE CONSOLE>//это указание компилятору к коду программы не относится begin // начало исполняемого кода write(Hello, World!); // инструкции readln; end. // конец программы

ПРИМЕЧАНИЕ
Список модулей в данном случае не нужен, поскольку мы не используем никаких дополнительных функций или процедур из библиотеки Object Pascal. Но, разумеется, в более сложных программах они могут понадобиться.

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

Рассмотренная нами структура характерна для программ на Pascal в целом, в том числе и для Windows-приложений, разрабатываемых визуальными средствами. Структура же отдельных модулей, представляющих собой описание того или иного окна, имеет ряд отличий. В общих чертах ее можно представить следующим образом: начинается такой модуль с ключевого слова unit, после которого следуют секции interface и implementation. Иногда могут быть также использованы еще 2 секции — initialization и finalization. Ну а завершается все это, разумеется, ключевым словом end с точкой:

unit ; interface implementation ; initialization ; finalization ; end.

При создании новых форм в среде Delphi весь необходимый код создается автоматически, разве что опциональные (и довольно редко используемые на практике) секции загрузки или завершения, при необходимости, придется дописывать самостоятельно.

Завершая эту тему, затронем еще один аспект структуры программ — подпрограммы. В качестве подпрограммы понимается блок инструкций, предназначенный для решения какой-либо частной задачи в рамках самой программы. Такие блоки в Object Pascal могут просто выполняться — в таком случае они называются процедурами, либо выполняться и возвращать какой-либо результат — в таком случае они называются функциями. И в том, и в другом случае, они могут принимать какие-либо значения для обработки. Эти значения называются аргументами. В целом же синтаксис обращения к процедуре или функции выглядит следующим образом:

Подробнее об этом будет рассказано в соответствующей главе, пока же отметим для себя сам факт их существования, поскольку очень скоро нам придется столкнуться с рядом процедур и функций, реализованных в самом языке Object Pascal.

Of — Ключевое слово Delphi

В первую очередь пошел искать в хелпе, не нашел (хотя узнал много интересного ^^), в яндексе тоже глухо. В книжках по делфи, которые мне попадались о сабже тоже нет упоминаний. Итак, что же делает ключевое слово «object»? Ссылки на документацию приветствуются, но и ответом «своими словами» не побрезгую.

ЗЫ В общем-то, какой-то конкретной цели не преследую, просто для повышения образованности.

Это устаревший способ работы с самодельными объектами. Теперь гораздо целесообразнее использовать class

> Это устаревший способ работы с самодельными объектами

Моё любопытсво все еще не удовлетворено :). Чем object отличается от class, что именно устарело. Попадался мне как то код с этим волшебным словом, так что хотелось бы понять что это из себя представляет.

Идеальное слово для описания всего.

Даже для искуственного интелекта.

> Desdechado © (03.03.07 17:06) [1]
> Это устаревший способ работы с самодельными объектами. Теперь гораздо целесообразнее использовать class

В Делфях классом считается все, что прождено от TObject. Но проблема в том, что нужно было объявить сам TObject в юните «system.pas», для чего и использовали ключевое слово языка Паскаль object. Ключевое слово class не является зарезервированным словом языка Паскаль, хотя поддерживается и зарезервировано сейчас почти всеми компиляторами (Delpi, FPC, Lazarus, Kylix, TNT).


> Чем object отличается от class, что именно устарело

object в общем-то позволяет создать статический объект. Подробнее о нем ты лучше прочитай в любом руководстве по Турбо-Паскалю 5.5-7.0, с тех пор ничего не изменилось. В Delphi object только для совместимости и поддерживается

Руководство щас погуглю.
А под статическим объектом понимается объект, все методы которого статические? А конструктор с деструктором присутствуют? (=

Servelat © (03.03.07 17:19) [6]
нет просто память под такой объект выделяется статически, то есть при загрузке программы в память, а не когда программист соизволит

> PEAKTOP © (03.03.07 17:14) [4]
TObject = class;
T >
купи «твикс». жуй. молчи. заодно почитай материалы по Object Pascal (тому, из которого упёрли концепцию обёектов в Turbo Pascal 5.5).

Собственно, вопрос закрыт; нашел у себя на винте UserGuide по BP70 (что прям удивительно, на русском), где тема полностью раскрыта, просвещаюсь. Всем спасибо за ответы.

Удобен тем, что содержит в себе идеи ООП (наследование) и не требует лишней работы и памяти. Посмотри, сколько всего делается и создается в конструкторе TObject! Если мне нужно будет использовать сотню-другую тысяч объектов, то выбор будет за object»ами, а не за классами, наверное.

> Если мне нужно будет использовать сотню-другую тысяч объектов,
> то выбор будет за object»ами, а не за классами, наверное.

Так и до record»a дойти не долго :))

> Ketmar © (03.03.07 17:34) [8]

> Loginov Dmitry © (03.03.07 18:58) [11]

Структурное программирование рулит. Я серьезно.


> Посмотри, сколько всего делается и создается в конструкторе
> TObject! Если мне нужно будет использовать сотню-другую
> тысяч объектов, то выбор будет за object»ами, а не за классами,
> наверное.

Гм. Наверное наооборот :-) class как раз под такие случаи и заточен :-)

> tesseract © (03.03.07 20:52) [14]

На пустых объектах/классах поэкспериментировал, 100000000 TObject»ов создано за 19 секунд и использовано 720 метров памяти, столько просто обджектов — за ноль секунд и использовано памяти метр с копейками. Если объекты буду содержать какие-то данные и выполнять какие-то действия, то и на сотне разницу почуствуем.

> использовано памяти метр с копейками

Сами-то в это верите?

> Если объекты буду содержать какие-то данные и выполнять
> какие-то действия, то и на сотне разницу почуствуем.

Или эта разница просто-напросто исчезнет.

> Сами-то в это верите?

Четырехзначная цифирь, начинается на один .

to PEAKTOP © (03.03.07 17:14) [4]:
Что за трава? Или это были грибы? :)))

to TUser © (03.03.07 21:04) [15]:
>На пустых объектах/классах поэкспериментировал
Угу, а производительность будем на «Hello, World!» мерять. :)
Пустой object занимает 0 байт, в отличие от наследника TObject, который занимает 4 минимум байта.

>Если объекты буду содержать какие-то данные и выполнять какие-то
>действия, то и на сотне разницу почуствуем.
Фиг. Если в object будет поле, допустим integer, вес уравняется. Преимуществ не будет почти никаких. При одинаковом количестве полей будут те самые 400 байт на сотне.

И вообще, что-то цифры подозрительные. Что там в коде-то?

TUser © (03.03.07 21:04) [15]

Тут такой момент — пустые объекты, как и пустые классы никому не нужны. Давай ты полные насоздаешь ?

33 секунды для объектов vs минута думанья и Out of memory в случае классов :) Объекты и классы содержали по два поля типа integer + то, что от TObject. Говорю же — объекты (те, которые экземпляры классов) память любят кушать. Больше, чем объекты, которые просто, т.е. типа record с наследованием.

> Говорю же — объекты (те, которые экземпляры классов) память
> любят кушать. Больше, чем объекты, которые просто, т.е.
> типа record с наследованием.

Ай-ай! Какая беда! 100000000 объектов всю память скушали!
Только нюансик один: что вообще в принципе можно делать с таким количеством объектов? Их же надо где-то индексировать (в массиве там, или в списке), это еще 400 метров памяти надо. Нужен метод доступа, поиска и т.п., что при таком количестве объектов (будь то object или class) будет выполняться катастрофически долго.
То есть пример со 100000000 объектов выглядет очень уж надуманным.

to TUser © (04.03.07 04:27) [21]:
>Говорю же — объекты (те, которые экземпляры классов) память любят
>кушать. Больше, чем объекты, которые просто, т.е. типа record с
>наследованием.
А вот мои подсчеты говорят, что памяти в результате понадобится одинаковое количество. Догадываетесь, почему? А времени, тут да, создание экземпляра класса требует чуть больше, т.к. экземпляру класса требуется инициализация, а у object её по-умолчанию нет, но это опять же, до тех пор пока там данных в нормальном количестве нет.

Поэтому еще раз говорю, что-то там не то с методикой. Код в студию.

Чтобы вопросов не возникало:

uses
SysUtils,
Windows;

type
Cls = class
a,b: integer;
end;

PObj = ^Obj;
Obj = object
private
a,b: integer;
end;

procedure AllocCls(count: integer);
var
i: integer;
begin
for i := 0 to Count — 1 do
Cls.Create;
end;

procedure AllocObj(count: integer);
var
i: integer;
o: PObj;
begin
for i := 0 to Count — 1 do
new(o);
end;

var
T1, T2, T3: Cardinal;
S1, S2, S3: Cardinal;
begin
T1 := GetTickCount;
S1 := GetHeapStatus.TotalAllocated;
AllocCls(10000000);
S2 := GetHeapStatus.TotalAllocated;
T2 := GetTickCount;
AllocObj(10000000);
S3 := GetHeapStatus.TotalAllocated;
T3 := GetTickCount;
writeln(Format(«%d %d», [T2-T1, S2-S1]));
writeln(Format(«%d %d», [T3-T2, S3-S2]));
readln;
end.

Результат (CoreDuo 6600 2.4 ГГц, RAM 2ГБ):
500 120000000
109 120000000

Памяти требуют оба варианта, что естественно для данного случая, одинаково, несмотря на разницу в размерах экземпляров. А чем разница во времени обусловлена — см. выше.

Но проблема в том, что нужно было объявить сам TObject в юните «system.pas», для чего и использовали ключевое слово языка Паскаль object

О как. Оказывается, object использовали для создания class. Вот так и возникают религии. Хвала всевышнему, объект придумавшему, ибо класс и экземпляр класса — суть порождение его. Во имя object, class и instance его! Аминь.

Я, наверное, еретик. бо у меня возник вопрос, откуда же в таком случае взялся сам object :0)

и если от record»а, то откуда взялся record? и так далее. )

to Virgo_Style © (04.03.07 12:29) [26]:
>откуда взялся record?
record был всегда :)

record придумал Вирт, а Вирта придумали мама с папой. выводы очевидны :)

хех
неужто настолько делать нефига людям что ещё не влом думать о такой архаике как object:)

> PEAKTOP © (03.03.07 19:03) [12]
расслабься. приведённый мной код — цитата из system.pas. советую перед тем, как вещать, таки читать генофонд. ну и — да, язык, о котором вещаешь, тоже выучить бы не помешало.

>>неужто настолько делать нефига людям что ещё не влом думать о такой архаике как object:)
что за наезды на обжект? фундаментальная штука. это класс придумка борланда, насколько помню в стандарте паскаля нет такого словечка:)

object — это отнюдь не архаика.

Во-первых, без слова object затруднительно определить callback типа

type
TForProgressBar = procedure(Current, Total: Integer) of object;

Это, ясное дело, очень мощное и «современное» средство, не реализованное, к примеру, в С++. Там аналог убогий.

Во-вторых, object позволяет создавать «интеллектуальные записи» (с методами), которые к тому же обладают свойством наследования. В некоторых диалектах С я встречал это свойство «наследования» с применением анонимных структур.

> просто так (04.03.07 14:07) [32]
я-таки скажу откровение: в том стандарте и object ни разу нет.


> я-таки скажу откровение: в том стандарте и object ни разу
> нет

да, точно ))), но класс развитие обжекта, причем не всегда удобное, и объявлять обжект устаревшим неправильно, для небольших структур данных он подходит гораздо больше чем класс

_uw_ (04.03.07 14:08) [33]
ну я не про все применения ключевого слова object, а именно про то применение которое оставлено для совместимости

в .NET структуры наделённые свойствами ООП юзаются порой в качестве «легковесных» объектов ибо для них в стеке память выделяется(то есть быстро) и освобождается быстро(а не когда GC соизволит)
в каком-то таком же смысле использования object-объектов возможно и может быть оправдано

Вывести информацию о книгах, в названии которых встречается некоторое ключевое слово

в чем ошибка? помогите! при пуске не нравится:fz:file of TKniga;. в чем проблема сдесь??
задача: В библиотеке имеется список книг. Каждая запись этою списка содержит: фамилии авторов, название книги, год издания. Вывести информацию о книгах, в названии которых встречается некоторое ключевое слово

09.06.2011, 23:22

Вывести информацию о книгах, в названии которых встречается некоторое ключевое слово
В библиотеке имеется список книг. Каждая запись этого списка содержит: фамилии авторов, название.

Вывести информацию о книгах, в названии которых встречается некоторое ключевое слово (ввести с клавиатуры)
В библиотеке имеется список книг. Каждая запись этого списка содержит: фамилии авторов, название.

Ввести слово и вывести элементы массивов, в которых слово встречается более одного раза
Написать программу, в которой требуется создать два массива строк.Ввести слово и вывести элементы.

Вывести информацию о книгах, в названии которых встречается некоторое ключевое слово
Уважаемые форумчани помогите мне с несложной задачей Имеются записи про книги : фамилию автора.

Определить, имеются ли в списке книги, в названии которых встречается некоторое слово
Здравствуйте, помогите разобраться. Только сел за си. Написал код но он неправильно работает. .

delphi — Ключевое слово Delphi

Я изучаю Delphi, читаю книгу Марко Канту, и она супер полная. Это очень ясно, но я сомневаюсь в ключевом слове self . У меня уже есть опыт работы с ООП, и у меня есть основы этого. Мой вопрос очень прост. Можно ли сравнить ключевое слово self (Delphi) с ключевым словом this (Java)?

Когда я прочитал книгу о self используемой внутренней записи, я понял, что-то вроде self : Delphi = this : Java . Посмотрите на код, который я создал для проведения теста:

Я собираюсь отрезать большую часть кода, я просто показываю конструктор здесь:

Используя ключевое слово self здесь, я имею в виду символ записи, а не символ, переданный в методе. Правильно ли это использовать себя? Может ли это быть братом Java this ?

    6 2
  • 22 июн 2020 2020-06-22 02:49:17
  • Alberto Miola

2 ответа

Self очень похож на this на Java, С++ или С#. Однако это немного больше вызывается, как показывает следующий код.

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

Смотрите вывод этой программы:

  • 22 июн 2020 2020-06-22 02:49:18
  • Stefan Glienke

Да, Delphi Self является прямым аналогом Java this .

Программирование на языке Delphi. Глава 2. Основы языка Delphi. Часть 1

Оглавление

В основе среды Borland Delphi лежит одноименный язык программирования — Delphi, ранее известный как Object Pascal. При разработке программы среда Delphi выполняет свою часть работы — создает пользовательский интерфейс согласно вашему дизайну, а вы выполняете свою часть — пишите обработчики событий на языке Delphi. Объем вашей работы зависит от программы: чем сложнее алгоритм, тем тяжелее ваш труд. Необходимо заранее усвоить, что невозможно заставить средство разработки делать всю работу за вас. Некоторые задачи среда Delphi действительно полностью берет на себя, например создание простейшей программы для просмотра базы данных. Однако большинство задач не вписываются в стандартные схемы — вам могут понадобиться специализированные компоненты, которых нет в палитре компонентов, или для задачи может не оказаться готового решения, и вы вынуждены будете решать ее старым дедовским способом — с помощью операторов языка Delphi. Поэтому мы настоятельно рекомендуем вам не игнорировать эту главу, поскольку на практике вы не избежите программирования. Мы решили изложить язык в одной главе, не размазывая его по всей книге, чтобы дать вам фундаментальные знания и обеспечить быстрый доступ к нужной информации при использовании книги в качестве справочника.

Алфавит


Буквы

Изучая в школе родной язык, вы начинали с букв, слов и простейших правил синтаксиса. Для постижения основ языка Delphi мы предлагаем вам сделать то же самое.

Текст программы на языке Delphi формируется с помощью букв, цифр и специальных символов.

Буквы — это прописные и строчные символы латинского алфавита и символ подчеркивания:

Цифры представлены стандартной арабской формой записи:

применяются в основном в качестве знаков арифметических операций, разделителей, ограничителей и т.д. Из специальных символов формируются составные символы :

Они служат, в частности, для обозначения операций типа «не равно», «больше или равно», указания диапазонов значений, комментирования программы, т.д.

Все перечисленные знаки отражены на клавиатуре и при нажатии соответствующих клавиш появляются на экране. Как вы видите, среди них нет русских букв, хотя на клавиатуре вашего компьютера они наверняка присутствуют. Дело в том, что такие буквы в языке Delphi несут чисто информационную нагрузку и используются только в качестве данных или при написании комментария к программе.

Числа

Одно и то же число можно записать самыми разными способами, например:

В языке Delphi имеется возможность применять все способы записи, но чаще всего используют целые и вещественные числа.

Целые числа состоят только из цифр и знака + или -. Если знак опущен и число не равно 0, то оно рассматривается как положительное, например:

Вещественные числа содержат целую и дробную части, разделенные точкой:

Вещественные числа могут быть представлены в двух формах: с фиксированной и плавающей точкой.

Форма с фиксированной точкой совпадает с обычной записью чисел, например:

Форма с плавающей точкой используется при работе с очень большими или очень малыми числами. В этой форме число, стоящее перед буквой E, умножается на 10 в степени, указанной после буквы E:

Число, стоящее перед буквой E, называется мантиссой , а число после буквы E — порядком .

В этой статье мы чаще будем использовать форму с фиксированной точкой, так как она воспринимается лучше второй формы и совпадает с привычной математической записью чисел.

Слова-идентификаторы

Неделимые последовательности символов алфавита образуют слова ( идентификаторы ). Идентификатор начинается с буквы и не должен содержать пробелов. После первого символа допускаются буквы и цифры. Напоминаем, что символ подчеркивания считается буквой.

При написании идентификаторов могут использоваться как прописные, так и строчные буквы (между ними не делается различий). Длина идентификатора может быть любой, но значимы только первые 255 символов (вполне достаточный предел, не так ли). Примеры написания идентификаторов приведены ниже:

Правильно


Неправильно


RightName Wrong Name
E_mail E-mail
_5inches 5inches

Все идентификаторы подразделяются на зарезервированные слова, стандартные директивы, стандартные идентификаторы и идентификаторы программиста.

Зарезервированные (ключевые) слова составляют основу языка Delphi, любое их искажение вызовет ошибку компиляции. Вот полный перечень зарезервированных слов:

Стандартные директивы интерпретируются либо как зарезервированные слова, либо как идентификаторы программиста в зависимости от контекста, в котором используются. Вот они:

Стандартные идентификаторы — это имена стандартных подпрограмм, типов данных языка Delphi, т.д. В качестве примера приведем имена подпрограмм ввода и вывода данных и нескольких математических функций. Вы, без сомнения, сами угадаете их назначение:

Идентификаторы программиста определяются программистом, т.е вами, и носят произвольный характер. Если идентификатор состоит из двух или более смысловых частей, то для удобства их лучше выделять заглавной буквой или разделять символом подчеркивания:

Имя идентификатора обязательно должно нести смысловую нагрузку, тогда вы сможете читать программу как книгу и не потратите время на расшифровку непонятных обозначений.

Комментарии

С помощью комментариев вы можете пояснить логику работы своей программы. Комментарий пропускается компилятором и может находиться в любом месте программы. Комментарием является:

Данные


Понятие типа данных

Программа в процессе выполнения всегда обрабатывает какие-либо данные. Данные могут представлять собой целые и дробные числа, символы, строки, массивы, множества и др. Так как компьютер всего лишь машина, для которой данные — это последовательность нулей и единиц, он должен абсолютно точно «знать», как их интерпретировать. По этой причине все данные в языке Delphi подразделены на типы. Для описания каждого типа данных существует свой стандартный идентификатор: для целых — Integer, для дробных — Real, для строк — string и т.д. Программист может образовывать собственные типы данных и давать им произвольные имена (о том, как это делается, мы поговорим чуть позже).

Тип данных показывает, какие значения принимают данные и какие операции можно с ними выполнять. Каждому типу данных соответствует определенный объем памяти, который требуется для размещения данных. Например, в языке Delphi существует тип данных Byte. Данные этого типа принимают значения в целочисленном диапазоне от 0 до 255, могут участвовать в операциях сложения, вычитания, умножения, деления, и занимают 1 байт памяти.

Все типы данных в языке Delphi можно расклассифицировать следующим образом:

  • простые типы данных. Они в свою очередь подразделяются на порядковые и вещественные типы данных. К порядковым типам относятся целочисленные, символьные, булевские, перечисляемые и интервальные типы данных;
  • временной тип данных. Служит для представления значений даты и времени;
  • строковые типы данных. Служат для представления последовательностей из символов, например текста;
  • составные типы данных (в некоторых источниках — структурированные типы данных). Формируются на основе всех остальных типов. К ним относятся массивы, множества, записи, файлы, классы и ссылки на классы;
  • процедурные типы данных. Позволяют манипулировать процедурами и функциями как данными программы;
  • указательные типы данных. Данные этих типов хранят адреса других данных, с их помощью организуются различные динамические структуры: списки, деревья и т.д.;
  • тип данных с непостоянным типом значений. Служит для представления значений, тип которых заранее неизвестен; с его помощью легко организуется работа со списком разнотипных значений;

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

По ходу изложения материала мы рассмотрим все перечисленные типы данных и более подробно объясним их смысл и назначение в программе.

Константы

Данные, независимо от типа, имеют некоторое значение и в программе предстают как константы или переменные. Данные, которые получили значение в начале программы и по своей природе изменяться не могут, называются константами . Константами, например, являются скорость света в вакууме и соотношение единиц измерения (метр, сантиметр, ярд, фут, дюйм), которые имеют научно обоснованные или традиционно принятые постоянные значения. Константы описываются с помощью зарезервированного слова const . За ним идет список имен констант, каждому из которых с помощью знака равенства присваивается значение. Одно присваивание отделяется от другого с помощью точки с запятой. Тип константы распознается компилятором автоматически, поэтому его не надо указывать при описании. Примеры констант:

После такого описания для обращения к нужному значению достаточно указать лишь имя соответствующей константы.

Значение константы можно задавать и выражением. Эту возможность удобно использовать для комплексного представления какого-либо понятия. Например, временной промежуток, равный одному месяцу, можно задать так:

Очевидно, что, изменив базовую константу SecondsInMinute, можно изменить значение константы SecondsInDay.

При объявлении константы можно указать ее тип:

Такие константы называются типизированными; их основное назначение — объявление константных значений составных типов данных.

Переменные

Переменные в отличие от констант могут неограниченное число раз менять свое значение в процессе работы программы. Если в начале программы некоторая переменная X имела значение 0, то в конце программы X может принять значение 10000. Так бывает, например, при суммировании введенных с клавиатуры чисел.

Переменные описываются с помощью зарезервированного слова var . За ним перечисляются идентификаторы переменных, и через двоеточие указывается их тип. Каждая группа переменных отделяется от другой группы точкой с запятой. Например:

В теле программы переменной можно присвоить значение. Для этого используется составной символ :=, например:

Вы можете присвоить значение переменной непосредственно при объявлении:

Объявленные таким образом переменные называются инициализированными . На инициализированные переменные накладывается ограничение: они не могут объявляться в подпрограммах (процедурах и функциях). Если переменная не инициализируется при объявлении, то по умолчанию она заполняется нулем.

Каждый используемый в программе элемент данных должен быть описан в разделе const или var . Исключение составляют данные, заданные непосредственно значением , например:

Простые типы данных


Целочисленные типы данных

Целочисленные типы данных применяются для описания целочисленных данных. Для решения различных задач могут потребоваться различные целые числа. В одних задачах счет идет на десятки, в других — на миллионы. Соответственно в языке Delphi имеется несколько целочисленных типов данных, среди которых вы можете выбрать наиболее подходящий для своей задачи.

Расставляем точки над i в Delphi RAII

Тема RAII в Delphi обычно замалчивается или же информация по этому вопросу ограничивается обсуждением полезности интерфейсов. Но интерфейсы поодиночке не дают многих желаемых возможностей. Когда в Delphi 2006 появилась перегрузка операций, приватные поля записей, собственные конструкторы и методы в записях и, казалось, было бы логично увидеть и автоматически вызываемый деструктор. И run-time позволяет, и в разделе запроса новых фич Delphi на протяжении нескольких лет в ТОП–10 висит запрос №21729 «Record Operator Overloading: Please implement «Initialize» and «Finalize» operators». Наверное, не судьба. Ничего, я покажу, как обойтись без несостоявшихся фич. Так как Delphi 7 живее всех живых, будут рассмотрены решения, совместимые с Delphi 7 в том числе

Времени найти обходные пути было достаточно. Эта статья — не tutorial и рассчитана на продвинутых разработчиков на Delphi, пишущих собственные библиотеки или делающих привязки к библиотекам на других языках программирования

Зачем хочется RAII в Delphi?

  • Автоматическое управление памятью. Лестница из try… finally — это не серьёзно. TList, TComponentList и прочие требуют дисциплины от того, кто будет их применять. Особенно сложно, не используя автоматику, сделать корректное освобождение памяти для переменных, используемых из восходящего замыкания
  • Copy-on-write и счётчики ссылок
  • Другое особое поведение при копировании
  • Copy-on-write и счётчики ссылок для объектов, созданных в сторонних библиотеках (например, CFString)

Для каких типов Delphi действует автоматическое управление?

  • AnsiString, WideString, UnicodeString — строки
  • array of… — динамические массивы
  • reference to… — замыкания в Delphi 2009+
  • интерфейсы
  • Variant, OleVariant — варианты

Среди всех этих возможностей программируемыми являются только интерфейсы и варианты

Чем плохи интерфейсы?
  • Инициализируются nil, у которого нельзя вызывать методы.
    Не подходит, если вы хотите реализовать собственный тип строки или собственную длинную арифметику. Неинициализированная переменная должна вести себя как пустая строка или 0, соответственно
  • Методы не могут изменить содержимое переменной–указателя, у которого они были вызваны
  • Нет контроля за тем, что происходит при копировании объекта. Только AddRef, который не может изменить содержимое переменной–указателя
  • Нет встроенной возможности сделать copy-on-write
  • Нет перегрузки операций
Чем плохи варианты?
  • Инициализируются Unassigned, у которого также нельзя вызвать методы
  • Вызовы нетипизированы. Реализация IDispatch или диспетчеризации у вариантов — нетривиальная и слабо документированная область знаний
  • Необходимость реализации муторных конверсий между другими типами вариантов, всяческих вспомогательных методов, которые могут быть вызваны

Как решить большинство этих проблем?

Решение, которое я предлагаю — заворачивать интерфейсы или варианты внутрь приватной части записей (record). Объявляем тип записи. Объявляем тип интерфейса. Дублируем все методы и в интерфейсе, и в записи. Методы записи перенаправляют все вызовы внутреннему объекту, при этом можно сделать то, что сама по себе переменная интерфейсного типа сделать не способна

В реализации каждого метода записи предусматриваем случай, когда в приватном поле nil — может потребоваться автоматически инициализировать объект перед тем, как что–либо вызывать у него. Если нужно реализовать Copy-on-write, в интерфейсе объявляется метод

Этот метод определяет по счётчику ссылок свою уникальность. Если объект не уникален, объект должен создать свою копию и записать этот указатель в Obj вместо себя. Каждый метод записи, который может что–либо изменить, перед передачей управления методу интерфейса должен убедиться в уникальности указателя. Для внутренних нужд можно и у других методов интерфейса предусмотреть var Obj: IOurInterface. Например, по аналогии со встроенными строками может возникнуть желание сделать так, чтобы, когда в строке собственного типа не остаётся символов, динамически размещённый объект удалялся, а внутренний указатель становился nil

В целях оптимизации при реализации собственных строк или длинной арифметики может потребоваться предусмотреть специальный случай a := a + b. Не гарантирую, что это сработает, но можно попробовать при реализации операции + сравнивать указатели @ Self и @ Result

Принципиально неразрешима проблема безусловной автоматической инициализации внутреннего поля, но можно инициализировать при первом обращении. Остальные проблемы разрешимы либо завёртыванием интерфейса в запись, либо завёртыванием варианта в запись, об этом далее

Вариант в записи — это как зефир в глазури, но вариант в записи

Собственный тип варианта даёт более полное управление по сравнению с интерфейсом. Так как вариантное поле приватно и наружу этот вариант не должен утекать, можно реализовать лишь минимальный набор методов собственного (custom) типа варианта. Если не считать отладчика, пытающегося привести (CastTo) вариант к строке при наведении курсора, потребуется реализовать копирование (Copy) и уничтожение (Clear) варианта. В оперативной памяти собственные типы варианта, как правило, состоят из маркера типа варианта и указателя (например, наследник TObject). Как это делается, предлагаю посмотреть на примере реализации комплексных чисел (VarCmplx.pas), который присутствует, по крайней мере, начиная с Delphi 7

Использование вариантов пригодилось бы для однозвенной обёртки CFString. Если делать обёртку для интерфейсов, Delphi будет вызывать AddRef и Release у интерфейса, но CFString — не интерфейс, и потребуется либо обернуть CFString в дополнительный слой косвенности из интерфейса, либо использовать собственный тип варианта, который вызывает CFRetain и CFRelease, требуемые для нормального управления памятью CFString. Это работало бы гораздо лучше, чем та обёртка CFString, которую предлагает Embarcadero в Delphi XE2

Эй, а как же Delphi 7?

Delphi — язык с длинной историей, и до того, как появилась объектная система Delphi, в Borland Pascal with Objects была другая объектная система. В Delphi 7 и Delphi 2005 она по–прежнему функционирует. Вместо record пишется ключевое слово object, и получившийся тип во многом похож на record в Delphi 2006: у него могут быть приватные поля, у него могут быть методы. object’ы одного типа можно присваивать друг другу, в этом смысле они тоже аналогичны record. Как раз то, что нам нужно. Компилятор будет ругаться на небезопасный тип, нет перегрузки операций, но это единственные неудобства. Сходство object и record настолько велико, что можно, используя условные директивы компилятора, на старых версиях Delphi объявлять тип как object, а на новых — как record. Именно так я поступил в своей небольшой библиотеке коллекций Delphi-CVariants

Проблемы могут возникнуть, если пытаться объявить несколько таких типов, использующих друг друга. Цикличные зависимости в исходном коде предусмотрены для классов, интерфейсов и указателей, но не для object’ов as is. Предпочтительнее объявлять object’ы так, чтобы каждый следующий знал про предыдущие, но не наоборот. Поэтому, например, в моей библиотечке CMapIterator знает про CVariant, но CVariant не знает про CMapIterator

Сохраненное ключевое слово в Delphi

Delphi позволяет сохранять ключевое слово при определении свойств следующим образом:

Какова цель ключевого слова и что оно делает?

3 ответа

Из моего файла справки Delphi 7:

Необязательные директивы сохранены, по умолчанию и nodefault называются спецификаторами хранилища. Они не влияют на поведение программы, но определяют, следует ли сохранять значения опубликованных свойств в файлах форм.

За сохраненной директивой должны следовать True, False, имя логического поля или имя метода без параметров, который возвращает логическое значение. Например,

Если свойство не имеет хранимой директивы, оно обрабатывается так, как если бы было сохранено значение True.

Звучит так, как будто он контролирует, сохранять ли свойство, относящееся к компоненту, в файле .DFM для формы. (Просто предположение, хотя)

Это ключевое слово определяет, следует ли сохранять значение свойства в файле формы; это true по умолчанию. Может быть полезно избежать, например, сохранения больших кусков двоичной информации в вашем файле .dfm (например, компонент изображения, который должен читать свое содержимое только во время выполнения.)

Хранимая директива принимает логическое значение: метод, который возвращает логический результат, ссылку на поле логического типа или константное выражение логического типа. RTTI свойства записывает смещение поля, ссылку на метод или постоянное значение, и среда IDE Delphi использует эту информацию, чтобы решить, следует ли пропустить свойство из файла .dfm.

Среда IDE вызывает метод, проверяет значение поля или использует постоянное логическое значение, и если значение равно False, свойство не сохраняется в файл .dfm. Если сохраненное значение равно True, происходит поведение по умолчанию, а именно, что свойство сохраняется, если его значение отличается от значения по умолчанию.

Секреты и уловки

Сохраненная директива часто неправильно понимается. Установка для True значения не заставляет Delphi сохранять значение свойства в файле .dfm. True — это значение по умолчанию для хранимой директивы. Вместо этого все, что вы можете сделать, это опустить свойство из файла .dfm, установив для параметра false значение False.

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

Если вы используете имя метода, метод может быть статическим или виртуальным, но не динамическим или обработчиком сообщений.

Ссылка на поле может быть именем поля, элементом записи или элементом массива с постоянным индексом. Ссылка на поле должна иметь логический тип.

Илон Маск рекомендует:  Как собрать компьютер самостоятельно, советы и рекомендации
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL