Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.192] |
|
|
Правила раздела:
| Страницы: (495) « Первая ... 31 32 [33] 34 35 ... 494 495 ( Перейти к последнему сообщению ) |
Delphi vs C++ vs C#
, ну и Java немножко, где-то ближе к старшему байту номеров страниц
|
Сообщ.
#481
,
|
|
|
|
Цитата D_KEY @ На уровне логики полностью заменяют. Ты же говоришь о физическом размещении текста программы. модули обычно имеют связь с размещением в том или ином виде. даже классы джавы имеют |
|
Сообщ.
#482
,
|
|
|
|
Цитата korvin @ они и не помешают, только class A, объявленный в модуле M будет иметь полное имя M.A, а класс A объявленный в модуле N -- N.A соответственно. Это называется пространство имен. Цитата Цитата MyNameIsIgor @ При помощи стражей включения не включает уже включённые в данной единице трансляции заголовочные файлы. т.е. мне в моем заголовочном файле нужно думать, как бы чья программа, юзающая мой хидер не подключила чей-то хидер раньше моего со схожим определением? С каким еще схожим определением . Ну и каша... |
|
Сообщ.
#483
,
|
|
|
|
Цитата korvin @ т.е. мне в моем заголовочном файле нужно думать, как бы чья программа, юзающая мой хидер не подключила чей-то хидер раньше моего со схожим определением? т.е. "#pragma once" же вроде не стандартизировано, а как делают в Qt через "#ifndef ..." могут и одинаковые "метки" оказаться? Вот для того, чтобы никто не сделал тип с тем же определением, и есть пространства имён. А стражи включения следят, чтобы ваш заголовочный файл не был включён два раза в одну единицу трансляции. Ещё раз: это разные задачи вообще. |
|
Сообщ.
#484
,
|
|
|
|
Цитата MyNameIsIgor @ Ну, дык, namespace же. Не имеющие к стражам включения никакого отношения. Вернее, это стражи включения не имеют к пространствам имён никакого отношения, они просто на разных уровнях. Вы что-то попутали. дык об чем и речь, нет модуля как языковой абстракции, а набор несвязанных друг с другом средств, каждое из которых необходимо в итоге задействовать, чтоб добиться чего-то похожего на модули. |
|
Сообщ.
#485
,
|
|
|
|
Цитата korvin @ Цитата D_KEY @ На уровне логики полностью заменяют. Ты же говоришь о физическом размещении текста программы. модули обычно имеют связь с размещением в том или ином виде. даже классы джавы имеют В том или ином виде все, что написано в программе имеет связь с размещением, ибо хранить где-то текст нужно. Только причем тут модули как логическая единица программы? В ООП модульность обеспечивается классами и объектами, а не модулями. Для объединения нескольких логически связанных классов используют пакеты/неймспейсы. Как же эти языковый конструкции физически размещаются - вопрос отдельный. |
|
Сообщ.
#486
,
|
|
|
|
Цитата MyNameIsIgor @ Ещё раз: это разные задачи вообще. разные. но модули обязаны их обе решать Добавлено Цитата D_KEY @ В ООП модульность обеспечивается классами и объектами, а не модулями. разработчики питона, руби и окамла видимо об этом не знают =/ |
|
Сообщ.
#487
,
|
|
|
|
Цитата korvin @ дык об чем и речь, нет модуля как языковой абстракции, а набор несвязанных друг с другом средств, каждое из которых необходимо в итоге задействовать, чтоб добиться чего-то похожего на модули. Цитата korvin @ разные. но модули обязаны их обе решать Да, существуют у C/C++ проблемы с препроцессором, только не понимаю как это влияет на факт решаемости задач модулей средствами ООП? Пишу вот на шарпе - ни модулей, ни стражей включения. ЧЯДНТ? Добавлено Цитата korvin @ разработчики питона, руби и окамла видимо об этом не знают =/ Видимо. |
|
Сообщ.
#488
,
|
|
|
|
Цитата MyNameIsIgor @ Да, существуют у C/C++ проблемы с препроцессором, только не понимаю как это влияет на факт решаемости задач модулей средствами ООП? Пишу вот на шарпе - ни модулей, ни стражей включения. ЧЯДНТ? ну так и которая из сущностей там выполняет работу "стражей включения": класс или пространство имен? |
|
Сообщ.
#489
,
|
|
|
|
Цитата korvin @ ну так и которая из сущностей там выполняет работу "стражей включения": класс или пространство имен? Дык там вообще нет такой работы, поскольку никакие заголовочные файлы никуда не вставляются... |
|
Сообщ.
#490
,
|
|
|
|
Цитата DesweR @ Ты любую фразу в поддержку чего-то считаешь доказательством? Доказательство - это цепь выводов, где в качестве первого выступает некое очевидное высказывание, каждый последующий непосредственно вытекает из предыдущего, и последним является объект доказательства. Чем и показывается логическая связь первого с последним. Если вы тут наговорили кучу интересного о пользе модулей, это не является доказательством необходимости их существования. Я тоже в том большом посте ничего не доказал, но я много наговорил в пользу своей точки зрения. Рассчитывал, что пойдёт конструктив, или хотя бы будут заданы вопросы, наивный. Если абстрактные рассуждения не могут быть тобою поняты сами по себе и приняты к сведению, это не значит, что там вода, это значит, что их логичность ускользает от твоего понимания. Ваши способности толочь воду в ступе демонстрирует весь соседний холивар. Это вашими усилиями он вырос в размере на порядок, полезной информации в нём ~10%.Обоснования чего? О преимуществах модулей? О них уже давно рассказали, если не хотите это принимать - ваши проблемы. А всё что тобою было написано - просто вода, без каких-либо доказательств. Хорошо. Попробуем перейти к доказательствам. Вот C. Какие средства декомпозиции в нём были? Только одно: каждая единица трансляции реализует только одну сущность, описание которой присутствует в заголовочном файле. Т.о. в .h мы имеем публикацию публичного интерфейса, с extern либо без оного, а в .c лежит реализация этого публичного + всё приватное, определённое как static. Как пользователь я беру и подключаю .h к себе в нужную единицу трансляции, тем самым показывая, что использую публичный интерфейс этой сущности. .c же быть где-то в проекте не обязан. Он вполне может быть уже откомпилен и добавлен в приложение линкером либо из .o/.obj, либо из .a/.lib. Какие средства декомпозиции были в Pascal? Никаких. Нету в Стандарте Pascal таких средств. Что делать Филиппу Канну? Он в 4-й версии Turbo Pascal ввёл модули, слизав их идею из Modula. Причём замечу, что в Modula модули были трёх видов: программные модули, в количестве ровно один на всю программу (аналог нашей единицы трансляции, содержащей main()), модули определений (наши .h) и модули реализаций (наши .c), тогда как в Turbo Pascal модули определений и модули реализаций объединены по непонятной для меня причине. Нормально? Почему нет. Раздельная компиляция вместе с декомпозицией во всей красе, публичный интерфейс под interface, приватный под implementation. Всё здо́рово. Пока. Единственно, что смущает, так это BEGIN/END. Ну да ладно, действительно, тогда других средств для гарантированой инициализации модуля не было. Смущение относилось скорее к отсутствию деинициализации. Мда, поторопился Филипп с плагиатом, надо было вместо объединения разнотипных модулей в один подумать, как исправить более насущный недостаток Modula. Пришлось вот костылить ExitProc-ом. Это - структурное программирование, которые полтора десятилетия считалось панацеей. Однако. Основной причиной обращения взора широкого программисткого сообщества к ОП стало то, что единица трансляции суть весьма неудобный способ декомпозиции и вообще реализации чёрных ящиков. Слишком грубый. Крупные проекты просто умирают от количества единиц трансляции, и програмимисты тонут в сотнях и тысячах модулей. К тому же обеспечивают только один уровень декомпозиции, что не просто очень мало, это мизерно мало, исчезающе мало. Нужны были более легковесные средства, к тому же умеющие выстраиваться в деревья, чтобы можно было при желании уровень декомпозиции выбирать соответственно желаемому уровню абстракции, чем глубже, тем больше деталей. И каждый уровень должен иметь свои публичные и приватные интерфейсы, естественено. Вот C++. Какие новые средства декомпозиции появлились в нём? Всего один - классы. На удивление этого оказалось достаточно. У него есть явно указываемые public и private, а для упрощения построений иерархий абстракции protected. Идеальный инструмент для построения всего чего угодно, начиная с чёрных ящиков и заканчивая инкапсуляций иерархий интерфейсов. (Как впоследствии оказалось, классы в Плюсах получились вообще универсальнейшим инструментом, ООП - это только малая часть их возможностей. Это в других, "специализированных" языках, классы только для ООП и подходят. В Плюсах же классы - это не ООП, это инструмент, в частности и для ООП.) Вопрос: для чего же тогда декомпозиция на уровне единиц трансляции? Правильно: при всём своём универсализме для решения простых частных задач универсальный инструмент не всегда хорош. Зачастую объединить несколько чёрных ящиков в одну подсистему можно просто ещё одним дополнительным уровнем декомпозиции, и в этом смысле единицы трансляции по-прежнему на коне, они проще. Знаете, меня умиляет правило в некоторых компаниях "один класс - одна пара .h/.cpp", так и хочется улыбнуться и погладить по головке, мол, хорошо, молодцы, в правильном направлении развиваетесь. C with object пока рулит, но ещё не вечер, перерастёте структурный подход к декомпозиции. Вот Object Pascal. Что мы видим? Та то же самое. Появились объекты с такими же по сути возможностями, что и классы в C++, и по-прежнему остались модули. Всё классно, кроме того, что объекты, которые не в хипе, не конструируются и разрушаются автоматически, самому вызывать надо. От блин, косяк. Не, ну тогда я тоже думал, во как круто, я сам определаю, когда что вызывать. Ага, пока реально не стал писать нормальные проекты. Так что без ручной инициализации/деинициализации по-прежнему никак. Уже первый звоночек. Но как в целом-то? Та нормально в целом. Всё ещё. Однако и классы и единицы трансляции всё ещё остаются крайними средствами декомпозиции. К примеру. Решил я реализовать класс комплексных чисел. Вроде бы ничего сложного, такой класс написать - пару пустяков. Приватный интерфейс содержит как минимум пару полей для репрезентации пары действительных составных частей и публичный с кучей операторов и функций. Только вот одно но: мы как-то привыкли вызывать функции sqrt(x), а не x.sqrt(), а для этого sqrt() должна быть свободной функцией, а не методом. Всё почему: сущности, тесно связанные с некой абстракцией, могут иметь синонимы в других подсистемах. Что оставлять их в глобальной области видимости, что инкапсулировать в класс - суть плохие решения. Так появились пространства имён, идеальные средства для группировки нескольких чёрных ящиков в единую подсистему, равно как и инкапсуляции под единым интерфейсом разнородных, но тесно связанных сущностей без влияний на другие подсистемы. Делаем интерфейс комплексных чисел простанством имён, и там будут и класс, и все связанные свободные функции, и всяко разные константы, типы, итп, тоже связанные. Внимание, вопрос: какая роль остаётся единицам трансляции? Ведь пространства имён не имеют границ, они открыты. Начатое в одной единице трансляции, оно может быть продолжено в другой, задокументировали в .h, реализовали в .cpp и там же расположили всё "приватное", достаточно в .h это не выносить. Они могут быть вложенными, т.е. иерархическими. Их взаимоотношения могут регулироваться и явно показываться using, итп. Зачем теперь единицы транляции? D_KEY ответил: они перестали играть сколько-нибудь существенной роли в декомпозиции. Вся декомпозиция теперь управляется логическими соображениями, а не физическим отделением сущностей друг от друга. Всё, что им остаётся - факторы удобства и здравого смысла. А что ж Object Pascal, который уже Delphi? Пересмотрели объектную модель, ввели классы. И... оставили модули в первоначальном виде. Даже расширили, initialization/finalization. Вот это ИМХО было уже грубой ошибкой. Зачем? Для глобальных переменных модуля? Не, ну понятно, что модуль теперь - скорее средство для композиции формы. Ну что ж, будем считать, что модуль - это такой "форменный" класс, с конструктором/деструктором и всем связанным с этим наполнением. Но как-то смахивает на красивый лимузин на узких улочках провинциального городишки, куда звезда приехала с гастролями. Модуль, как и единица трансляции, по гибкости не сравнится с пространством имён. А главное, теперь-то в Delphi есть пространства имён! Ну и вот теперь объясните мне, на кой модули в Дельфях? Ведь они даже более специализированы, чем единицы трансляции в Плюсах. В их-то виде. Боюсь, единственный ответ, который меня устроит - обратная совместимость. ![]() ![]() namespace { struct Init { Init(){ /* initialization */} ~Init(){ /* finalization */ }} dummiy;} Цитата korvin @ Лучше задайся вопросом, какая разница, кто эту работу сделает, препроцессор или компилятор. Хочешь сказать, когда компилятор видит взаимные USES и самостоятелно выполняет #pragma once, это круче, чем если его просто не поставить перед такой рекурсией? Так так и говори, зачем третью страницу воду толочь? ну так и которая из сущностей там выполняет работу "стражей включения": класс или пространство имен? |
|
Сообщ.
#491
,
|
|
|
|
Цитата Qraizer @ Хочешь сказать, когда компилятор видит взаимные USES и самостоятелно выполняет #pragma once, это круче, чем если его просто не поставить перед такой рекурсией? Так так и говори, зачем третью страницу воду толочь? эм... я так и говорю, но некоторые спорят. ты же не будешь отрицать, что первый вариант круче? =) Добавлено Цитата Qraizer @ Лучше задайся вопросом, какая разница, кто эту работу сделает, препроцессор или компилятор. а разница проста: компилятор просто не позволит повторно "подключить" один и тот же модуль, в отличие от C/C++, где все просто надеются, что никто не забудет поставить #pragma once |
|
Сообщ.
#492
,
|
|
|
|
Qraizer, ну точно пора заводить блог
Добавлено Цитата korvin @ а разница проста: компилятор просто не позволит повторно "подключить" один и тот же модуль, в отличие от C/C++, где все просто надеются, что никто не забудет поставить #pragma once А main функцию не забудешь написать? Кстати, стражи любая IDE или шаблоны в текстовом редакторе ставят сами. |
|
Сообщ.
#493
,
|
|
|
|
Цитата korvin @ а разница проста: компилятор просто не позволит повторно "подключить" один и тот же модуль, в отличие от C/C++, где все просто надеются, что никто не забудет поставить #pragma once Ну, не поставят - не скомпилится или не слинкутеся. Не вижу особых проблем... |
|
Сообщ.
#494
,
|
|
|
|
Цитата D_KEY @ А main функцию не забудешь написать? если забуду -- компилятор напомнит. если забуду написать "#pragma once", никто ничего не скажет Добавлено Цитата MyNameIsIgor @ Ну, не поставят - не скомпилится или не слинкутеся. Не вижу особых проблем... откуда уверенность? а если так, то зачем вообще его ставят? Добавлено Цитата D_KEY @ Кстати, стражи любая IDE или шаблоны в текстовом редакторе ставят сами. по-твоему это какой-то плюс? |
|
Сообщ.
#495
,
|
|
|
|
Цитата korvin @ Цитата D_KEY @ А main функцию не забудешь написать? если забуду -- компилятор напомнит. если забуду написать "#pragma once", никто ничего не скажет Правда что ли? Пробовал ?Как только два раза появится, скажем, определение класса в одной единицы трансляции - компилятор будет ругаться на повторное определение. Цитата Чтоб не ругался компилятор Цитата MyNameIsIgor @ Ну, не поставят - не скомпилится или не слинкутеся. Не вижу особых проблем... откуда уверенность? а если так, то зачем вообще его ставят? Цитата По-моему это не минус. Цитата D_KEY @ Кстати, стражи любая IDE или шаблоны в текстовом редакторе ставят сами. по-твоему это какой-то плюс? |