Russian Qt Forum
Ноябрь 27, 2024, 03:06 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3] 4 5 ... 8   Вниз
  Печать  
Автор Тема: C++ vs D  (Прочитано 69504 раз)
Tonal
Гость
« Ответ #30 : Октябрь 28, 2008, 22:15 »

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

Делегаты - аналог системы сигнал-слот в Qt. Несколько устарелое явление, т.к. является частным случаем замыкания + лямбда. А лямбды и замыкания сейчас как раз входят в моду: .Net 3 и C++x0. Улыбающийся

Насчёт преимуществ - как "низкоуровневый" язык он сливает С/С++ как раз из за своих "высокоуровевых" возможностей при отключении которых никаких преимуществ кроме чуть более удачного синтаксиса не остаётся. (интересно, могу я в D прицепить к структуре метод для удобства и не потерять её бинарной совместимости с С. Например With() и Height() к Rect-у который использую для работы с той же WinApi или написать для какой-нибудь структуры деструктор, кторый закроет связанный с ней файл? Могу ли поместить структуры в массив или map и напрямую отдавать ссылку на них в plain C API)

Если сравнивать с C# и Java, то интересно, получаю ли я детальный трейс при, например, вылете за границы массива? Могу ли подгрузить дополнительные модули во время работы и насколько это прозрачно для меня? Каковы возможности RTTI - можно ли по имени вызвать метод или прочитсть/записать значение поля.

Общие вопросы: насколько быстрый получается код?
Какая перспектива стандартизации?
Сколько и каких проектов делается?
Кто из крупных ИТ игроков проявляет интерес/поддержку?

П.С. Собрать бинарик с профилятором и анализатором покрытия умеет так же GCC
Intel и MSVC точно умеют с профилятором.
Записан
Eldar
Гость
« Ответ #31 : Октябрь 28, 2008, 23:49 »

5. Объявление всех функций-членов классов виртуальными.

А что тут позитивного? вызов виртуального метода медленее, чем не виртуального (покрайней мере в С++ так)
Ну давайте подробнее - что представляет собой вызов виртуального метода это по сути что-то похожее на *(ptr+x*y)func(). порассуждаем - для соврременных процессоров операция умножения такая уж дорогая? Это только предвапрительное суждение, компилятор D анализирует иерархию и преобразует виртуальные вызовы в обычные если в этом нет необходимости. А вот вызов слота по сигналу намного медленнее.
« Последнее редактирование: Октябрь 29, 2008, 07:12 от Eldar » Записан
Eldar
Гость
« Ответ #32 : Октябрь 29, 2008, 07:10 »

>>Насчёт преимуществ - как "низкоуровневый" язык он сливает С/С++ как раз из за своих "высокоуровевых" возможностей при отключении которых никаких преимуществ кроме чуть более удачного синтаксиса не остаётся.
Подробнее можно?

>>(интересно, могу я в D прицепить к структуре метод для удобства и не потерять её бинарной совместимости с С. Например With() и Height() к Rect-у который использую для работы с той же WinApi или написать для какой-нибудь структуры деструктор, кторый закроет связанный с ней файл? Могу ли поместить структуры в массив или map и напрямую отдавать ссылку на них в plain C API)

Да, структуры в D полностью совместимы с Сишными. И к ним легко можно прицепить extern (C) методы. Правда насчет конструкторов и деструкторов - D1 их не имеет, только D2.

Цитировать
Общие вопросы: насколько быстрый получается код?
Какая перспектива стандартизации?
Сколько и каких проектов делается?
Кто из крупных ИТ игроков проявляет интерес/поддержку?
Код по скорости мало уступает gcc, я тестов лично не проводил - но можно глянуть здесь http://shootout.alioth.debian.org/
Стандартизация - лично мне она не нужна. И то что С++ стандартизирован - нисколько не делает его лучше. Даже с точки зрения стандартов - тот же msvc отличается от gcc некоторыми деталями. В случае D - я уже упоминал - есть спецификации и ее воплощение в виде dmd. Разработчики основных компиляторов используют ее.
Насчет поддержки крупных игроков - ее нет Улыбающийся По проектам - кроме опен-сорсных я сказать не могу. Но его применяют.
По этой же как раз и причине я решился делать свой "проект" на D. Чтобы одной программой на D было больше. Но надо сказать у D потрясающее комьюнити.
« Последнее редактирование: Октябрь 29, 2008, 08:02 от Eldar » Записан
Tonal
Гость
« Ответ #33 : Октябрь 29, 2008, 09:04 »

