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


Задание свойств через constructor Create

Есть такая программа, она создаёт кнопку, как вы понимаете:

24.04.2020, 18:42

Задание свойств массивным Edit при OnKeyDown
Автоматически создаются 30 элементов Edit A1-30 и B1-30 в два ряда procedure.

Задание свойств динамически добавляемым элементам
Доброго времени суток, форумчане! Простенький вопрос такой: Вывожу на страницу из БД строки в.

JPA. Задание свойств соединения непосредственно в программе
Здравствуйте, господа программисты. Вопрос следующего характера. Мне необходимо предоставить.

Ошибка: Syntax error, «=» constructor but constructor found
Пытался найти решение, но нашел только одну подобную тему и ее решением было убрать »;» после.

Как через ADO вызвать Create Table?
Народ помогите пожалуйста. Как через ADO вызвать Create table для ACCESS. Необходимо создавать.

24.04.2020, 19:50 2

Решение

переопределить конструктор нужно, вот примерно так, для Top и Left я показал как, остальное сами , удачи

24.04.2020, 21:17 [ТС] 3 24.04.2020, 21:32 4 24.04.2020, 21:52 5

TProp ничего не знает о TInputButton, либо ему надо это сказать, либо TInputButton сделать конструктор такой как сделали вы. Я не буду тут сейчас основы «классописания» писать, так как это делают куча книжек с подробным объяснением, что и зачем там есть

вот тут вот есть отличный пример самописного класса, с «самописным» конструктором

Конструкторы и деструкторы

Методы, которые предназначены для создания и удаления объектов называются конструкторами и деструкторами соответственно. Описание данных методов отличается от обычных тем, что в их заголовках стоят ключевые слова constructor и destructor. В качестве имен конструкторов и деструкторов в базовом классе TObject и многих других классах используются имена Create и Destroy.

Прежде чем обращаться к элементам объекта, его нужно создать с помощью конструктора. Например: ObjectA:=TOwnClass.Create;

Конструктор выделяет память для нового объекта, задает нулевые значения для порядковых полей, значение nil – для указателей и полей классов, строковые поля устанавливает пустыми, а также возвращает указатель на созданный объект.

Классы объектов определяются в секции type глобального блока. Описание класса начинается с ключевого слова class и заканчивается ключевым словом end .

Чтобы от описания класса перейти к объекту, следует выполнить соответствующее объявление в разделе var : Var math:TMatematica;

Переменная math – это ссылка на экземпляр (объект в памяти), которого физически еще не существует. Чтобы сконструировать объект (выделить память для экземпляра) класса TMatematica и связать с ним переменную math , нужно в тексте программы поместить следующий оператор: math:= TMatematica.Create;

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

После создания объект можно использовать в программе: получать и устанавливать значения его полей, вызывать его методы. Доступ к полям и методам объекта происходит с помощью имен, например: math.x1;

Кроме того, как и при работе с записями, допустимо использование оператора with , например:

Если объект становится ненужным, он должен быть удален вызовом специального метода Destroy (освобождение памяти, занимаемой объектом), например: math .Destroy;

Destroy – это деструктор объекта; он присутствует в классе наряду с конструктором и служит для удаления объекта из динамической памяти. После вызова деструктора переменная math становится несвязанной и не должна использоваться для доступа к полям и методам уже несуществующего объекта. Чтобы отличать в программе связанные объектные переменные от несвязанных, последние следует инициализировать значением nil .

Вызов деструктора для несуществующих объектов недопустим и при выполнении программы приведет к ошибке. Чтобы избавить от лишних ошибок, в объекты ввели предопределенный метод Free , который следует вызывать вместо деструктора. Метод Free сам вызывает деструктор Destroy, но только в том случае, если значение объектной переменной не равно nil : math .Free;

После уничтожения объекта переменная math сохраняет свое значение, продолжая ссылаться на место в памяти, где объекта уже нет. Если эту переменную предполагается еще использовать, то желательно присвоить ей значение nil , чтобы программа могла проверить, существует объект или нет. Таким образом, наиболее правильная последовательность действий при уничтожении объекта должна быть следующая:

С помощью стандартной процедуры FreeAndNil это можно сделать проще и элегантнее:

