| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Религиозные войны > Изменить синтаксис паскаля(делфи) |
| Автор: Burka 30.5.2008, 15:17 |
| А можно ли изменить сам синтаксис языка в компиляторе или где нить там ? я вот например хочу поменять begin на {, а end на }. (а коментарии сделать так : /*...*/ ) Реальноли это? если да, то где это менять? |
| Автор: Bose 30.5.2008, 15:25 |
| В компиляторе нереально. Но можно попробовать поюзать препроцессоры, которые будут преобразовывать твой синтаксис к стандартному. Нагуглил парочку: 1) http://deex.delphist.com/indexru.htm 2) http://andy.jgknet.de/dlang/ |
| Автор: Burka 30.5.2008, 22:23 |
| Спасибо, попробовал Deex, но че то результат не порадовал, не удобно очень, компилировать постоянно через батник. |
| Автор: Snowy 30.5.2008, 22:57 |
| Ну это не С++ Паскаль - язык строгий. Вольностей не позволяет. Так что только через внешний препроцессор, компиляция сторонняя, проверка синтаксиса отсутствует. Паскаль не терпит подобных извращений. Он от рождения строг и консервативен. Как английский лорд обязан говорить на безупречном британском, так и программист на языках Вирта должен создавать чёткий, недвусмысленный код. Такова суть строгих языков - не допускаются никакие разночтения. А все кустарные поделки - кустарно и работают. Если хочется лепить что попало и как угодно - это вам к плюсам. Дельфи вольностей не допускает. Это строгий и чёткий язык. |
| Автор: mr.Anderson 30.5.2008, 23:43 |
| Snowy, точно, и в этом плюс Паскаля! Я подобными извратами занимался на Сях. Там это дело легко решается макросами. |
| Автор: aktuba 31.5.2008, 00:03 |
| Изменять синтаксис Delphi на синтаксис C++ - бред... Синтаксис Delphi - один из главных плюсов перед С++! Хочешь использовать Delphi с синтаксисом плюсов - Borland C++. А вообще - для мазохистов есть отдельные форумы. |
| Автор: Burka 31.5.2008, 00:41 |
| Snowy, в каждой строчке одно и тоже написано я не хочу менять синтаксис делфи на синтаксис си, я просто хочу заменить слова бегин и энд на скобочки потому что они меньше места занимают, с ними намного было бы удобней. А ни у кого нет исходников компилятора делфи? |
| Автор: aktuba 31.5.2008, 01:10 | ||
Эх... Нарываешся на минуса... begin...end - это то, что удобно программистам Delphi. Не нравится - используй Borland C++. И хватит тут бред писать! |
| Автор: Burka 31.5.2008, 02:47 |
| aktuba, а толку от этих минусов плюсов, жизнь перевернется как будто если меня тут заминусуют. Вообще не я начал тут бред разводить, а те кто начал филосовствовать про строгость консервативность и тп. я задал вопрос и я хочу получить на него ответ, мне все равно что об этом думают другие, нравятся бегины пишете наздоровье, зачем только мне вбивать необходимость этих эндов. |
| Автор: Mayk 31.5.2008, 05:35 |
| Со скобками есть проблема. При компиляции сторонних .pas файлов могут возникнуть Серьезные Проблемы из-за того что {комменты} будут третироваться как код. Ищи free pascal compiler или gnu pascal compiler. Можешь ещё попробовать настроить Текстовой Редактор чтобы по нажатию на { вставлялось begin и по нажатитю на } - end. Правда удалять их одной клавишей затрундительно. ps. В мире есть ровно http://en.wikipedia.org/wiki/Editor_war: это vi(ныне его отпрыск vim) и emacs. Остальное - [flame mode] Как жалок язык что синтаксис является его одним из главных плюсов перед с++. БУГАГАГА. [/flame mode] |
| Автор: aktuba 31.5.2008, 08:24 | ||
Жалок не язык, а тот кто не умеет им пользоваться по назначению, пытаясь переделать, либо тот, кто не понимает плюсов языка. БУГАГАГА. |
| Автор: Alexeis 31.5.2008, 10:10 |
Я тоже не согласен. Delphi язык более высокого уровня абстракции, потому за синтаксисом стоят горы невидимого кода, который генериться автоматически. Синтаксис лишь уменьшает число ошибок за счет своей строгости. |
| Автор: Lazin 31.5.2008, 10:30 | ||
| Господа паскалисты, что вы понимаете под "строгостью" синтаксиса. Просто я впервые вижу? что-бы данный эпитет применялся к синтаксису языка. С++ - язык со статической строгой типизацией, все проверяется в compile time, причем даже такие мелочи как возможное несоответстие размера указателя размеру переменной в которую его записывают в случае перехода на 64х битную платформу. Добавлено через 29 секунд
|
| Автор: JackYF 31.5.2008, 10:50 |
Аналог boost::lambda уже появился? |
| Автор: Lazin 31.5.2008, 11:06 |
| Alexeis, ты не отвечаешь на мой ответ © , у тебя разрыв? |
| Автор: Alexeis 31.5.2008, 13:30 | ||
Я что маньяк круглые сутки сидеть на форуме Хочешь пример?
Попробуй после это скомпилировать любую программу. Синтаксис не просто может меняться, его можно превратить во что угодно, так что потом не найдешь концов. Потом посмотри чего можно замутить в операторе if . Это ж форменное безобразие! Таких опасных фич. в синтаксисе десятки. Например структуры. Нет ни какой гарантии что они будут бинарно совместимы с чем нибудь. По правилам структуру можно пронаследовать от класса Сравни с Delphi Record! Структура без возможности наследования, безо всяких виртуальных функций и деструкторов, чистые бинарные данные в строгом порядке. Можно создавать в стеке, по дефолту ни чем не инициализируется. Все четко и по делу. На счет фигурных скобок, опять же они мелкие и плохо заметные, постоянно путаешься какая скобка от какого блока. Посмотри на синтаксис switch, не дай бог забыть break после очередного case. Идем дальше операторы цикла while. На кой черт он вообще сдался в С++ если есть цикл for, который его заменяет на 100%, намного лучше его и логичнее, включает в себя секцию инициализаций, секцию условий и секцию для пост операций преимущественно для инкремента счетчиков. Макросы - еще одно жуткое изобретение при наличии инлайн функций. Какое количество трудноанализируемых ошибок можно сделать на них! Межмодульное связывание extern Объявление функций классов. Можно запросто объявить функцию и ни где ее не реализовать. И это будет правильно. Я согласен, что все это можно не использовать когда программу пишешь сам, но реальность такова, что помимо написания новых программ нужно осуществлять поддержку старых написанных другими людьми с их естественной кривизной рук. Уверяю тебя такого безобразия на Delphi встретить нельзя. |
| Автор: Lazin 31.5.2008, 14:42 | ||||||||||||||||||
| ну во первых, вся эта чертовщина унаследована от С, во вторых иногда это бывает нужно эдакое самоубийство
структура и класс в С++ это примерно одно и то-же, что-бы гарантировать бинарную совместимость, нужно просто учитывать выравнивание к то-му-же никто не мешает использовать включение вместо наследования а что если он там и не нужен?
я им пользовался за всю жизнь 2 раза
зато пользователь класса видит только интерфейс класса, а не реализацию, намного меньше зависимостей в коде, например foo.h
или foo.h
foo.cpp
пользователь подключает только Foo.h, но в первом случае он неявно подключает кучу других заголовочных файлов. во втором случае можно забыть реализовать ф-ю, но эту ошибку легко найти а как-же славные традиции писать программу в обработчиках событий |
| Автор: nerezus 31.5.2008, 15:10 | ||||||||
лезть в этот разговор не хотел, но прямо таки интересно стало ) P.S. ну раз все равно залез, то: C++ - это гибкость. Pascal - это строгость. Естественно гибкий язык имеет бОльшие возможности, но строгость - тоже хорошо. Например мне нравится делфи во всем, кроме синтаксиса паскалеподобного. Именно за строгость и однозначность.
Причем везде. Самое сложное - это не разгребать код, а алгоритм. Сложно сть несоизмерима ;) Так что разбор кода будем считать меньше погрешности. |
| Автор: Mayk 31.5.2008, 15:56 | ||||
надеюсь что нет Если это появится раньше полноценных замыканий/лямбд в дельфи (кстати как с этим в дельфи.нет?) то это смерти подобно Добавлено через 59 секунд Жестокой! Беспощадной! Безжалостной смерти! Добавлено через 9 минут и 48 секунд А может разделим эту эпическую тему и половину выкинем нафик в релвойну к подобному треду? На дельфи полно другого безобразия. Из запомненго мною локальные ф-ции, которые должны были быть ф-циями класса.
И конечно же наименования элементов на форме(такая же феерия и на builder c++, да)
|
| Автор: Alexeis 31.5.2008, 16:13 | ||||||
Если он не нужен, то должна быть команда сквозного прохода. В С++ любят так делать. Фича используется в 1% случаев, а предусматривать обход нужно в остальных 99% случаев. А мне приходиться дорабатывать софт где такие экстерны исчисляются десятками. Это не самоубийство а пример того как опасны средства С++. Понятно что это вырожденный пример, но вред такого характера могут нести макросы. На счет возможностей языка. Попробуйте на С++ создать класс у которого будут 2е виртуальные функции с одним именем и одинаковым перечнем параметров или реализовать интерфейс без использования виртуальных методов, попробуйте делегировать реализацию интерфейса объекту члену класса. Или создать объект по его строковому имени. Можно ли в С++ вызвать функцию зная только ее имя (строка). Может ли статическая функция быть виртуальной? В Delphi можно реализовать полноценный Singleton вообще не создавая экземпляра класса. Как видите тонкими механизмами делфи не обделен тонкими механизмами, при этом он более логичен. Взять хотя бы циклы. Из 3х циклов нет ни одного лишнего. Цикл for только для целых и перечисляемых типов, цикл While с предусловием цикл Repeat с постусловием. Оператор выбора простой и очевидный. Если это функция так она и называется функцией, процедура называется процедурой. Если объявляется переменная, то будь добр пиши var, перешел к объявлению типа пиши type. А то объявил переменную фиг знает где, потом скопипастил код и закрыл имя переменной из внешней области. Теперь пройдусь по массивам. В С++ некоторые вместо нормального a[i] умудряются писать *(a + 1), плюс в сочетании. Массив - указатель палка о двух концах. В функции никак не возможно определить что тебе передали массив или указатель. В Delphi строго, если передаешь указатель, то это указатель, если массив, то это массив. Так что строгости в любом случае больше. Добавлено через 4 минуты и 2 секунды
Это механизм аналогичный блокам в С++. В каждой локальной функции могут быть свои локальные переменные, при этом она видит переменные из внешней функции. Просто это блоки определенные до их использования. Вполне себе рабочий механизм, правда в ООП уже малоэффективен. |
| Автор: Lazin 31.5.2008, 17:44 | ||||||||||||
это как? как компилятор будет определять какую из них вызывать?
на то нам и дан паттерн NVI
легко
да, рефлексии у нас нет
ну просто ты привык к нему, вот он и кажется логичным, мне например не понятно, почему функция и процедура, это разные вещи... Да, в С++ много чего нет, но... что-бы было если бы у бабушки был член... наверное она бы была не бабушкой а дедушкой так и здесь, будь в с++ рефлешн, интерфейсы и прочие фишки делфи, то это был бы другой язык |
| Автор: nerezus 31.5.2008, 17:56 | ||
|
| Автор: Alexeis 31.5.2008, 19:01 | ||||
В таком как в примере это никому и не нужно. При наследовании виртуальной функции, можно запретить предкам начиная с определенного колена вызывать виртуальную функцию того класса, который реально создан. Т.е. в одном из наследников вводиться новый виртуальный метод, точно такой же как и прежний, но с директивой reintroduce, после чего в таблицу VMT вводиться новая запись, а старая остается. Т.о. можно добиться разных действий, в зависимости от того к какому из предков был приведен объект. Довольно тонкий механизм, но в VCL используется. Статические виртуальные функции используются при приведении классов наследников к классам предов (не путать с приведением объектов). Фактически для класса создается своя таблица VMT. На счет синглтона. В Delphi каждая статическая функция получает один неявный параметр как и обычная, но это не указатель на объект, а указатель на класс, т.е. ведет себя точно также как и обычная, можно определять статические поля, виртуальные статические функции, которые в наследнике перекрываются. Класс может иметь свои свойства, точно также как объект. Можно создать сколько угодно переменных класса и при этом это всегда будет тот же самый класс. Объявляется тип класса точно также как и обычный.
При этом он является классом обычных объектов, в том смысле, что создает объекты и объекты этого класса имеют доступ ко всем статическим полям и функциям.
Смотри при выходе из процедуры в Delphi ты пишешь exit, т.е. выхожу, в С++ тоже самое действие будет называться "возвращаю ничего". Код Delphi самоописателен. Чисто виртуальная функция пишется и директивой abstract, перекрыл функцию пиши override. Вызываешь виртуальный метод предка из перекрытого пишешь Inherited. Это по любому более читабельно, чем если ничего не писать. Мне кажется совместимость с C сильно испортила язык С++. Можно было обойтись раздельной компиляцией. Билдер, например, может скомпилировать код делфи, код C++ и слинковать в один исполняемый файл. И ни каких проблем. |
| Автор: MAKCim 1.6.2008, 11:44 |
| Alexeis, 1. в Delphi объекты классов можно создать в стеке? 2. можно ли определить свой аллокатор для класса? (аналог перегрузки new в С++) 3. есть ли аналог спецификатора volatile? 4. есть ли аналог элипсисов? (оператор ...) 5. можно ли создать массив в стеке с неконстантным значением числа элементов? (типа int array[count], где count - не константа) 6. есть ли аналог объединений? (union) 7. есть ли аналог mutable-полей? 8. есть ли возможность метапрограммирования? 9. есть ли аналог виртуального наследования? 10. есть ли встроенная поддержка комплексной арифметики? 11. есть ли аналог спецификатора restrict? |
| Автор: Lazin 1.6.2008, 12:32 |
| 12. есть ли аналог ссылок 13. есть ли аналог модификатора const для параметров функций 14. есть ли спецификации исключений 15. какие возможности управления временем жизни объектов в стеке 16. можно-ли на Delphi реализовать функтор 17. можно-ли реализовать смарт-поинтер 18. можно-ли реализовать сборку мусора, используя только возможности стандартных библиотек как уже задолбал этот холивар, Delphi-программисты не понимают что дают возможности языка С++, какие паттерны можно реализовать и тд. например идиома RAII, без нее очень сложно пользоваться исключениями... но в паскале это невозможно, так как там объекты классов не создаются в стеке, можно конечно сделать то-же самое с помощью finaly(наверное???), но это уже совсем не то, ведь это делается вручную а компилятор С++ делает такие вещи сам. Конечно делфи для чего-то то-же хорош, наверное, но для чего конкретно я не знаю |
| Автор: Alexeis 1.6.2008, 12:49 | ||||
Только классические паскалевские (не VCL ские)
Угу. Не знаю че за хрень 4. есть ли аналог элипсисов? (оператор ...) Тоже ни знаю че такое угу Не знаю че это такое Аналогично, звучит как-то абстрактно Тоже не слышал че такое ... Бр... надоело ты бы пояснял хоть что это такое, а то ведь термины могут отличаться.
Не я его начал. Ты бы видел как изящно реализуются многие паттерны на Delphi. С++ просто нервно курит в сторонке. |
| Автор: MAKCim 1.6.2008, 13:13 | ||||||||
грубо говоря запрет кэширования переменной
компилятор не будет использовать регистр для хранения variable в цикле, т. е на каждой итерации будет осуществляться чтение variable функции с переменным числом параметров
поля класса, которые можно изменять для константного объекта можно ли в Delphi вычислить факториал константы во время компиляции?
требуется создать класс D, унаследованный от B, C, и при этом B, C, D будут использовать один и тот же объект A Добавлено через 3 минуты и 19 секунд
перегрузка глобального new и boost threads? (хотя boost threads вроде пока не стандартная) Добавлено через 7 минут и 37 секунд плохо да и вообще, как-то паскаль и делфи не сильно со стеком дружат |
| Автор: Alexeis 1.6.2008, 14:04 | ||||||
Это вообще, не имеет отношения к языку. Скорее директива определенного компилятора. Делается, но несколько иным образом через array of const, при этом число параметров получается автоматически. Кстати в С++ нельзя получить число элементов динамического массива, типа High(mas) В этом смысле существует несколько другой механизм. Механизм ReadOny и WriteOnly свойств, ограничивающих возможность изменения состояния объекта.
Класс будет использовать объект
Очень деже неплохо, стековые объекты нарушают концепцию безопасности ООП в Delphi. Этот механизм неэффективен для больших объектов, а маленькие стековые объекты есть, это Record. Все четко разделено. Объект маленький - делай Record это будет быстро + копирование по значению, большой - делай в куче. |
| Автор: W4FhLF 1.6.2008, 14:25 | ||||
Часть стандарта.
Можно пример? Мне кажется, что использование массивов к эллипсису никакого отношения не имеет.
Для этого, в прицнипе, и существуют стандартные STL-контейнеры. Нет, на самом деле всё просто. Обычное наследование: ![]() Виртуальное: ![]() |
| Автор: Mayk 1.6.2008, 14:34 | ||||
Да? А std::vector<t>::size() для кого? Добавлено через 4 минуты и 3 секунды Кстати в паскале нельзя вычислить факториал в compile time. ps. а в си++ нельзя вычслить синус -
но тссс, это секрет. |
| Автор: Alexeis 1.6.2008, 14:53 |
Так это ж класс... |
| Автор: vinter 1.6.2008, 15:05 |
это стандартная замена массива |
| Автор: Любитель 1.6.2008, 17:21 | ||||||||||||||||||
ИМХО Дельфям глубоко плевать на ФП.
Смысл непонятен. Только проблемы ИМХО
Стоп. А в Дельфи разве есть статические поля? В С++ они унаследованы от С, потому в оч недобном виде. Ими, по-моему, никто не пользуется (в плюсах). Записи с вариантами? Дык множественного ж вроде нет - зачем виртуальное?! Немного оффтоп. Какие компилеры на сегодня юзают рестрикт для оптимизации? Да - const
Delphi .Net?
AFAIK только глобально. Разве я не прав? Эт которые с object вместо class? Если да - тогда фтопку, точно не помню, но помню, что это нечто кривое и недоделанное
А какое отношение это имеет к mutable?
Нелогично
Нетипизрованный массив, если я правильно понял, как-то можно в дельфях передавать в функцию. Как затем юзать - фиг его Ну, в С++ тоже много чего нельзя в компайл-тайм (не тот язык всё-таки) - так что кодогенераторы рулят Насчёт виртуальных конструкторов и виртуальных статических методов - респект. Гуд ЗЫ Блин, хорошая вещь холивары |
| Автор: Rrader 1.6.2008, 17:41 | ||||||
В справочной системе приведен пример:
Для последней версии Dephi можно для прохода использовать оператор for..in..do
Прямого аналога нет, но для вызовов функций, там, где в С++ любят использовать ссылки, используется оператор @ |
| Автор: W4FhLF 1.6.2008, 18:04 |
Действительно, хорошая штука |
| Автор: Alexeis 1.6.2008, 18:57 | ||||
Неправ, память для классов выделяет виртуальная статическая функция, которую можно переопределить для любого класса и все наследники этого класса автоматом будут использовать ее для выделения памяти, потому что конструктор в Delphi это статическая функция класса с дополнительными скрытыми вызовами.
Ну не то чтобы кривое, просто старый механизм. Есть целая библиотека KOL которая живет этим механизмом, код получается самый чистый и маленький, они то как раз ближе всего к классам С++. Как я понял это механизм ограничения доступа к полям данных. Тут оно работает несколько другим образом. Доступ к свойству можно ограничить или расширить в наследнике, передавая объект как предка. В отличие от С++, здесь можно свойство поднять из private в public, при необходимости в наследнике расширить доступ к свойству или функции. Нельзя требовать от языка, чтобы он полностью повторял механизмы другого. В замен одного механизма может быть совершенно другой или два заменяют один. Соответвтенно алгоритмы и структура программы строиться по другому. Так вот ограничить часть свойств так чтобы их нельзя было изменить при передаче в функцию возможно. Что именно нелогично? То что если внутри объекта возникнет исключение, то вся динамическая память которая была выделена до того повиснет ввиде утечки? Это логично? Или логично, то что проверка принадлежности указателя на базовый класс к наследнику при помощи is пройдет, а попытка использования базового как наследника при помощи as провалиться в исключение, потому что видите ли это не первый базовый класс, а лишь второй, а второй базовый уже для этого не годиться. Или то что при присваивании стековых объектов поля копируются лишь бинарно, потому все внутренние объекты созданные в куче будут одним, а потом, когда уничтожат второй объект, деструтктор упадет на AV потому что объект поле был у них общим и его уничтожил первый владелец, а второй уже удаляет мусор. Чего дальше перечислять все особенности "безопасной" работы с объектами в С++? Или все таки согласишься, что большой объект должен иметь встроенные механизмы безопасности, а простой можно создавать хоть у черта на рогах. Будте уверены, что создание объектов в куче это не глупое ограничение, а серьезный механизм безопасности и исключения случайных ошибок при работе с памятью. Добавлено через 2 минуты и 15 секунд
var параметр это как раз такой параметр, который передается по ссылке, а @ это аналог & |
| Автор: Burka 1.6.2008, 19:11 | ||||
Mayk, спасибо за максимально полный ответ и за то что он по теме =)
да, я думал над этим. я бы написал программку которая конвертирует исходники под мой синтаксис, это не сложно.
Как вариант подходит, но крайне удобно перед каждой компиляцией это проделовать. даже через батник будет не то Еще подумаю может чего придумаю. |
| Автор: skyboy 1.6.2008, 19:44 | ||||
вот-вот. делаешь внешний препроцессор в виде расширения ide и подключаешь к среде разработки ;) уж извини, для таких экзотических требований готовых решений либо нет, либо совсем уж никому неизвестные.
ну, скажем так: после привычной модели штука выглядит... .ээээ... коряво. но если уж сильно хочется иметь в стеке объект - то решение есть. разве нет? статические методы есть и в 6(насколько помню, работать начал с 7-ки). статические поля, насколько помню, уже в BDS 2005 есть. кстати, об этом узнал от Alexis'a, так что он точно скажет. |
| Автор: MAKCim 1.6.2008, 19:45 | ||||||||||||||||||||
это, как уже заметили, стандарт в низкоуровневом коде volatile встречается повсеместно
потому что в С/С++ нет понятия динамического массива нет вообще динамических массивов есть указатели указатели относятся к простым типам данных я даю 95%, что динамический массив в Delphi - это ни что иное, как объект соответствующего класса, только он завуалирован синтаксисом Delphi, т. е по сути является встроенным приведи ассемблерный листинг функции, работающей с динамическим массивом, сразу все станет видно
не то вот пример mutable
скажем так, при создании объекта D, создается только один объект A больших это сколько?
а если объект маленький, но структурой не представим (нужна семантика класса)? не гибко и притянуто за уши
GCC
а причем здесь стек и куча? если объекты в куче выделяются ничего не повиснет?
это все от того, что в Delphi нет конструкторов копирования, перегрузки operator= и т. д в С++ настраивается любое поведение
это именно глупое ограничение (читать абзац выше) |
| Автор: Burka 1.6.2008, 20:36 |
| skyboy, расширения ide - ты имеешь виду что то типа плагина делать для делфи или просто прогу отдельную. И вообще как плагины делать? Где про них понятней написано? |
| Автор: Alexeis 1.6.2008, 21:28 | ||||||
Он может все кроме того что связанно с наследованием, даже больше. Большие это те которые содержат вложенные или пронаследованы, т.е. включаются опасные механизмы. Все равно не ясно, зачем создавать 2 объекта, при наследовании и так создается только 1 объект В наследник A, объекту A не зачем создаваться, это же наследование, а не композиция.
Это часть общего механизма безопасности объектов. Если объект создается в стеке, то его конструктор вызывается в неопределенное время и деструктор тоже, потому его нельзя поместить в блок try...except и правильно отработать исключения. Аналогично происходит в случае глобальных объектов. Кроме того объекты в C++ не инициализируются нулями, потому при возникновении исключения в конструкторе, нельзя вызвать деструктор, так как в последнем невозможно узнать какие из вложенных объектов уже были созданы и соответственно уничтожить только их, ведь если в объекте мусор, то указатели не нулевые. Исключение в конструкторах для Delphi это не критическая ситуация, а механизм сигнализации о неверных параметрах.
Все в Delphi есть, но дело не в том что можно все сделать правильно, а в том, чтобы язык не давал лишней возможности для возникновения трудно анализирумых ошибок. Можно все делать правильно, но факт остается фактом, что ошибки в программах исправляются годами и количество совершаемых в средней программе исчисляется сотнями, потому задача языка свести к миниму возможности появления. При разработке программы не исходят из того, что в ней не будет ошибок, порядочный программист при написании программы должен понимать что ошибки будут, однозначно будут, их не избежать и нужно так спланировать написание ПО, чтобы все ошибки легко находились, поэтому безопасность ООП это не последнее дело в программировании. Глупо надеятся что можно писать идеальные программы без ошибок с идеальной структурой, где предусмотрено все на все случаи жизни. |
| Автор: Lazin 1.6.2008, 22:24 | ||||||||||||||||||
я понял в чем твое заблуждение, на самом деле все происходит немного не так как ты думаешь. стандартом четко определен порядок создания и удаления стековых объектов, в С++ порядок вызова деструкторов всегда противоположен порядку создания объектов
стек, он на то и стек, что-бы все работало по принципу FIFO если где нибудь в функции возникнет исключение, то стековые объекты будут удалены в порядке обратном их созданию часто в С++ делают так, например есть класс Mutex - который работает как мьютекс
обычный способ его использования
если между вызовами enter и leave, произойдет исключение, то это приведет к блокировке программы, все встанет колом так вот, можно описать такой класс
это все)) теперь в коде можно писать вот так
исключения в конструкторах в С++ - нормальное явление, деструкторы для полей объекта вызываются, следуя все тому-же принципу... и вообще там все происходит намного интереснее чем ты думаешь, инициализация нулями отношения к делу не имеет никакого =) Добавлено через 3 минуты и 21 секунду
конструкторы копирования и операторы присваивания, никогда небыли источником ошибок
модульные тесты не помогают? |
| Автор: skyboy 1.6.2008, 23:24 |
| господа, а почему, собственно, обсуждение не продолжается в http://forum.vingrad.ru/forum/topic-175814.html?! зачем нам клоны? |
| Автор: Любитель 1.6.2008, 23:57 | ||||||||||
Вообщем-то да. Компилер вставляет вызовы внутренних функций рантайма. Даже присваивание для них переопределено (работает reference counting, в частности).
+1
Красиво сказал
А чем эт они опасны?!
Новая эпоха Хотелось бы узнать - что там со статическими полями? В современной дельфе. Для общего развития |
| Автор: skyboy 2.6.2008, 01:36 |
даже во FreePascal http://community.freepascal.org:10000/bboards/message?message_id=238369&forum_id=24082 Добавлено через 4 минуты и 20 секунд к примеру, http://forum.vingrad.ru/index.php?showtopic=147455&view=findpost&p=1110291 Добавлено через 5 минут и 19 секунд оказалось, я все же не от Alexis'a http://forum.vingrad.ru/index.php?showtopic=145750&view=findpost&p=1097256 про static-поля |
| Автор: Любитель 2.6.2008, 02:32 |
| Понятно. Буду знать |
| Автор: nerezus 2.6.2008, 06:03 | ||
|
| Автор: MAKCim 2.6.2008, 09:14 | ||||||||||||
структура (record) может содержать методы?
ничего опасного нет при условии, что язык позволяет осуществлять полное управление жизненным циклом объекта
у нас наследование не обычное без виртуального механизма будет создано 2 объекта A: по ветке B и ветке C ладно, проехали, как тут уже сказали, в Delphi нет множественного наследования
читай пост Lazin от себя замечу, что как я и предполагал, плохо и непродуманно Delphi работает со стеком кроме того, я не получил ответа на вопрос: как куча в Delphi предотвращает возникновение приведенных тобой "проблем"? тем, что ты явно вызываешь конструктор/деструктор? извини конечно, но такой подход еще больше увеличивает вероятность ошибок
а вот здесь уже на вкус и цвет...
глупо но и строгость не панацея |
| Автор: Alexeis 2.6.2008, 10:06 | ||||||||
Lazin, вот пример
Как в этом случае спасти объект b? Его член member при создании вызвал исключение и вышел аварийно, требуется отработать эту ситуацию и пересоздать объект member или вообще отказаться от него.
Привожу пример.
Все члены member1, member2, member3 повисли утечкой, хотя память выделенная под b будет возвращена в кучу. Если бы объект b был предварительно занулен, то для очистки member1 - member3 можно было вызвать деструктор ~b, а так это сделать невозможно, потому что в этом случае возникнет исключение в деструкторе на строчке delete member4; и настанет полный северный пушистый зверек, поэтому в С++ при возникновении исключения в конструкторе никогда не вызывается деструктор.
Источник ошибок не он сам, а его отсутствие по недосмотру. Его просто нужно делать, но не всегда, пока объект простой он может быть не нужным, но в определенный момент при расширении объекта неожиданно поле член заменяется на указатель, все красиво, оно создается в конструкторе, уничтожается в деструкторе, но теперь для копирования такого объекта уже необходим конструктор копирования. Вот этот момент как раз неочевиден, ведь структурно класс почти не изменился. Вот это и называется опасный код, не интуитивный код, который приводит к возникновению ошибок. nerezus, см. ниже после этой фразы, метакласс обладает практически всеми возможностями объекта + синтаксически похож на объект, он сам и есть Синглтон по определению. Да, в том числе конструкторы с параметрами, свойства и даже операторы. |
| Автор: skyboy 2.6.2008, 10:26 |
есть. но объявления(интерфейса), а не реализации. через абстрактные классы - т.н. interface это к обсуждаемому виртуальному наследованию не относится, но уже столько раз звучало про "отсутствие множественного наследования", что не смог промолчать. |
| Автор: Lazin 2.6.2008, 10:39 | ||||||||||||
создай объект в стеке и вставь в конструкторы - деструкторы брейкпоинты, и ты увидишь что в этом случае деструкторы вызываются если-бы obj был смарт поинтером, например shared_ptr-ом, то и в твоем примере все будет нормально удалено Добавлено через 3 минуты и 25 секунд
опять-же, здесь поля объекта - голые указатели, поэтому память освобождена не будет, если-бы это были объекты, то деструкторы были-бы вызваны... если-бы здесь поля member были-бы смарт поинтерами, то все было-бы корректно удалено Добавлено через 9 минут и 27 секунд если написать это развернуто, то получится вот что
во время раскрутки стека вызываются деструкторы сконструированных объектов в порядке обратном их созданию, тоесть
если member - голый указатель, то ничего не удалиться, так как у POD типов нет деструкторов, а если смарт поинтер, например auto_ptr, то его деструктор вызовет delete для объекта, который он содержит |
| Автор: Alexeis 2.6.2008, 11:14 |
| skyboy, все верно, но это опять же сделано специально, так как множественное наследование опасный механизм, приводящий к возникновению неочевидных ошибок. Наследование интерфейса это не тоже что наследование класса, так реализация наследуется только от одного класса. |
| Автор: MAKCim 2.6.2008, 11:21 | ||
никто не заставляет им пользоваться, однако в случае необходимости Delphi будет курить по поводу стека, ответом Lazin удовлетворен? |
| Автор: Alexeis 2.6.2008, 11:22 | ||||||
Первый код был примером не для утечек, а для исключений. См. выше. Здесь невозможно отработать исключение, с утечками тут все ОК.
Выходит что без смарт поинтеров о безопасном программировании под С++ можно забыть. Видишь, а в Delphi объекты изначально создавались так чтобы они были с одной стороны простыми в работе, с другой, чтобы были безопасными. Добавлено через 1 минуту и 17 секунд
В случае необходимости алгоритмы пишут так чтобы обойтись без опасных механизмов. |
| Автор: MAKCim 2.6.2008, 11:24 |
| Alexeis, так ты все-таки на вопрос ответь? |
| Автор: Alexeis 2.6.2008, 11:25 | ||
Ни чуть. Статические объекты приводят к потере контроля над созданием объектов и невозможности отработки исключений.
Не услышал ни грамма по этой теме. Добавлено через 34 секунды На какой именно? |
| Автор: MAKCim 2.6.2008, 11:27 | ||||
исключение обработать можно
Добавлено через 1 минуту и 57 секунд
Добавлено через 14 минут и 3 секунды для реализации нужного тебе поведения нужно использовать указатель в этом вся гибкость С++: можно сделать и так, и так, в зависимости от требуемого поведения |
| Автор: Alexeis 2.6.2008, 11:45 |
Значит остается только опасное копирование по значению, могут быть и другие причины, которые мне неизвестны, но говорить сразу что это глупо излишне самонадеянно. Заметь от этого механизма отказалась даже Microsoft при разработке нового языка C#. Объекты в C# создаются только в куче. Кстати еще вспомнил момент связанный с интерфейсами. После освобождения интерфейса связанный объект должен немедленно уничтожен, а интерфейс ничего не знает создан ли объект в стеке или в куче и соответственно не сможет его удалить. |
| Автор: MAKCim 2.6.2008, 11:52 | ||
объект класса с pure virtual методами (применительно к С++) создать нельзя работа с такими классами осуществляется через указатели/ссылки, т. е через простые типы, а у них нет ни коструктора, ни деструктора это что касается семантики стека, т. е автоматического удаления при выходе из области видимости если удаление осуществляется через delete, то, определив в таком классе виртуальный деструктор, мы получим требуемое поведение (т. е удаление реального объекта) Добавлено @ 11:53 поведение управляемо через конструктор копий и operator= где тут что опасно? |
| Автор: Alexeis 2.6.2008, 12:02 | ||||||
Я не про него самого, а про его наследника. Наследник выполняет интерфейс (реализует его методы), одновременно он является сервером для интерфейса. Интерфейс же в свою очередь является клиентом и владеет минимальной информацией о структуре класса, но при освобождении интерфейса (интерфейсу присваивается nil) начинается подсчет ссылок на серверный объект, если число ссылок равно нулю, то серверный объект гарантированно уничтожается освобождая ресурсы. В этой схеме время жизни объекта сервера полностью контролируется клиентами. |
| Автор: MAKCim 2.6.2008, 12:09 | ||||
Alexeis,
на вкус и цвет... это проблема не языка, он предоставляет все возможности для безопасного написания кода твое дело ими пользоваться или нет
ну пожалуйста, оберни указатель классом и считай ссылки или пользуйся готовыми реализациями, из того же буста например Добавлено через 5 минут и 5 секунд пусть I - интерфейс, obj - объект класса, реализующего интерфейс выполнены следующие действия I a = obj I b = obj I c = obj где в этом случае расположен счетчик ссылок на obj? (в каждом из a, b, c?) |
| Автор: Alexeis 2.6.2008, 12:43 |
| MAKCim, я сейчас не говорю про интерфейсы, как о преимуществе, это уже подробно изжевали в старой теме. Тут я говорю про то что механизм интерфейсов находиться в противоречии с механизмом стековых (не динамических) объектов, так как у последних время жизни от входа в блок до выхода. Подсчет ссылок должен реализовывать объект. Все интерфейсы наследуются от IUnknown, который требует реализации методов подсчета ссылок (поскольку эти методы в нем объявлены). Интерфейс сам по себе не является сущностью. Он не имеет ни каких данных, это лишь протокол доступа к объекту, на деле являющийся чем-то вроде дополнительной таблицы VMT, которая расположена в объекте. Это и есть гарантия того что объект исполняет интерфейс. Добавлено через 1 минуту и 41 секунду точнее в объекте указатель на нее. |
| Автор: Lazin 2.6.2008, 12:54 |
| вот за это я и люблю С++, можно создать такой класс, объекты которого нельзя создать в стке, а можно только в куче, и наоборот.... и никаких тебе разговоров о том, что концепция стековых объектов плохо сочетается с концепцией интерфейсов и подсчетом ссылок |
| Автор: MAKCim 2.6.2008, 12:57 | ||
где ты нашел противоречие? приведи пример я правильно понимаю: класс, реализующий любой интерфейс, должен реализовывать методы подсчета ссылок? если так, на лицо еще один показатель "гибкости" |
| Автор: Alexeis 2.6.2008, 13:16 | ||||
Ни каких проблем, для этого есть предок в котором уже реализован IUknown.
Это возможность для появления ошибок, зачем тебе лишняя возможность появления ошибок? Гораздо лучше когда компилятор тебе не даст сделать глупость переведя ошибку из времени исполнения во время компиляции. Это известный принцип. Самые лучшие ошибки это те которые видны на этапе компиляции, потом идут те которые кричат о себе в RunTime, а самые вредные, которые молчат и тихо делают свое черное дело. |
| Автор: skyboy 2.6.2008, 13:26 | ||
да. типа CnPack или ModelMaker CodeExplorer. Впрочем, сам их не делал, потому не могу сказать наверняка, позволят ли они до компиляции неявно делать замену так, чтоб не надо было сохранять файл. |
| Автор: MAKCim 2.6.2008, 13:27 | ||||
в данном случае ни о каком создании объекта на стеке не может идти и речи т. к он уничтожится еще до того, как будет передан клиенту поэтому клиенту передается ссылка или указатель на динамически (или статически) созданный объект дальше нужно учитывать протокол взаимодействия клиента и сервера, а именно, кто ответственен за удаление объекта в общем я не вижу никакой опасности Добавлено @ 13:28
cтоп реализации методов в интерфейсе быть не может допустим у меня есть интерфейс I и класс C, реализующий I где будет реализация подсчета ссылок? |
| Автор: Lazin 2.6.2008, 13:32 | ||||||
а я и написал про этап компиляции, если к примеру перегрузить для класса операторы new delete, и сделать их закрытыми, то объект можно будет создать только в стеке
причем достаточно сделать закрытой только одну форму оператора new(delete), в этом примере такое
не прокатит |
| Автор: Любитель 2.6.2008, 13:36 |
Интерфейсы - это только COM?! |
| Автор: Alexeis 2.6.2008, 13:51 |
Ничуть. Интерфейсы прекрасно работают безо всякого COMa, но они просто совместимы с COM. COM нужен только для межязыкового взаимодействия. При работе внутри приложения написанного только на VCL или приложение + Dll, COM не участвует, работают лишь встроенные механизмы. |
| Автор: Любитель 2.6.2008, 13:56 |
| А с чего тогда любой интерфейс должен наследоваться от IUnknown? |
| Автор: Alexeis 2.6.2008, 14:00 |
| Lazin, я и не сомневаюсь, что на С++ можно написать Delphi, более того сам компилятор таки написан на билдере. Это все тонкие нюансы, которые не обязательно знать программисту на Delphi. У него есть хороший и главное ПРОСТОЙ инструмент, который много за него делает, причем делает скрыто. Это работает вне зависимости от того знает он что его объекты создаются в куче или не знает. В идеале ему вообще не нужно знать слова указатель. Программист Delphi должен проектировать программу при помощи паттернов, которые реализуются при помощи высокоуровневых средств ООП, которые работают стабильно. Важно не изобретать велосипедов, там где уже все поставлено на поток. |
| Автор: MAKCim 2.6.2008, 14:03 | ||
| Alexeis, ответь на мой вопрос
|
| Автор: Alexeis 2.6.2008, 14:03 |
Это происходит неявно вне зависимости от желания программиста. Если его не указать, то Delphi без спроса его туда скрыто пропишет. На этом основан механизм подсчета ссылок. Добавлено через 2 минуты и 40 секунд MAKCim, я уже писал, что интерфейс не самостоятельная сущность. Сам он ничего не умеет. Подсчет ссылок целиком и полностью лежит на объекте. |
| Автор: MAKCim 2.6.2008, 14:16 | ||
значит я обязан для каждого класса, реализующего любой интерфейс, определять методы подсчета ссылок? |
| Автор: skyboy 2.6.2008, 14:34 |
нет. можно вместо TObject наследоваться от TInterfacedObject. |
| Автор: Любитель 2.6.2008, 15:20 | ||
Вот я этого не понимаю. С чего это любой интерфейс должен включать методы, занимающиеся подсчётом ссылок? Не вариант. Множественного наследования реализации у нас нет. Появляется проблема в выборе TInterfacedObject или чего-то ещё, не наследющегося от этого класса. |
| Автор: nickless 2.6.2008, 18:51 |
| И не надоедает же об одном и том же спорить... |
| Автор: skyboy 2.6.2008, 19:13 | ||
не появляется. любой класс без указания явного предка - наследник TObject. TInterfacedObject - прямой потомок TObject, ничего, кроме реализации подсчета ссылок, к предку не добавляющий. Зачем вместо TInterfacedObject использовать TObject, если они идентичны за исключением подсчета ссылок? Только ради проблем? |
| Автор: Alexeis 2.6.2008, 19:54 |
| nickless, не об одном. Акценты смещаются. |
| Автор: Mayk 3.6.2008, 04:56 |
| на эту тему тоже стоит подписаться |
| Автор: MAKCim 3.6.2008, 08:59 |
| Mayk, подписка не бесплатна |
| Автор: Любитель 3.6.2008, 12:12 | ||
Блин, не от TObject. Я хочу наследоваться от некоторого TMyObject - а он не наследуется от TInterfacedObject. В то же время я хочу реализовать некий Interface1. Я вынужден также реализовывать подсчёт ссылок, который Interface1 наследует от IUnknown - хотим мы того или нет. Наследоваться одновременно и от TMyObject, и от TInterfacedObject я не могу. И вопрос - зачем мне лишние труды по реализации ненужного мне подсчёт ссылок?! |
| Автор: Alexeis 3.6.2008, 12:28 |
| Любитель, TMyObject в любом случае наследуется от TObject, потому все изменение сводиться лишь к замене TObject на TInterfacedObject. Не пойму в чем проблема? |
| Автор: skyboy 3.6.2008, 13:06 | ||
если твой TMyObject не доступен тебе для редактирования, то ты можешь объявить собственного наследника TMyObject, который реализует IUnknown(методы объявленные в нем). И использовать в своих проектах TMyMyObject = class(TMyObject) implements IUnknown в качестве базы. Если ты не хочешь реализовывать три метода, сделай композицию с объектом TInterfacedObject и передай реализацию методов IUnknown внутреннему объекту класса TInterfacedObject. Добавлено через 6 минут и 9 секунд предчувствуя возражения типа "это же не удобно! меня поплющит три строчки дописать и объявить внутренний объект" сразу привожу контраргументы: (по реализации) если объектов будет слишком много, объект, реализующий подсчет ссылок и правда - лишняя трата: либо делать-таки "ручную"(непосредственную) реализацию методов, либо использовать шаблон "Посетитель"(http://en.wikipedia.org/wiki/Visitor_pattern) (по структуре) композиция вполне соответствует "духу ООП", а перенос реализации на внутренние объекты - полне нормально при условии отсутствия множественного наследования; к тому же само по себе делегирование - не есть плохо, лишь бы логика одного объекта не переносилась в независимый и несвязанный по модели объект. |
| Автор: Любитель 3.6.2008, 13:22 | ||
| Это всё хорошо, вопрос в том - нафига мне вообще заботиться о подсчёте ссылок, который мне вовсе не нужен, если я хочу релизовать некий интерфейс, не имеющий никакого отношения к подсчёту ссылок? Вообщем, думаю мы друг друга поняли. Нигде больше реализация произвольного интерфейса не заставляет реализовывать подсчёт ссылок (почему вообще именно подсчёт ссылок - мож ещё какую-нибудь полезную фиговину реалдизовать Добавлено через 46 секунд
Надо змаенить TMyObject на THisObject |
| Автор: Alexeis 3.6.2008, 13:43 | ||
Ну вот, это не просто фиговина, а управление памятью. Кстати интерфейс является автоматическим объектом. Это значит что при выходе интерфейса из блока счетчик ссылок декремнируется автоматически и если он становиться равным нулю, то объект автоматом удаляется, без явного вызова Free или деструктора. Тоже удобная фича. Так что не нада. |
| Автор: Любитель 3.6.2008, 13:46 | ||
Гы. Это собственно и называется смарт-поинтер. И непонятно, почему сие обязано привзываться к интерфейсам. |
| Автор: Alexeis 3.6.2008, 14:28 |
Сие называется автоматические объекты. И никак это не привязывается к интерфейсам, просто интерфейс это один из 3х типов автоматических объектов. |
| Автор: Любитель 3.6.2008, 14:36 |
| Ладно, скажем по-вашему - почему в дельфях нету интерфейсов для неавтоматических объектов? |
| Автор: skyboy 3.6.2008, 14:39 |
не заботься.. все - для тебя. поставь заглушки на методы, реализующие подсчет ссылок и пожалуйста - держи утечки памяти. распишитесь о получении: здесь и здесь кстати, тебя не напрягает тот факт, что смарт-понинтеры в "неуправляемом" С++ надо указывать явно? как же? это же лишний код! почему надо писать лишний код?! или любые указатели в С++ становятся "умными" по умолчанию? Добавлено через 4 минуты и 14 секунд типа приведения типов в С++? потому что не будет контроля. RTTI дает большой контроль за типом данных во время выполнения, но и приводить можно только к тому, от чего наследовано, а не к тому, у кого одноименные методы. А если и в С++ приводить только к тем классам, от которых происходило наследование, то какая разница? опять же пришли к противостоянию "мультинаследование против однозначного наследования" Добавлено через 7 минут и 4 секунды ты Алексиса не понял. Интерфейс по сути - разновидность автоматического объекта. а если поставишь заглушки-пустышки, то ничего у тебя удаляться не будет. и все должны быть довольны. |
| Автор: Любитель 3.6.2008, 14:48 | ||
Не, не напрягает. Я просто пишу boost::shared_ptr<MyType> (подставить tr1 по вкусу). А любые нет - указал, стали. Но никто не заставляет, чтоб они ими были. Нет, я не о приведении - всё о том же. Почему реализация любого интерфейса заставляет реализовывать подсчёт ссылок? ЗЫ Блин, мне надоедает обсуждать одну тему |
| Автор: skyboy 3.6.2008, 14:54 | ||
странно, что тебя не напрягает сам факт принудительного наследования от класса(TObject), у которого с полтора десятка методов. типа, "а вдруг я захочу реализовать собственную логику метода inheritsFrom(AClass: TClass)?" и т.д.. Добавлено через 1 минуту и 32 секунды вообще, не могу понять. тебя не устраивает: а) необходимость самостоятельно писать код в случае "косого наследования"? б) необходимость реализации подсчета ссылок в том или ином виде? в) необходимость реализации чего бы то ни было? |
| Автор: Alexeis 3.6.2008, 15:00 | ||
Объект который управляет интерфейс не является автоматическим. Автоматическим объектом называется сам интерфейс (объект в общем смысле этого слова, не тот что инстанцируется классом). |
| Автор: Любитель 3.6.2008, 15:43 | ||||||
Все пункты. Тобою они как раз названы в порядке важности
Я понимаю. Только это костыль. Во-первых, я всё равно что-то должен писать (что мне вовсе не надо), а во-вторых, это как раз может создать потенциальные проблемы. Кто-нибудь будет юзать этот TMyMyObject, увидит, что он реализует IUnknown (который как я понял объявляет лишь всё, связанное с подсчётом ссылок) и решит, что это работает. А ему - обломись
Ладно, чо-т я запутался |
| Автор: Alexeis 3.6.2008, 16:16 | ||
Интерфейсы реализованы так чтобы выполнять свою функцию. Например, "строитель" создает некоторый функциональный объект и передает его интерфейсы тем кто его должен использовать. Клиенты не знают ничего о классе объекта и о том как он реализует свои интерфейсы, не знает какие еще у него есть интерфейсы и не знает использует ли его еще кто-то. В этой модели, можно сколько угодно менять класс функционального объекта, добавлять к нему другие члены, которые будут частично или полностью реализовывать интерфейсы, заменять его другим при этом все зависимые модули даже не нужно перекомпилировать, поскольку они ссылаются на абстрактный интерфейс. Сам же строитель отпускает свое дитя в свободное плавание, при этом строитель не должен созвать ни каких дополнительных списков с созданными им объектами. Более того сам объект не будет существовать до окончания работы приложения и освободит ресурсы сразу же как только станет ненужным. |
| Автор: Любитель 3.6.2008, 16:32 |
| Блин, у меня есть интерфейс объекта, поддерживающего, например, сравнение (IComparable Кстати, возникла идея - а в Delphi .Net интерфейся тоже наследуются от IUnknown?! |
| Автор: Alexeis 3.6.2008, 17:23 | ||
Боюсь что там ситуация намного хуже, там любой объект наследует IInterface, а подсчет ссылок реализован у всех объектов, так как это является частью механизма сборки мусора. Там что-то вроде такого получается <указатель на управляющий объект> -> <управляющий объект> -> <объект> Фактически указатель на объект не доступен, доступен только <указатель на управляющий объект>, сам же <управляющий объект> реализует IUnknown и возможно еще кучу всякой хрени. При проходе очередного цикла сборки мусора объект перемещается в памяти и в управляющий объект записывается новый адрес объекта (существует системная очередь хранящая все ссылки на управляющие объекты), при этом <указатель на управляющий объект> остается неизменным. На управляющий объект может быть множество ссылок, которые он сам считает. Когда этот счетчик становиться равным нулю, объект будет объявлен не нужным и будут удален при следующем цикле сборки мусора. |
| Автор: Любитель 3.6.2008, 17:49 | ||||
Ну... это не банальный подсчёт ссылок. Насколько я знаю, ВМ просто хранит информацию о всех объектах и при запуске собрки мусора стоит граф объектов. "Висячие" части (не связанные со статическими полями, локальными переменными и т. д.) удаляются. То есть, это явно не подсчёт ссылок и реализуется это не на уровне отдельных классов (и не на уровне System.Object), а на уровне ВМ.
Он ничего не считает. Весь подсчёт проводится не во время работы, а во время сборки мусора. Гм. А что это за IInterface?! Что в нём объявлено? Просто речь о том, что дотнетовские интерфейсы ни от чего не наследуются (что логично) - как с этим поступает Delphi .Net? |
| Автор: MAKCim 3.6.2008, 18:25 |
| Alexeis, в общем с подсчетом ссылок ересь какая-то получается как сказал Любитель, костыль на пустом месте ты вот лучше скажи: как в Delphi обстоят дела с шаблонами? |
| Автор: lukas 3.6.2008, 18:40 |
| MAKCim, шаблоны это не проблема языка... это проблема среды... |
| Автор: Lazin 3.6.2008, 19:02 |
нет, это проблема языка |
| Автор: MAKCim 3.6.2008, 19:07 |
с шаблонами ясно сейчас найдем еще что-нибудь... |
| Автор: skyboy 3.6.2008, 19:18 |
ну да. как же. писать малопонятные инструкции с <> - это запросто. А воспользоваться расширением для рефакторинга, которому надо будет передать имя класса и имя дл поля, и IDE сформирует "скелет" по шаблону "Observer" - это не круто. аааа.... укусите меня за ногу.... Как в С++ с метаклассами дела обстоят? |
| Автор: MAKCim 3.6.2008, 19:26 | ||
что это в двух словах типа класса Class в Java? Добавлено через 2 минуты и 49 секунд
гы т. е Delphi IDE и Delphi язык уже неразрывно связаны? а если нет у меня IDE, а есть, к примеру, компилятор и vim? |
| Автор: skyboy 3.6.2008, 19:50 | ||
возможно. я практически не знаком с java. в Delphi, объект TClass может иметь значением ссылку на любой класс.
чей-то навроде переменных-функций, только расширенное до класса. та ладно! Это же Религиозные войны vim, кстати, вроде славился мощной системой расширений. вроде, на базе скриптов... вот и пишите скрипты Кста, аргумент наводит на грустные размышления. Есть бесплатная среда с отладчиков и тп, но чтоб вот так - vi пользоваться взамен... ууу... |
| Автор: MAKCim 3.6.2008, 19:57 | ||||
| skyboy, не совсем понял про метаклассы можно не кусок кода, а целостный рабочий пример?
нормальный пример как раз показывает бредовость сравнения кодогенерации IDE с возможностями языка
VIM и не на такое способен |
| Автор: Alexeis 3.6.2008, 21:00 | ||
На уровне чего происходит это вопрос условный, <управляющий объект> тоже принадлежит системе, а чисто с объектной точки зрения, никто чужой не может менять внутренние данные объекта, потому все что анализирует внутренние данные объекта правильно считать его методами. Могу залезть в книгу и сказать точнее, но данные по ссылкам точно находятся в управляющем объекте, более того есть даже какие-то методы, которые доступны для использования. |
| Автор: JackYF 4.6.2008, 01:06 | ||
А потом ещё два десятка расширений, чтобы это поддерживать? |
| Автор: skyboy 4.6.2008, 01:41 | ||
в смысле? смотря, какие расширения. мне вот хватает mmx model maker. учитывая, что mmx codeExplorer входит в Delphi начиная с какой-то там версии, то рефакторинг стал бесплатноприлагаемой фичей. MMX CodeExplorer + CnPack и я сплю спокойно Добавлено через 9 минут и 17 секунд признаться чесно, не могу сходу придумать настолько обоснованное применение, чтоб меня не запинали. Металкассы, так же, как и templates(когда немного-немного касался С++) для меня пока - слишком непонятная штука: не могу представить, как использовать: не дорос ещё. Потому пример приводить не буду, извини. Только замечу, что суть в том, что сам класс тоже является объектом. Который можно хранить в переменной, передавать в функцию в виде параметра(не имя класса, а сам класс - кстати, теряется смысл объектной реализации паттерна Фабрика/Factory: мы и так при желании можем создавать объект любого произвольного класса). Вкупе с RTTI это дает выражения вроде
|
| Автор: MAKCim 4.6.2008, 09:54 |
рефлексии в С++ нет |
| Автор: Lazin 4.6.2008, 10:38 | ||||
такое поведение легко реализовать и без метаклассов |
| Автор: MAKCim 4.6.2008, 11:13 |
как? |
| Автор: skyboy 4.6.2008, 11:16 |
| MAKCim, видимо, он имеет в виду шаблон "Фабрика". ведь как раз она и предназначена для создания объектов заранее не определенного класса. Правда, приходится писать "лишний код", но в итоге-то функционал тот же, разве нет? |
| Автор: Lazin 4.6.2008, 11:38 | ||
| я бы не сказал что много лишнего кода, ассоциативный массив, плюс статический метод или функция Create для каждого типа... как то так...
|
| Автор: MAKCim 4.6.2008, 11:42 |
| Lazin, проблема в том, что все классы придется регистрировать (причем статически) getClassByName() же возвращает объект метакласса для любого класса (или я не прав?) т. е полный аналог Class.forName() в Java |
| Автор: Любитель 4.6.2008, 12:01 | ||
Плохо обстоят - не спорим
Это уже мегакостыль. Всё - писать надо на асме фсё + мегаИДЕ, чтоб там генерила мегакод. |
| Автор: skyboy 4.6.2008, 12:02 | ||
исправляюсь: getClass, а не getClassByName(редко пользую, не упомнил).
именно вот оно - RTTI впрочем, есть свои сложности - как быть, если конструктор не может быть вызван без параметров? или наоборот - мы вызываем с параметрами, а конструктор должен быть без параметров... нло это частные случае применения это раз. потом: получаемый т.о. класс должен быть потомком TPersistent(а не базового TObject). это два. автоматически регистрируются только те классы, поля-объекты которых(в смысле, объекты каких классов) являются полями формы. Остальные классы надо "регистрировать" при помощи RegisterClass(уверен, сделано в целях повышения производительности: класс, который можно получить по имени должен быть в памяти даже если ни одного объекта такого класса не создается; значит, надо указывать явно, какие классы загружать: не размещать же в памяти всю VCL!). это три. |
| Автор: Lazin 4.6.2008, 12:03 | ||
зато как дисциплинирует, плюс платишь только за то, что тебе нужно... |
| Автор: skyboy 4.6.2008, 12:03 |
UML-костыль, если уж начистоту. мне с моей низкой колокольни кажется, что шаблоны вполне подменяют метаклассы |
| Автор: MAKCim 4.6.2008, 12:31 | ||||
в любом случае это не то почему бы не сделать в С++ полноценный RTTI с возможностью динамической загрузки и использования классов? это же не трудно в итоге получили бы Spring для C++ Добавлено через 2 минуты и 49 секунд
это два ортогональных понятия |
| Автор: skyboy 4.6.2008, 12:51 |
как минимум - это два подхода к метапрограммированию. разве нет? |
| Автор: Любитель 4.6.2008, 13:23 | ||
+1 Нет. Метаклассы дельфи к метапрограммированию не имеют отношения. Метапрограммирование - программирование на стадии компиляции, грубо говоря. |
| Автор: skyboy 4.6.2008, 13:51 |
раз уж на то пошло, это создание программы, которая создает другие программы |
| Автор: MAKCim 4.6.2008, 14:21 | ||
грубо говоря да ты создаешь код, который генерирует другой код по определенным правилам чем представим класс? идентификатором, методами и данными остается эту информацию упорядочить и структурировать в бинарном формате скомпилированных классов единственная сложность - это статические поля в текущих версиях компиляторов С++ статические поля представлены глобальными переменными |
| Автор: Любитель 4.6.2008, 14:32 | ||||
Согласен. Метаклассы к этому не имеют отношение - это к RTTI.
По-моему, просто добавить информацию в type_info - это раз. И создать глобальный маппинг: "имя класса" -> type_info. Насчёт статических полей - не понял, в чём проблема? |
| Автор: MAKCim 4.6.2008, 14:47 | ||||||
| Любитель, смотри как я это вижу есть класс
он компилируется в бинарное представление (описывает идентификатор, методы и данные) для поддержки фабрики классов реализуется класс rtti со статическим методом load_class(), получающий имя класса в качестве параметра load_class() находит скомпилированный класс, распаковывает его (парсит), создает объект type_info, его представляющий и помещает его в список объектов (например, хэшированный по имени класса) реализация type_info дополняется методом создания экземпляра класса (возвращает void *) т. е выходной код будет примерно таким
так вот, что касается статических полей как получить доступ к variable из object? если каждый объект Class будет хранить адрес variable, то общий размер таких объектов увеличится на sizeof(void*) а это семантически неправильно поэтому я бы расширил С++ концепцией атрибутов (или анотация), т. е метаинформацией о классе что-то наподобие этого
при этом, в случае, если Class реализует атрибут dynamic, то каждый объект этого класса будет содержать адреса всех статических переменных класса (если такие есть) |
| Автор: Любитель 4.6.2008, 15:26 | ||||
Это уже требует поддержки со стороный копилеры (речь про стандартный type_info?).
По мне бы, полноценную метаинфу о всё, что только можно - не отказался бы
А вот это не понял. Зачем объёкут содержать инфу? Компилер генерит метаинформацию о классе как таковом - и туда засовывает либо адреса, либо оффсета (статик/нонстатик). |
| Автор: skyboy 4.6.2008, 15:39 | ||
в Делфи каждый класс представляет собой объект, потому статические объекты, по идее, относятся к объекту-классу и поедания памяти не происходит. В С++, как я понимаю, с РТТИ будет сложно, т.к. класс как структура не хранится в памяти(я прав?), а в процессе компиляции конструкторы преобразуется аллокаторы, методы - в вызовы с передачей параметров. |
| Автор: Любитель 4.6.2008, 15:59 |
Есть type_info. Спецблок информации о типе, который компилер сохраняет для класса (в большинстве компилеров - по желанию). Вызовы методов - это, конечно, просто вызов функций (как и в дельяи, кстати). |
| Автор: Beltar 4.6.2008, 15:59 | ||
Хотите печатать быстро поступите на курсы машинисток. Кстати, реального кскорения даже при наборе вы не получите хотя бы из-за того, что надо нажимать еще и Shift. Я лично уже давно не пишу end руками. Их за меня вставляет Delphi 2006. ;) И вообще, все эти вроде бы мусорные слова типа then при просмотре кода очень сильно помогают. Если менять синтаксис, то я бы сделал в конструкции case закрытие не через end, а через endcase, лишний end если case стоит в середине процедуры иногда создает путаницу. Что касается надежности и быстроты набора Си, то все время сэкономленное при наборе сишного кода съедается компиляцией. Почему-то господа сишники стыдливо молчат, что проект в несколько тысяч строк в том же Билдере на самом современном процессоре будет собираться полминуты. Так же стыдливо молчат про проваливающиеся case, про отсутствие родного контроля выхода за границы массива. И еще я громко заявляю, что в Си++ нет цикла for. То что есть, это while с переставленными в другие места начальным значением и приращением счетчика. Не кажется ли, что приращение на 1, нужное в 99,9% случаев компилятор мог бы и сам ставить. |
| Автор: Alexeis 4.6.2008, 16:13 | ||||
Не нужно путать полный ребилд и билд. Если нет лишних инклудов, то при рабочем билде компилятся 1-2 cpp шника +линковка. Это происходит не дольше чем в делфи. Ребилд ол делается очень редко, например при изменении настроек компиляции. В этом нет большой нужны.
В С++ ахренительный цикл for, такой обалденный, что делфи нервно курит в сторонке. Невероятно удобный, логичный и функциональный. С таким фором ничего другого не нужно. |
| Автор: Lazin 4.6.2008, 16:32 | ||
какой ужас, Shift нужно нажимать, слепой метод набора рулед в С++ и Delphi под массивом понимают несколько разные вещи, ты-бы еще Си-шный массив сравнил с массивами в Руби только вся фишка в том, что в С++ есть аналог массива Delphi - vector(там проверяется выход за границу массива, и ее даже можно отключить), а вот в Delphi нет аналога Сишного массива |
| Автор: MAKCim 4.6.2008, 17:14 | ||||||
компилятор тут не причем это libstdc++.so
ну смотри
что компилятор будет генерировать в месте присваивания variable? на сегодняшний день статические переменные реализуются через обычные глобальные переменные но variable на момент компиляции не будет определена (класс загружается динамически) |
| Автор: Любитель 4.6.2008, 18:07 | ||
Ааааа.... Так ты про то, что сам класс берётся откуда-то из библиотеки что ли? |
| Автор: MAKCim 4.6.2008, 18:24 | ||
сам класс будет описываться бинарным форматом и загружаться при необходимости |
| Автор: lukas 4.6.2008, 18:54 |
| Что вы тут спорите... пока вы тут решаете что RTII у делфи во много раз лучше чем у С++, пытаетесь приводить аргументы, в это время вся технология .NET ушла вперед... так например в C# и всех подобных .NET языках RTII механизм круче раз в 100 по возможностям чем у делфи... там можно практически все (да не практически а абсолютно все) получить о классе о функциях, о методах в ран-тайм... я считаю это довольно хорошим преимуществом... хоть .NET это компиляция в байт-код... но скорость всеравно приближается с каждым разом к компилируемым языкам... а скорость при наших современных компах практически не критична... |
| Автор: MAKCim 4.6.2008, 19:08 | ||
| lukas, про .NET тут речи не было
еще раз задаю этот вопрос перечисли программы, установленные на твоем компьютере и использующие для своей работы .NET framework |
| Автор: Mayk 4.6.2008, 19:26 | ||||
Не вперёд,а назад, не ушла а сделала поползновение. RTTI в Smalltalk'е с его метаклассами и ярко выраженным "всё — объект, и это — тоже" мягко скажем не слаб уже пару десятков лет. Где он теперь?
В питоне это тоже можно. Питон+смаллталк+нет+ява убьют с++ и дельфи? Забавно, учитывая что ST с этими достоинствами был рожден до с++ и дельфи и почему то их не убил. Наверное он противник абортов. Однако исследования в области JIT'ов вроде встречаются гораздо чаще чем в области "а как бы нам зафигачить двусвязный спиок в минимальное число указателей хрустит попкорном ps. эту энергию, да в мирные бы цели. |
| Автор: Lazin 4.6.2008, 20:34 | ||||
ты этим пользовался хоть раз? по моему там это не очень удобно сделано... вот например в питоне рефлексия используется сплошь и рядом, например является естественным проверить есть ли у объекта класса какой-либо метод, а потом выполнить какой нибудь код который прифигачит к объекту какой нибудь атрибут... а в NET этим часто пользуются? все .NET программисты которых я знаю стараются по возможности обойтись без использоания rtti, так как тормозное оно... и когда только M$ успели всем внушить что .NET теперь абсолютно везде, некоторые люди верят, что виста на нем написана чуть ли не целиком Добавлено через 1 минуту и 1 секунду Добавлено через 2 минуты и 13 секунд интересно, куда пропал Мастер, может он и правда Тар и Mayk его спугнул |
| Автор: lukas 4.6.2008, 21:25 |
| я говорю о возможностях языка... а не о том где это применять... и кому это удобно... вы же не спрашиваете кто применяет RTII в делфи и для чего... с чего же тут начинать разводить... для чего нам RTII, конешно область применения RTII очень узкоограничена... .NET и все подобное... что выполняет байт код это еще одна ступень в абстракции программных языков... тему тут удивляться... P.S. Там где нужна скорость, обычно RTII совсем не нужна, а там где она вообще не ощутима... да и ощутить ее нельзя... т.к. разницы нет никакой... вот там то и удобно применять RTII. P.S.S. По вашей логике можно было до сих пор программировать на одних функциях, не используя объекты и их методы, т.к. методы же работают медленее... а для нас скорость критична... когда процессоры dual core... 3.0 MGz... |
| Автор: MAKCim 4.6.2008, 21:36 |
гы язык тут не причем ключевое слово CLR в общем случае ложь |
| Автор: lukas 4.6.2008, 21:50 | ||
ну да в с++ возможно... поэтому там и нет нормального RTII, т.к. объект это набор функций названных методами... (образно говоря) |
| Автор: MAKCim 4.6.2008, 22:33 | ||
объект - это данные данные отделены от кода |
| Автор: lukas 5.6.2008, 06:42 |
| MAKCim, и почему же они должны работать так же как и функции... сделай простой тест на с++... возми функцию и метод объекта который выполняет тоже самое что и функция... поставь это все в цикл большой и посчитай на что больше времени уйдет... с помощью функции GetTimeCount() например... Делаю ставку, что функция выполнится раз в 10 быстрее чем метод объекта... |
| Автор: Mayk 5.6.2008, 07:08 | ||||||||
а почему иначе
Какой феерический бред.
|
| Автор: lukas 5.6.2008, 07:34 | ||
| Mayk, короче говоря я не знаю как устроен компилятор си, поэтому ничего утверждать не буду... возможно оптимизация... я даже уверен... приглядись на свои циклы... по крайней мере оптимизация дает иногда такие результаты... ну и возьми побольше цикл... 94 это не показатель... хм... повторил тоже самое на делфи... время таже такое же как у тебя... (надо же проци у нас наверно одинаковые
|
| Автор: Mayk 5.6.2008, 07:54 | ||||||||||||
Точно! Счас мы добавим ещё и виртуальную таблицу на потеху оптимизаторам.
Похоже что накладные расходы на вызовы здесь ужасно незначительны. Добавлено через 1 минуту и 31 секунду и это при том что у testvirmethod'а нету на этапе компиляции кода A::foo(). Добавлено через 8 минут и 55 секунд
Всё то. При вызове метода из накладных расходов - это лишь передача указателя на класс(да и то лишь в том случае если компиялтор был достаточно туп чтобе не сделать данный метод (foo) статическим самостоятельно). это вообще почти нулевые расходы. |
| Автор: MAKCim 5.6.2008, 09:33 | ||||
Добавлено через 5 минут и 42 секунды в который раз убеждаюсь, что С/С++ обязателен для обучения а то всякие Java/.NET-ы дают своеобразное понимание многих вещей |
| Автор: skyboy 5.6.2008, 10:24 |
каким боком затесались .NET/Java в тему о Delphi и С++? Оффтоп! Надо говорить: "А то всякие Delphi дают своеобразное понимание многих вещей" - и вот, ещё один аргумент в пользу С++ |
| Автор: lukas 5.6.2008, 11:05 |
| ДА какая разница... мне пох... наверно я спутал со свойствами... property.. |
| Автор: Alexeis 5.6.2008, 11:20 |
| Понимание многих вещей лучше всего дает ASM и C. С++ здесь точно также своеобразно преломляет алгоритмы под свои правила. |
| Автор: W4FhLF 5.6.2008, 11:23 |
| Асм рулед, я всегда это говорил |
| Автор: skyboy 5.6.2008, 11:59 |
которые компилятся в обращения к тем же методам.... новые замеры проведем? |
| Автор: lukas 5.6.2008, 13:48 |
| skyboy, функция против property?? |
| Автор: Lazin 5.6.2008, 14:18 | ||
+1 |
| Автор: Любитель 5.6.2008, 16:41 | ||||
А... даже так... Я про другое думал - получение полной метаинформации об обычном классе. Хотя такое - это, конечно, ещё интересней. Этого в дельфи нет
А чем реализация методов в обычно (не дотнетовской) дельфе отличается от функций property в .Net это специальный тип метаданных. Который указывает имя свойства, тип и референсы на гет/сет методы. Последние - обычный методы, по-сути |
| Автор: Mayk 5.6.2008, 16:54 |
| Скажите, а кто нить кроме меня ещё путает эту тему и http://forum.vingrad.ru/forum/topic-45838/unread-1/210.html? |
| Автор: lukas 5.6.2008, 17:38 | ||||
хех америку открыл... в делфи тоже самое... думаю и в билдере тоже самое...
|
| Автор: Любитель 5.6.2008, 17:44 |
Я не знаю, как они там реализуются в дельфи. Всмысле в PE-шнике что сохраняется. РЕчь шла о том, что и property вовсе не будут работать в 10 раз медленнее функций/методов. Вообщем, никакой приницпиальной разницы Неа. Здесь Мастера нет! |
| Автор: lukas 5.6.2008, 20:01 |
| короче спорить о языках программирования также глупо как и о естественных языках... например руский и английский... давайте поспорим кто круче... у кого больше возможностей для построения предложений и т.д... |
| Автор: MAKCim 5.6.2008, 20:58 | ||
ОК, соглашусь угу
а что тут спорить очевидно, что русский круче Добавлено через 1 минуту и 45 секунд только вот переносимость будет нулевая но зато в рамках конкретной платформы все будет пучком |
| Автор: nerezus 5.6.2008, 21:38 | ||
|
| Автор: lukas 6.6.2008, 10:17 |
да, но это не мешает английскому быть самым популярным языком в мире... короче... это последний офтоп... |
| Автор: MAKCim 6.6.2008, 10:28 | ||
английский в разы проще |
| Автор: LSD 6.6.2008, 10:32 |
| Вы решили, что менять синтаксис паскаля, это не тот размах, и решили поменять синтаксис английского языка? |
| Автор: Mayk 6.6.2008, 10:42 |
| And ze drems vil finali kum tru!!!!!!!!!!! |
| Автор: skyboy 6.6.2008, 10:48 |
| Mayk, чьи мечты-то исполнятся? |
| Автор: Mayk 6.6.2008, 11:00 |
| skyboy, это из старинного баяна про английский язык - см например тут http://forum.vingrad.ru/forum/topic-208538.html |
| Автор: Любитель 6.6.2008, 11:03 | ||
Большего и не надо. С бинарной переносимостью (даже на одой платформе - при смене компилера) у С++ всегда были (и будут) проблемы. Это не есть плохо. |
| Автор: JackYF 6.6.2008, 13:42 |
ABI - фиг с ним. API, главное, сохраняется Не удержусь: а в GNU/Linux'е на 99-и-много-девяток-в-периоде-процентов такой проблемы нет |
| Автор: Любитель 6.6.2008, 15:55 | ||
Хм... Ну для начала - ты много знаешь разных компилеров под GNU/Linux? gcc3 vs gcc4 - проблемы совместимости AFAIK были. Хотя вроде их решали, но это естественно (всё-таки это разные версии одного компилера |
| Автор: JackYF 7.6.2008, 00:47 |
| Любитель, ну так об этом и речь веду. Холивары всё-таки |