>>Насчёт преимуществ - как "низкоуровневый" язык он сливает С/С++ как раз из за своих "высокоуровевых" возможностей при отключении которых никаких преимуществ кроме чуть более удачного синтаксиса не остаётся.
Подробнее можно?
...
Да, структуры в D полностью совместимы с Сишными. И к ним легко можно прицепить extern (C) методы. Правда насчет конструкторов и деструкторов - D1 их не имеет, только D2.
Объясняю подробнее.
Пусть мне нужно написать нечто низкоуровневое. Это значит, что что будет много работы с железом и plain C API.
Работая на чистом С всё это у меня есть, но хочется некоторых удобств.
Что мне даёт тут С++?
У меня остаётся всё что есть в С, но появляются дополнительные нехилые удовства, например:
Я могу наследоваться от существующих plain C структур и добавить в наследник невиртуальные функции, конструктор/деструктор, перегрузить, операторы, написать шаблоны функций и классов и работать уже с такими вот навороченными объектами. При этом не утеряв бинарную совместимость, т.е. те же экземпляры я скармливаю железке и plain C API без каких-либо преобразований.
Тут утверждается что D низкоуровневый и что D круче С++ - вот и давайте сравнивать их "низкоуровневые" возможности.
Всякие виртуальности, GC и исключения тут идут лесом так как противоречат бинарной совместимости и временнЫм характеристикам.
А вот множественное наследование - вполне себе канает, т.к. не вносит оверхеда. Улыбающийся

Цитировать
Общие вопросы: насколько быстрый получается код?
Какая перспектива стандартизации?
Сколько и каких проектов делается?
Кто из крупных ИТ игроков проявляет интерес/поддержку?
Код по скорости мало уступает gcc, я тестов лично не проводил - но можно глянуть здесь http://shootout.alioth.debian.org/
Стандартизация - лично мне она не нужна. И то что С++ стандартизирован - нисколько не делает его лучше. Даже с точки зрения стандартов - тот же msvc отличается от gcc некоторыми деталями. В случае D - я уже упоминал - есть спецификации и ее воплощение в виде dmd. Разработчики основных компиляторов используют ее.
Насчет поддержки крупных игроков - ее нет Улыбающийся По проектам - кроме опен-сорсных я сказать не могу. Но его применяют.
По этой же как раз и причине я решился делать свой "проект" на D. Чтобы одной программой на D было больше. Но надо сказать у D потрясающее комьюнити.
Эжели отбросить скорость, то то ответам на остальные вопросы можно судить о распространённости технологии, её стабильности, пригодности для серьёзных проектов, качеству литературы и поддержки.
Всего этого у D сейчас просто нет - это значит, что язык пока ещё не подходит не для чего, кроме как для "поиграться".
Это не значит, что он полхой - это значит что он ещё "сырой" для серьёзных применений.

Тут ещё подумалось, что в этом флейме мы как-то упустили алголообразных - Pascal, Ada, Modula, Oberon.
А там есть довольно интересные нароботки - например Ada давно имеет и шаблоны и классы и исключения и сборку мусора и пакетную систему. Умеет компилятся в натив. Имеет встроенную многозадачность.
Поищи в истории - тут был как-то кадр который делал к ней биндинг. Улыбающийся
Или связка Modula + Oberon используется для создания операционок Modula на низком уровне, Oberon для среднего и дальше.
Ну а в Pascal славные ребята из багланда добавили в структуры методы и перегрузку операций. А их наследники теперь ещё и шаблоны (генерики) и при этом компилят в натив. Улыбающийся

П.С. Написание биндинга D к Qt несомненно будет для D очень серьёзным плюсом. Улыбающийся
Записан
Eldar
Гость
« Ответ #34 : Октябрь 29, 2008, 09:21 »

Цитировать
Я могу наследоваться от существующих plain C структур и добавить в наследник невиртуальные функции, конструктор/деструктор, перегрузить, операторы, написать шаблоны функций и классов и работать уже с такими вот навороченными объектами. При этом не утеряв бинарную совместимость, т.е. те же экземпляры я скармливаю железке и plain C API без каких-либо преобразований.