Delphi: Понимание конструкторов

  • виртуальный
  • переопределить
  • перегрузка
  • реинтродукции

при применении к конструкторам объектов. Каждый раз, когда я произвольно добавляю ключевые слова до тех пор, пока компилятор не закроется — и (после 12 лет разработки с Delphi), я бы лучше знал, что я делаю, а не пытался случайным образом.

Учитывая гипотетический набор объектов:

То, как я хочу, чтобы они вели себя, вероятно, очевидно из деклараций, но:

  • TComputer имеет простой конструктор, и потомки могут его переопределить
  • TCellPhone имеет альтернативный конструктор, и потомки могут его переопределить
  • TiPhone переопределяет оба конструктора, вызывая унаследованную версию каждого

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

Я хочу понять, почему. Тогда это будет очевидно.

См. также

Изменить: Я также хочу получить некоторые рассуждения о порядке virtual , override , overload , reintroduce . Потому что при попытке всех комбинаций ключевых слов число комбинаций взрывается:

  • виртуальный; перегрузки;
  • виртуальный; переопределить;
  • переопределение; перегрузки;
  • переопределение; виртуальный;
  • виртуальный; переопределить; перегрузки;
  • виртуальный; перегрузки; переопределить;
  • перегрузки; виртуальный; переопределить;
  • переопределение; виртуальный; перегрузки;
  • переопределение; перегрузки; виртуальный;
  • перегрузки; переопределить; виртуальный;
  • и т.д.

Изменить 2: Я думаю, мы должны начать с «является ли возможна иерархия объектов? Если нет, почему бы и нет? Например, принципиально неверно иметь конструктор от предка?

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

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

Теперь эти объявления не компилируются:

Итак, сначала я попытаюсь установить TCellPhone . я начну с случайного добавления ключевого слова overload (я знаю, что не хочу reintroduce , потому что это скроет другой конструктор, который я не хочу):

Но это не удается: Field definition not allowed after methods or properties .

Я знаю по опыту, что даже если у меня нет поля после метода или свойства, если я отменил порядок ключевых слов virtual и overload : Delphi закроется:

Но я все еще получаю ошибку:

Метод «Создать» скрывает виртуальный метод базового типа «TComputer»

Итак, я пытаюсь удалить оба ключевых слова:

Но я все еще получаю ошибку:

Метод «Создать» скрывает виртуальный метод базового типа «TComputer»

Итак, я схожу, чтобы теперь попробовать reintroduce :

И теперь TCellPhone компилируется, но для TiPhone это намного хуже:

Оба жалуются, что я не могу их переопределить, поэтому я удаляю ключевое слово override :

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

В разделе interface все хорошо. К сожалению, мои реализации не будут работать. Мой единственный конструктор параметров TiPhone не может вызвать унаследованный конструктор:

Я вижу две причины, по которым ваш оригинальный набор деклараций не должен компилироваться чисто:

В TCellPhone должно быть предупреждение, что его конструктор скрывает метод базового класса. Это связано с тем, что метод базового класса является виртуальным, и компилятор беспокоится о том, что вы вводите новый метод с тем же именем без переопределения метода базового класса. Неважно, что подписи различаются. Если ваше намерение действительно скрывает метод базового класса, тогда вам нужно использовать reintroduce в декларации потомков, как показало одно из ваших слепых догадок. Единственная цель этой директивы — подавить предупреждение; он не влияет на поведение во время выполнения.

Илон Маск рекомендует:  Round - Функция Delphi

Игнорируя, что произойдет с TIPhone позже, следующее объявление TCellPhone — это то, что вы хотите. Он скрывает метод предков, но вы также хотите, чтобы он был виртуальным. Он не наследует виртуальность метода предка, потому что это два совершенно разных метода, которые просто имеют одно и то же имя. Поэтому вам нужно использовать virtual и в новой декларации.

Конструктор базового класса TComputer.Create также скрывает метод своего предка TObject.Create , но поскольку метод в TObject не является виртуальным, компилятор не предупреждает об этом. Скрытие не виртуальных методов происходит все время и вообще не примечательно.

