Параметризовать конструктор

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

Re: Параметризовать конструктор

Сообщение Vapaamies » 25.07.2014 00:34:07

А в FPC же вроде есть модуль Objects от Turbo/Free Vision, в нем что с Load? Вчера видел Objects.pp в исходниках, но не смотрел. Жарко-с.
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 291
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Параметризовать конструктор

Сообщение Дож » 25.07.2014 03:12:22

Действительно, всё изобретено до нас :)
http://www.freepascal.org/docs-html/rtl ... uctor.html

В этом модуле даже вызов nested функций в каком-то виде есть...
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Параметризовать конструктор

Сообщение MylnikovDm » 28.07.2014 23:34:47

Дож писал(а):Я хочу получить указатель на конструктор объекта (именно object, а не class), дальше передать его параметром куда-то, и применить этот конструктор для инициализации объекта. Как это сделать (если это вообще возможно)? Чисто гипотетически это возможно, но как это написать на паскале, у меня пока даже идей нет.

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

вся эта хрень с фабриками классов была придумана для языка C++, поскольку там нет виртуальных конструкторов. В Delphi и FreePascal они есть, плюс коснтрукция TObjectClass = class of TObject; , поэтому нечего огород с такими сложностями городить.

И писать, и разбираться с вашим кодом будет намного проще.
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Re: Параметризовать конструктор

Сообщение zub » 29.07.2014 00:15:43

>>В Delphi и FreePascal они есть, плюс коснтрукция TObjectClass = class of TObject
Тема про object`ы, не про class`ы
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: Параметризовать конструктор

Сообщение MylnikovDm » 29.07.2014 00:51:50

Упс, ясно, недоглядел. Извиняюсь.
Хотя, если честно, не понятно, зачем мучиться с object'ами, когда есть class'ы?
Может я что в этой жизни упустил?
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Re: Параметризовать конструктор

Сообщение Дож » 29.07.2014 16:13:09

Упс, ясно, недоглядел. Извиняюсь.
Хотя, если честно, не понятно, зачем мучиться с object'ами, когда есть class'ы?
Может я что в этой жизни упустил?

Каждый отдельный экземпляр класса нужно выделять в куче. Часто возникает необходимость создавать объекты на лету («на стеке») или создавать много однотипных экземпляров в коллекции, в этих случаях использование объектов эффективнее.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Параметризовать конструктор

Сообщение MylnikovDm » 29.07.2014 18:52:57

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


Угу, понятно. А как на счёт новых record'ов, которые также, как и классы, могут иметь методы и свойства? Или во FreePascal этой фичи нет, только в Deplhi XE?

А, глянул доку, http://freepascal.org/docs-html/ref/refse51.html#x107-1170009.1, они тут какие-то ущербные, нет наследования.
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Re: Параметризовать конструктор

Сообщение Дож » 29.07.2014 19:12:23

Угу, понятно. А как на счёт новых record'ов, которые также, как и классы, могут иметь методы и свойства? Или во FreePascal этой фичи нет, только в Deplhi XE?


Во Free Pascal record не предоставляет всех возможностей object'а. Общая философия такова, что record должен оставаться тупыми данными, а методы к ним лишь для синтаксической красоты.

А про static не знал, спасибо за ссылку.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Параметризовать конструктор

Сообщение Vapaamies » 29.07.2014 19:42:10

MylnikovDm писал(а):вся эта хрень с фабриками классов была придумана для языка C++, поскольку там нет виртуальных конструкторов.

Немного не так. Вся эта хрень с фабриками является одним из способов порождения экземпляров в ООП, и в C++ она реализуется в лоб, а в Delphi/FPC -- компилятором, где фабрикой класса являются виртуальные конструкторы. Вынужденной платой за упрощение стало размещение объектов только в куче, поскольку разработчики решили не усложнять компилятор полноценным ARC и escape analysis (не знаю для него русского термина).
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 291
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Параметризовать конструктор

Сообщение MylnikovDm » 29.07.2014 20:42:03

Vapaamies писал(а):Вынужденной платой за упрощение стало размещение объектов только в куче, поскольку разработчики решили не усложнять компилятор полноценным ARC и escape analysis (не знаю для него русского термина).

Если вы не знаете, конструктор какого объекта вам на самом деле придёт, то вы не можете выделить необхдимое количество памяти на этапе компиляции. Только в runtime динамически "из кучи". Соответственно, все объекты становятся исключительно указателями. Какие ещё есть варианты? Анализировать весь код с учётом все потомков и выделять максимально возможный объём, как для union в C или вариантных record в pascal? Но тогда не будет работать раздельная компиляция модулей или вся иерархия, для которой будет работать такой механизм, должна быть в одном модуле.

Кстати, механизм с виртуальными конструкторами на практике более удобный и гибкий, чем использование фабрик классов. IMHO
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Re: Параметризовать конструктор

Сообщение zub » 29.07.2014 20:59:00

>>А как на счёт новых record'ов, которые также, как и классы, могут иметь методы и свойства?
В делфи для record`ов доступны виртуальные методы? зачем тогда новые record`ы если есть старые object`ы?))
zub
долгожитель
 
Сообщения: 2884
Зарегистрирован: 14.11.2005 23:51:26

Re: Параметризовать конструктор

Сообщение MylnikovDm » 29.07.2014 21:17:46

zub писал(а):В делфи для record`ов доступны виртуальные методы? зачем тогда новые record`ы если есть старые object`ы?


Да, вы правы, полез смотреть доки по Delphi и обнаружил, что в record не поддерживаются виртуальные методы. Я почему-то думал, что можно... Век живи, век учись. :D