Вопрос имхо здесь в другом. В D структуры совместимы с C. Копируете из Сишного хидера структуру, определяете ее и делаете с ней все что хотите. Насчет наследования, имхо, оно не для этих случаях. Во многих умных книжках по С++ часто советуют предпочитать наследованию композицию. Насчет работы со структурами - можете глянуть в исходники GtkD - имхо достаточно удачный пример биндинга к Сишной либе.
С шаблонами также проблем не будет.

Насчет Ады - в поисках как должен работать биндинг Qt наткнулся на QtAda. Читать код на Аде имхо невозможно, это просто ужас.

Цитировать
Ну а в Pascal славные ребята из багланда добавили в структуры методы и перегрузку операций. А их наследники теперь ещё и шаблоны (генерики) и при этом компилят в натив.

Кстати в треде по биндингу некоторые товарищи считают что дельфи - гамно. Приятно что не все так думают Улыбающийся
« Последнее редактирование: Октябрь 29, 2008, 09:25 от Eldar » Записан
Tonal
Гость
« Ответ #35 : Октябрь 29, 2008, 09:26 »

Ну давайте подробнее - что представляет собой вызов виртуального метода это по сути что-то похожее на *(ptr+x*y)func(). порассуждаем - для соврременных процессоров операция умножения такая уж дорогая? Это только предвапрительное суждение, компилятор D анализирует иерархию и преобразует виртуальные вызовы в обычные если в этом нет необходимости.
А Вот из практики: профилировал я как-то одну прогу, и оказалось, что изрядно тормозит сортировка массива.
Причём массив вроде был не большой ~2-5 тысяч элементов, и сортировка была быстрая...
Но - в массиве были умные указатели на COM объекты. Т.е вся работа с ними делалась через виртуальные функции, т.е. можешь посчитать, сколько приходилось на тупой swap - а их довольно много при быстрой сортировке...
Когда это до меня дошло выход был найден тут же: создал массив структур, которые содержали только ключ сортировки и номер в исходном массиве, отсортировал его, после чего переставил элементы в исходном массиве. Улыбающийся

Хотя было это лет 10 назад и сейчас машинки стали несколько быстрее, но объёмы данных тоже изрядно выросли. Так что история, как мне кажется, не потеряла актуальности. Улыбающийся
Записан
Tonal
Гость
« Ответ #36 : Октябрь 29, 2008, 09:44 »

Цитировать
Я могу наследоваться от существующих plain C структур и добавить в наследник невиртуальные функции, конструктор/деструктор, перегрузить, операторы, написать шаблоны функций и классов и работать уже с такими вот навороченными объектами. При этом не утеряв бинарную совместимость, т.е. те же экземпляры я скармливаю железке и plain C API без каких-либо преобразований.

Вопрос имхо здесь в другом. В D структуры совместимы с C. Копируете из Сишного хидера структуру, определяете ее и делаете с ней все что хотите. Насчет наследования, имхо, оно не для этих случаях. Во многих умных книжках по С++ часто советуют предпочитать наследованию композицию. Насчет работы со структурами - можете глянуть в исходники GtkD - имхо достаточно удачный пример биндинга к Сишной либе.
С шаблонами также проблем не будет.
В С++ не нужно ничего никуда копировать - ты просто инклюдишь эти хедеры.
Совместимые с plain C структуры есть практически во всех языках: Pascal, VB, Python, Hascell.
Какие из них на этом основании можно назвать "низкоуровневыми"?
Но только в С++ с ними можно прозрачно работать - наследоваться, добавлять методы, использовать в шаблонах без необходимости дополнительной конвертации.
Т.е. ещё раз повторяю вопрос: В чём преимущества именно "низкоуровневости" D по сравнению с С++?
Все фишечки С++ которые я описал дают серьёзный выигрыш в производительности программиста практически не давая оверхеда при выполнении.
Что тут может предложить D?
Если нечего - то и сравнивать его нужно с теми же Pascal, Ada, C#, Java.
И не говорить про какую-то абстрактную "низкоуровневость". Улыбающийся

Насчет Ады - в поисках как должен работать биндинг Qt наткнулся на QtAda. Читать код на Аде имхо невозможно, это просто ужас.
Привычки. Улыбающийся
Записан
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #37 : Октябрь 29, 2008, 10:25 »

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

Скажу из опыта, что если в gcc (как минимум версия 4.1.2) для C кода включить профилировщик, так же можно наблюдать нереальные глюки. D в этом смысле не одинок Улыбающийся.
Записан