Вы должны получить сообщение об ошибке в TIPhone , потому что больше нельзя использовать конструктор с одним аргументом. Вы спрятали его в TCellPhone . Поскольку вы хотите иметь два конструктора, reintroduce явно не был правильным выбором для использования ранее. Вы не хотите скрывать конструктор базового класса; вы хотите увеличить его с помощью другого конструктора.

Поскольку вы хотите, чтобы оба конструктора имели одинаковое имя, вам нужно использовать директиву overload . Эта директива должна использоваться в всех исходных объявлениях — при первом вводе каждой отдельной подписи последующие объявления в потомках. Я думал, что это необходимо для всех объявлений (даже базового класса), и это не помешает сделать это, но я думаю, это не требуется. Итак, ваши объявления должны выглядеть так:

Современная документация рассказывает, в каком порядке все должно идти:

вновь ввести; перегрузки; связывание; вызывающая конвенция; абстрактный; предупреждение

где привязка виртуальная, динамическая или переопределяет; вызов зарегистрировать, pascal, cdecl, stdcall или safecall; и предупреждение платформа, устаревшая или библиотека.

Это шесть разных категорий, но, по моему опыту, редко бывает более трех в любой декларации. (Например, функции, для которых требуются указанные соглашения вызова, вероятно, не являются методами, поэтому они не могут быть виртуальными.) Я никогда не помню порядок; Я никогда не видел, чтобы это было зарегистрировано до сегодняшнего дня. Вместо этого я считаю более полезным запомнить каждую директивную цель. Когда вы помните, какие директивы вам нужны для разных задач, вы получите всего два или три, а затем довольно просто поэкспериментировать, чтобы получить правильный порядок. Компилятор может принимать несколько заказов, но не волнуйтесь — порядок не имеет значения при определении значения. Любое упорядочение, которое принимает компилятор, будет иметь то же значение, что и любое другое (за исключением вызовов условных обозначений, если вы упомянете более одного из них, учитывается только последний, поэтому не делайте этого).

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

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


Блог GunSmoker-а

. when altering one’s mind becomes as easy as programming a computer, what does it mean to be human.

22 декабря 2008 г.

Новое ключевое слово static в Delphi

Недавно я переводил пост Почему методы класса должны быть помечены словом «static», чтобы их можно было использовать в качестве функции обратного вызова? Реймонда Чена. Там я оставил весь код «как есть» — на C++. Здесь я рассмотрю этот вопрос с точки зрения Delphi.

Как известно, в языке есть такие сущности как процедуры/функции и методы. Причём начинающие программисты часто путают эти два понятия.

Функция (в дальнейшем здесь будет также подразумеваться и процедура) — это код. Процедурная переменная — это указатель на код. Например: Метод — это тоже код, но код, связанный с классом. Указатель на метод — это ссылка на код + ссылка на конкретный объект. Например: Когда путают одно с другим компилятор чаще всего показывает такое сообщение: «Incompatible types: regular procedure and method pointer». Чаще всего или забывают писать «of object» в объявлении своих процедурных типов или пытаются передать в функцию (чаще всего как callback — т.е. функцию обратного вызова) метод класса вместо обычной функции (а самым упорным это иногда удаётся).

Что делает эти две сущности такими принципиально несовместимыми? Функция — это просто код. Она не имеет связи с данными, отличными от тех, что передаются в её параметры. Методы класса помимо работы с параметрами (как и обычная функция) ещё могут оперировать с данными объекта (вот оно: «код» vs «код + данные»), например: С функциями такое невозможно — обратите внимание, как вы манипулируете с P3 (он же: Self.P3) в методе. Собственно сам объект (это встроенная переменная Self) неявно передаётся в метод первым параметром. Поэтому, если метод объявлен как function(const P1, P2: Integer): Integer of object — с двумя параметрами, то, на самом деле, он трактуется как функция с тремя параметрами: function(Self: TSomeObj; const P1, P2: Integer): Integer . Именно это различие (на бинарном уровне) делает несовместимыми обычные функции и методы.

Соответственно, указатель на обычную функцию — это просто указатель (pointer), только что типизированный (это я про TDoSomethingFunc) — т.е. 4 байта. А вот указатель на метод — это уже запись или, если будет угодно, два указателя — один на код, второй — на данные, т.е. всего 8 байт.