Добавлено спустя 3 часа 17 минут 54 секунды:
Дож писал(а):Каждый отдельный экземпляр класса нужно выделять в куче. Часто возникает необходимость создавать объекты на лету («на стеке») или создавать много однотипных экземпляров в коллекции, в этих случаях использование объектов эффективнее.

Пытался понять в чём будет выражаться эта эффективность, если вы собираетесь использовать "фабрику классов"? Вы точно уверены, что накладные расходы для "фабрики классов" работающей с объектами будут в данном случае меньше чем при использовании виртуальных конструкторов классов? При этом и "на стеке" и в коллекции вы средствами штатного компилятора ничего создать не сможете, поскольку в момент компиляции конкретный тип объекта-наследника ещё не известен. Соответственно, будете использоваться всяческое "шаманство" с ассемблером и прочим (что мы уже наблюдаем в имеющихся примерах).
Вопросы, которые при этом возникают:
1. Насколько эффективнее будет подобное "шаманство" с объектами, чем использование классов?
2. Из чего следует, что аналогичное "шаманство" нельзя провести с классами, заставив их находиться "на стеке", например, через свой менеджер памяти?
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Re: Параметризовать конструктор

Сообщение Дож » 30.07.2014 11:30:12

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

Да, конечно.

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

Смогу, если у меня в наследниках нет новых данных и нет новых виртуальных методов.

Я в стартовом посте писал, что «вполне осознаю опасности, связанные с непрямым вызовом конструктора».

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

Вы невнимательно читали тему, уже найдено готовое решение:
Код: Выделить всё
uses
  Objects;

type
  TMyObject = object
    constructor Init;
  end;

constructor TMyObject.Init;
begin
end;

var
  O: TMyObject;

begin
  CallVoidConstructor(@TMyObject.Init, @O, TypeOf(TMyObject));
end.


CallVoidConstructor можно реализовать самостоятельно и ассемблер для этого не требуется (см. http://www.freepascal.ru/forum/viewtopic.php?p=81947#p81947).

2. Из чего следует, что аналогичное "шаманство" нельзя провести с классами, заставив их находиться "на стеке", например, через свой менеджер памяти?


Не из чего. Может быть и можно, но зачем? Мне не хочется мудрить с подменой системного МП, который должен будет догадываться когда создавать объекты на стеке, а когда — нет, в то время, как задача вполне себе алгоритмическая и решается алгоритмически вне зависимости от используемого МП.

Про «на стеке» я отвечал на вопрос почему предпочитаю object'ы, а не классы. А конструктор-параметр хочу применять для одинаковых объектов (но различных в поведении) в коллекции, память под которые выделена сразу в большом количестве.
Аватара пользователя
Дож
энтузиаст
 
Сообщения: 899
Зарегистрирован: 12.10.2008 16:14:47

Re: Параметризовать конструктор

Сообщение Vapaamies » 31.07.2014 01:22:43

MylnikovDm писал(а):Если вы не знаете, конструктор какого объекта вам на самом деле придёт, то вы не можете выделить необхдимое количество памяти на этапе компиляции. Только в runtime динамически "из кучи". Соответственно, все объекты становятся исключительно указателями. Какие ещё есть варианты?

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

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

Стоит лишь захотеть решать задачи.
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 291
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Параметризовать конструктор

Сообщение MylnikovDm » 31.07.2014 12:31:36

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

Вот это точно не будет ни быстрее, ни удобнее. Сейчас вы будете терять только при выделении памяти под объект из кучи, а если сделать обращение ко всем полям через аналог VMT, то вы будете иметь накладные расходы при каждом обращении к любому полю данных внутри класса.
Да и если уж на то пошло, то смещение полей в теле объекта вообще нет смысла хранить, поскольку при наследовании и добавлении новых полей в наследниках смещение существовавших до этого полей не изменяется. Вопрос не в смещениях, а в том, сколько выделять памяти под размещение данных объекта. Именно поэтому не получается разметить эти данные на стеке в момент компиляции, поскольку реальный объект может оказаться наследником, которому требуется больше памяти. Опять же, каким образом вам в этом сможет помочь предложенная вами таблица смещения полей в объекте? Кроме того, есть RTTI, коорая раньше создавалась только для published полей, а сейчас, если мне не изменяет память, после введения механизмов связывания, в последних Delphi она создаётся для всех полей. Там и смещение, и размер, и тип, и много ещё чего есть. Вот только рамзещать объекты на стеке или в коллекциях и массивах это никак не помогает.

Дож писал(а):Смогу, если у меня в наследниках нет новых данных и нет новых виртуальных методов.

А в этом случае вам весь этот механизм не нужен, поскольку прекрасно будет работать тупое жёсткое преобразование типа объекта к нужном классу/объекту. Раз не новых полей данных, не будет выхода за пределы памяти объекта. Раз нет новых виртуальных методов, то вам не нужна VMT, а значит и подстановка нужной функции для обработки на этапе исполнения. И, если честно, я вообще не понимаю, зачем вам тогда ООП? Каким образом вы собираетесь менять поведение ваших объектов, если не используете виртуальных функций? Статические функции обрабатываются на этапе компиляции, поэтому нет смысла городить огород с фабриками классов и прочими механизмами. Все равно это не будет работать. Если у вас в коде функции компилятор будет считать, что у вас объект класса TList, всегда будет вызываться невиртуальный метод Add для класса TList, даже если вы исхитритесь и подсуните ему во время исполнения вместо TList свой новый наследник TIntegerList.
MylnikovDm
постоялец
 
Сообщения: 103
Зарегистрирован: 15.02.2007 21:26:10
Откуда: Челябинск

Пред.След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16

Рейтинг@Mail.ru