Собираю информацию по крупицам
http://webhamster.ru
Eldar
Гость
« Ответ #38 : Октябрь 29, 2008, 11:45 »

Цитировать
Все фишечки С++ которые я описал дают серьёзный выигрыш в производительности программиста практически не давая оверхеда при выполнении.

Я бы не сказал что вызовы st.processStruct() по сравнению с processStruct(st) дают серьезный выйгрыш в производительности. Также как и конвертация хидеров(которую можно проводить автоматически Подмигивающий ) А то что нельзя наследоваться - еще раз повторюсь - я бы в этом случае предпочел композицию и обернул в класс(не только в D но и С++) - а уже классы дают гораздо больше возможностей и в конечном итоге к повышению производительности:
Код:
class Wrapper
{
   PlainCStruct struct;
}
Это занимает много времени?

Хотя конечно тот же самый OO враппер гтк для С++ конечно проще было писать, чем для D. С этой точки зрения не спорю - С++ удобнее..
« Последнее редактирование: Октябрь 29, 2008, 11:47 от Eldar » Записан
Tonal
Гость
« Ответ #39 : Октябрь 29, 2008, 12:30 »

Цитировать
Все фишечки С++ которые я описал дают серьёзный выигрыш в производительности программиста практически не давая оверхеда при выполнении.
Я бы не сказал что вызовы st.processStruct() по сравнению с processStruct(st) дают серьезный выйгрыш в производительности. Также как и конвертация хидеров(которую можно проводить автоматически Подмигивающий )
Смотри выделенное.

А то что нельзя наследоваться - еще раз повторюсь - я бы в этом случае предпочел композицию и обернул в класс(не только в D но и С++) - а уже классы дают гораздо больше возможностей и в конечном итоге к повышению производительности:
Код:
class Wrapper
{
   PlainCStruct struct;
}
Это занимает много времени?
Это занимает время и раздувает код.
Во всех методах Wrapper-а тебе нужно указать префикс struct...
Во всех системных вызовах где будут использоваться экземпляры Wrapper нужно явно преобразовывать туда и обратно.
Для случая наследования в С++ этого делать не надо - т.е. очивидный выигрыш при написании и сопровождении кода.
Кто ближе к "низкому" уровню?
На чём писать такой код проще?
Какой код проще поддаётся оптимизации - с промежуточными действиями или без оных?
Какие именно возможности дают классы обёртки к "повышению производительности в конечном итоге"?

Хотя конечно тот же самый OO враппер гтк для С++ конечно проще было писать, чем для D. С этой точки зрения не спорю - С++ удобнее..
Отож. Улыбающийся
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #40 : Октябрь 29, 2008, 13:09 »

Ну давайте подробнее - что представляет собой вызов виртуального метода это по сути что-то похожее на *(ptr+x*y)func(). порассуждаем - для соврременных процессоров операция умножения такая уж дорогая? Это только предвапрительное суждение, компилятор D анализирует иерархию и преобразует виртуальные вызовы в обычные если в этом нет необходимости. А вот вызов слота по сигналу намного медленнее.

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

Для примера рассмотрим функцию класса, вычисляющую, например, определитель квадратной матрицы, что в лучшем случае выполняется за O(n*n*n) операций, где n - размерность матрицы. То есть, например, для матрицы размерности 5, это уже как минимум 125 обращений к памяти (а в действительности, больше). Соответственно издержки от объявления этой функции виртуальной составляют менее 1%. Про мат. вычисления уже говорил выше Tonal.

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

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
Eldar
Гость
« Ответ #41 : Октябрь 29, 2008, 13:48 »

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

Цитировать
Все фишечки С++ которые я описал дают серьёзный выигрыш в производительности программиста практически не давая оверхеда при выполнении.
Я бы не сказал что вызовы st.processStruct() по сравнению с processStruct(st) дают серьезный выйгрыш в производительности. Также как и конвертация хидеров(которую можно проводить автоматически Подмигивающий )
Смотри выделенное.