Понятно, что если у вас что-то предназначено для передачи указателя на функцию, то никакими силами указатель на метод вы туда не пропихнёте. Хотя бы потому, что размер у них разный.

Ещё в Delphi есть классовые методы. Это такие методы, которые можно вызывать не имея на руках объект. В этом случае вместо объекта в неявный параметр Self передаётся информация о классе. Т.е. в классовых методах вы не можете использовать информацию о конкретном объекте (например, читать/писать его поля), но можете использовать информацию о классе — например, вызывать конструктор класса. Также методы класса могут быть виртуальными. Заметим, что сигнатура функции, реализующей метод, всё ещё совпадает с сигнатурой обычного метода: неявный параметр (данные класса вместо Self) + все явные параметры метода.

Например: Теперь ещё один шажок и мы переходим к тому, о чём говорил Реймонд Чен. Классовый метод можно объявить статическим (только в новых версиях Delphi). В этом случае у него не будет неявного параметра. Разумеется, при этом он не может использовать информацию экземпляра и класса. Зато он и не отличается от обычной функции.

Рассматривая пример с потоком, вот что мы могли бы написать в старых Delphi без поддержки статических классовых методов: Теперь, с введением нового ключевого слова static, появилась возможность писать так: При этом Реймонд говорит о том, что если у Execute сделать модель вызова stdcall, то бинарные сигнатуры параметра CreateThread, методов ThreadProc и Execute совпадут — поэтому, мол, умный компилятор уменьшит код ThreadProc до простого jmp. Увы, но компилятор Delphi не настолько умён — в этом случае он генерирует полный вызов вместе с передачей параметра.

Delphi: Понимание конструкторов — constructor

  • виртуальный
  • переопределить
  • перегрузка
  • реинтродукции

при применении к конструкторам объектов. Каждый раз, когда я произвольно добавляю ключевые слова до тех пор, пока компилятор не закроется — и (после 12 лет разработки с Delphi), я бы лучше знал, что я делаю, а не пытался случайным образом.

Учитывая гипотетический набор объектов:

То, как я хочу, чтобы они вели себя, вероятно, очевидно из деклараций, но:

  • TComputer имеет простой конструктор, и потомки могут его переопределить
  • TCellPhone имеет альтернативный конструктор, и потомки могут его переопределить
  • TiPhone переопределяет оба конструктора, вызывая унаследованную версию каждого

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

Я хочу понять, почему. Тогда это будет очевидно.

См. также

Изменить: Я также хочу получить некоторые рассуждения о порядке virtual , override , overload , reintroduce . Потому что при попытке всех комбинаций ключевых слов число комбинаций взрывается:

  • виртуальный; перегрузки;
  • виртуальный; переопределить;
  • переопределение; перегрузки;
  • переопределение; виртуальный;
  • виртуальный; переопределить; перегрузки;
  • виртуальный; перегрузки; переопределить;
  • перегрузки; виртуальный; переопределить;
  • переопределение; виртуальный; перегрузки;
  • переопределение; перегрузки; виртуальный;
  • перегрузки; переопределить; виртуальный;
  • и т.д.
Илон Маск рекомендует:  Что такое код getcurrentposition

Изменить 2: Я думаю, мы должны начать с «является ли возможна иерархия объектов? Если нет, почему бы и нет? Например, принципиально неверно иметь конструктор от предка?

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

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

Теперь эти объявления не компилируются:

Итак, сначала я попытаюсь установить TCellPhone . я начну с случайного добавления ключевого слова overload (я знаю, что не хочу reintroduce , потому что это скроет другой конструктор, который я не хочу):

Но это не удается: Field definition not allowed after methods or properties .

Я знаю по опыту, что даже если у меня нет поля после метода или свойства, если я отменил порядок ключевых слов virtual и overload : Delphi закроется:

Но я все еще получаю ошибку:

Метод «Создать» скрывает виртуальный метод базового типа «TComputer»

Итак, я пытаюсь удалить оба ключевых слова:

Но я все еще получаю ошибку:

Метод «Создать» скрывает виртуальный метод базового типа «TComputer»

Итак, я схожу, чтобы теперь попробовать reintroduce :