А то что нельзя наследоваться - еще раз повторюсь - я бы в этом случае предпочел композицию и обернул в класс(не только в D но и С++) - а уже классы дают гораздо больше возможностей и в конечном итоге к повышению производительности:
Код:
class Wrapper
{
   PlainCStruct struct;
}
Это занимает много времени?
Это занимает время и раздувает код.
Во всех методах Wrapper-а тебе нужно указать префикс struct...
Вы так и не разъяснили какой выйгрыш в производительности дает st.processStruct() по сравнению с processStruct(st) . Честно - не пойму.
В общем и целом я понял что Вы имеете в виду, но согласитесь  - D предлагая существенно более высокий уровень удобства не теряет связи с системой. Не бывает универсальных языков. Если работать с системой преимущественно, писать драйверы для ОС или еще что-то следует предпочесть основной язык системы. В случае же с D - это просто дополнительная возможность - в случае необходимости легко получить доступ к системе.
« Последнее редактирование: Октябрь 29, 2008, 14:04 от Eldar » Записан
SASA
Гость
« Ответ #42 : Октябрь 29, 2008, 17:00 »

Делегаты - аналог системы сигнал-слот в Qt. Несколько устарелое явление, т.к. является частным случаем замыкания + лямбда. А лямбды и замыкания сейчас как раз входят в моду: .Net 3 и C++x0. Улыбающийся

Первоклассник: «Папа, а как пишется цифра восемь?»
Отец: «Возьми знак бесконечности и поверни на пи пополам.»

Про Ди. Рассматривать язык отдельно не имеет смысла. 90% (а то и больше) функционала прикладных программ это библиотеки. Сейчас я пишу на cpp+Qt и у меня есть замечательный классы для строк, массивов, словарей и т.д. Раньше писал с MFC. И там тоже всё было. И отсутствие типа «строка» в языке мне до лампочки. Плюс к этому – функционал QString, наверное, побольше чем у строк Ди.
Про Qt. Писали что Qt – костыли. Согласен. Но костыли-скороходы.
Записан
ритт
Гость
« Ответ #43 : Октябрь 29, 2008, 21:47 »

ребят, хватит уже про "костыли", а?
std:: - стандартные расширения языка; boost:: - расширения, по тем или иным причинам не попавшие (пока) в "стандартные" - почитайте историю проекта буст...
Qt проводит ряд врапперов над этими расширениями, к тому же буст в кутэ используется крайне редко (за исключением вэбкита, который таскает с собой собственный ряд врапперов)
как можно расширения называть "костылями"? как можно QVector называть "костылём"? чем не нравится qforeach?

Си изначально был задуман как язык с минимальным встроенным функционалом, где все необходимые расширения будут подключаться по мере надобности, а при таком подходе расширения критически необходимы...
возьмём примера ради работу со строками - имеется стандартное расширение std::string, НО никто не заставляет программиста использовать именно это расширение - вы вполне можете написать что-то более производительное или лучше отвечающее требованиям; также отпадает проблема с кодированием и структурированием строк (а вдруг ещё лет через 10 придумают utf-88 и 555-терминантные строки?). т.о. Си изначально не зависит от прихотей моды и тенденций - всегда можно написать необходимую реализацию и использовать её в качестве основной реализации строк (хэша, вектора и т.п.)

единственное, с чем соглашусь - include (а в особенности, include/include_next) иногда бывает неудобным...часто из-за того, что человеку свойственно что-то забывать...например, гварды Улыбающийся
но такие "детские болезни" легко излечиваются выбором удобной среды разработки.
Записан
Eldar
Гость
« Ответ #44 : Октябрь 30, 2008, 03:06 »

С ньюсгруп на digitalmars.com - How does D improve design practices over C++?
- Unit checking
- Design by contract
- Invariant checks
- Stronger const
- Modules
- Garbage collection
- No automatic copy constructor
- More restrictive operators
- Delegates (Specifically, encouraging there use by making them simple to use)
- Specific constructs such as Interfaces
- More restrictive casting
- No C style Macros
- Overload sets which prevent function call hijacking
- Nested functions
- Structs with value semantics, Classes with reference semantics
- Ability to move (bitcopy) a struct without invoking construction
- Alias parameters to templates
- Compile time function evaluation
- Function, array, and struct literals
- String mixins
- In, reference, and out function parameters
- Lazy function parameters
- Standardized way of doing conditional compilation
- Standardized way of debug conditionals
- Warnings on implicit casts that lose bits
- No uninitialized data
- User defined default initializers for typedefs and fields
- Template constraints
- The override keyword helps you make sure really overriding something.
- encourages less frequent use of pointers
- enforcing better encapsulation.  Things can be shared only in modules
Записан
Страниц: 1 2 [3] 4 5 ... 8   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.17 секунд. Запросов: 23.