И теперь TCellPhone компилируется, но для TiPhone это намного хуже:

Оба жалуются, что я не могу их переопределить, поэтому я удаляю ключевое слово override :

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

В разделе interface все хорошо. К сожалению, мои реализации не будут работать. Мой единственный конструктор параметров TiPhone не может вызвать унаследованный конструктор:

    5 4
  • 5 окт 2020 2020-10-05 05:20:54
  • Ian Boyd

4 ответа

используйте перегрузку для обоих, это так, как я делаю это, и он работает.

constructor Create; Overload ; constructor Values; Overload; 5 окт 2020 2020-10-05 05:20:56

  • Damon
  • Это рабочая реализация требуемых определений:

    Первая часть соответствует этому. Определение двух конструкторов TiPhone выполняется следующим образом:

    • Первый конструктор перегружает один из двух конструкторов, унаследованных и переопределяющих свой родной брат. Для этого используйте overload; override , чтобы перегрузить TCellPhone один, переопределив другой конструктор.
    • Для этого второй конструктор нуждается в простой override , чтобы переопределить свой родной брат.
    • 5 окт 2020 2020-10-05 05:20:56
    • Muhammad Alkarouri

    Заметьте, что у меня нет Delphi 5, поэтому я основываю свои ответы на последней версии Delphi XE. Я не думаю, что это действительно будет иметь значение здесь, но если это произойдет, вас предупредили.:)

    В основном это основан на http://docwiki.embarcadero.com/RADStudio/en/Methods, который является текущей документацией о том, как работают методы. Возможно, у вашего файла справки Delphi 5 есть что-то похожее.

    Во-первых, виртуальный конструктор может не иметь особого смысла здесь. Есть несколько случаев, когда вы этого хотите, но это, вероятно, не одно. Взгляните на http://docwiki.embarcadero.com/RADStudio/en/Class_References для ситутации, где вам нужен виртуальный конструктор — если вы всегда знаете тип своих объектов при кодировании, однако, вы этого не делаете.

    Проблема, которую вы затем получаете в своем конструкторе с 1 параметром, состоит в том, что ваш родительский класс не имеет самого конструктора с 1 параметром — унаследованные конструкторы не отображаются. Вы не можете использовать inherited для перехода на несколько уровней в иерархии, вы можете только вызвать своего непосредственного родителя. Вам нужно будет вызвать конструктор с двумя параметрами с некоторым значением по умолчанию или добавить конструктор с 1 параметром в TCellPhone.

    В целом, четыре ключевых слова имеют следующие значения:

    • virtual — Отметьте это как функцию, где вам понадобится диспетчеризация во время выполнения (допускает полиморфное поведение). Это только для первоначального определения, а не при переопределении в подклассах.
    • override — предоставить новую реализацию для виртуального метода.
    • overload — Отметьте функцию с тем же именем, что и другая функция, но другой список параметров.
    • reintroduce — Расскажите компилятору, что вы на самом деле намеревались скрыть виртуальный метод, вместо того, чтобы просто забыть предоставить override .

    Требуемое упорядочение подробно описано в документации:

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

    вновь; перегрузки; связывание; вызывающая конвенция; Абстрактные; предупреждение

    где привязка является виртуальной, динамической или переопределить; вызывающая конвенция register, pascal, cdecl, stdcall или директива SafeCall; и предупреждение — это платформа, устаревшие или библиотеки.


    • 5 окт 2020 2020-10-05 05:20:56
    • Michael Madsen

    Я вижу две причины, по которым ваш оригинальный набор деклараций не должен компилироваться чисто:

    В TCellPhone должно быть предупреждение, что его конструктор скрывает метод базового класса. Это связано с тем, что метод базового класса является виртуальным, и компилятор беспокоится о том, что вы вводите новый метод с тем же именем без переопределения метода базового класса. Неважно, что подписи различаются. Если ваше намерение действительно скрывает метод базового класса, тогда вам нужно использовать reintroduce в декларации потомков, как показало одно из ваших слепых догадок. Единственная цель этой директивы — подавить предупреждение; он не влияет на поведение во время выполнения.

    Игнорируя, что произойдет с TIPhone позже, следующее объявление TCellPhone — это то, что вы хотите. Он скрывает метод предков, но вы также хотите, чтобы он был виртуальным. Он не наследует виртуальность метода предка, потому что это два совершенно разных метода, которые просто имеют одно и то же имя. Поэтому вам нужно использовать virtual и в новой декларации.

    Конструктор базового класса TComputer.Create также скрывает метод своего предка TObject.Create , но поскольку метод в TObject не является виртуальным, компилятор не предупреждает об этом. Скрытие не виртуальных методов происходит все время и вообще не примечательно.

    Вы должны получить сообщение об ошибке в TIPhone , потому что больше нельзя использовать конструктор с одним аргументом. Вы спрятали его в TCellPhone . Поскольку вы хотите иметь два конструктора, reintroduce явно не был правильным выбором для использования ранее. Вы не хотите скрывать конструктор базового класса; вы хотите увеличить его с помощью другого конструктора.

    Поскольку вы хотите, чтобы оба конструктора имели одинаковое имя, вам нужно использовать директиву overload . Эта директива должна использоваться в всех исходных объявлениях — при первом вводе каждой отдельной подписи последующие объявления в потомках. Я думал, что это необходимо для всех объявлений (даже базового класса), и это не помешает сделать это, но я думаю, это не требуется. Итак, ваши объявления должны выглядеть так:

    Современная документация рассказывает, в каком порядке все должно идти:

    вновь ввести; перегрузки; связывание; вызывающая конвенция; абстрактный; предупреждение

    где привязка виртуальная, динамическая или переопределяет; вызов зарегистрировать, pascal, cdecl, stdcall или safecall; и предупреждение платформа, устаревшая или библиотека.

    Это шесть разных категорий, но, по моему опыту, редко бывает более трех в любой декларации. (Например, функции, для которых требуются указанные соглашения вызова, вероятно, не являются методами, поэтому они не могут быть виртуальными.) Я никогда не помню порядок; Я никогда не видел, чтобы это было зарегистрировано до сегодняшнего дня. Вместо этого я считаю более полезным запомнить каждую директивную цель. Когда вы помните, какие директивы вам нужны для разных задач, вы получите всего два или три, а затем довольно просто поэкспериментировать, чтобы получить правильный порядок. Компилятор может принимать несколько заказов, но не волнуйтесь — порядок не имеет значения при определении значения. Любое упорядочение, которое принимает компилятор, будет иметь то же значение, что и любое другое (за исключением вызовов условных обозначений, если вы упомянете более одного из них, учитывается только последний, поэтому не делайте этого).

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

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

    Delphi constructor and > Ask Question

    I have a doubt that I cannot solve. I have read the documentation at embarcadero for class constructors but I cannot understand the meaning of that. In other words, what is the usage difference between a constructor and a class constructor ? I did this:

    Илон Маск рекомендует:  Генератор JAD-файла

    Instead this code is not working properly:

    I guess that the answer is in this line of the documentation:

    Normally, class constructors are used to initialize the static fields of the class or to perform a type of initialization, which is required before the class or any class instance can function properly.

    Tell me if I am correct:

    • Constructor: I can use the inherited Create; , initialize variables and so on.
    • Class constructor: I can use this when I have to create an object in my class immediately?

    Об «очевидном» и полезном или создание и уничтожение объектов Delphi

    Когда читаешь о той или иной реализации механизмов ООП, то весьма забавно видеть, как та или иная конкретная особенность конкретного языка или библиотеки называется «очевидной». Особенно выделяется в этом отношении описание ООП в C++, в котором по факту реализация одна из самых непрозрачных и запутанных.
    Так вот, я ничего не буду писать про очевидность, а расскажу про способ облегчить себе жизнь в критических точках жизненного цикла объектов, используя не «очевидные», но весьма полезные особенности реализации ООП в Delphi.

    Обработка невозможности завершить создание объекта в конструкторе

    Если конструктор хранит свои данные только в полях объекта, то решение элементарно — достаточно возбудить исключение. RTL Delphi сама его перехватит, вызовет деструктор, высвободит занятую память и возбудит исключение повторно.
    Соответственно, если часть данных для конструирования хранится в глобальных переменных, то достаточно использовать обычный блок try..except с повторным возбуждением исключения.
    Отсюда выводятся два требования к деструкторам: не провоцировать исключения, что означает не пытаться заниматься чем-либо, кроме освобождения ресурсов (например, сохранением настроек) и обязательно поддерживать…

    Удаление частично инициализированного объекта

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

    Порядок вызова конструкторов

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

    Вызов виртуальных методов в конструкторе

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

    Виртуальные конструкторы и ссылки на класс

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

    Автоматическое управление временем жизни объекта

    Если объект реализует тот или иной явно заданный интерфейс, то его можно привести к ссылке на этот интерфейс, используя присваивание или операцию as. В этом случае Delphi будет сама генерировать вызовы методов IUnknown, что позволяет не запрашивать интерфейсы и не удалять объекты явно.

    Что означает ключевое слово `constructor` означает в названии класса?

    Если у меня есть объявление класса, как этот:

    Что ключевое слово constructor делать?

    Не каждый класс имеет конструктор, уже, что это до делать там?

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

    Это особое ограничение является конструктору ограничение :

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

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

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

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

    Что означает в Delphi ключевое слово Constructor?

    Видео Виртуальные методы класса c++. Ключевое слово virtual. Ключевое слово override. ООП. C++ #103

    Это лучший ответ на вопрос! SeaMan75[11.6K] заработала 75 рублей!

    В Delphi ключевое слово Constructor означает метод, который является конструктором объекта и по умолчанию, этот метод называют Create. Но можно конструктор назвать и по иному, в Delphi это не критично. А вот в других языках конструктор однозначно определяется тем, что не имеет типа возвращаемых данных и совпадает с именем класса, например:

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

    • виртуальные
    • переопределить
    • перегрузка
    • реинтродукции

    когда применительно к объектно-конструкторы. Каждый раз, когда я случайно добавить ключевые слова до тех пор, пока компилятор замолкает и (после 12 лет разработки Delphi) я лучше знаю, что я делаю, вместо того, чтобы пытаться вещи беспорядочно.

    Данный гипотетический набор объектов:

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

    • TComputer имеет простой конструктор, и потомки могут переопределить это,
    • TCellPhone имеет дополнительный конструктор, и потомки могут переопределить это,
    • TiPhone переопределяет оба конструктора, назвав унаследованная версия каждый элемент

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

    я хочу понять, почему. Фиксация тогда станет очевидным.

    • Delphi: Как скрыть предка конструкторов?
    • Восстановившие функции в Delphi
    • Delphi: Как добавить другой конструктор, чтобы потомок?

    Редактировать: я тоже хочет получить какое-то рассуждение о порядке virtual , override , overload , reintroduce . Потому что, когда набирают все сочетания слов, количество комбинаций взрывается:

    • virtual; перегрузки;
    • virtual; override;
    • override; перегрузки;
    • override; виртуальный;
    • virtual; override; перегрузки;
    • virtual; перегрузки; override;
    • перегрузки; виртуальный; override;
    • override; виртуальный; перегрузки;
    • override; перегрузки; виртуальный;
    • перегрузки; override; виртуальный;
    • и т.д.

    2. я думаю, мы должны начать с » — это объект иерархии дали даже возможности?» Если нет, то почему? Например, это принципиально неверная иметь конструктор предка?

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

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

    Теперь эти декларации не скомпилируется:

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

    Но это не удается: Field definition not allowed after methods or properties .

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

    Но я все равно получаю ошибку:

    Метод » Создания » скрывает виртуальный метод базового типа » TComputer’

    Поэтому я стараюсь извлекать обе ключевые слова:

    Но я все равно получаю ошибку:

    Метод » Создания » скрывает виртуальный метод базового типа » TComputer’

    Итак, я ухожу в отставку себя сейчас набирают reintroduce :

    А теперь TCellPhone компилирует, но он сделал вещи намного хуже TiPhone:

    Оба жалуются, что я не могу изменить их, так что я удалить override ключевые слова:

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

    Всех все хорошо в interface раздел. К сожалению, мой реализации не будет работать. Мой единственный параметр конструктора TiPhone не вызов унаследованного конструктора:

    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL