|
|
  |
С/С++, Почему до сих пор все сидят на древних языках вроде С и С++ |
|
|
|
Nov 17 2014, 14:15
|

Гуру
     
Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237

|
Цитата(dxp @ Nov 17 2014, 16:47)  Не расскажете, чем виртуальные функции отличаются от виртуальных методов? И как одно "унифицируется" в другое? Википедия утверждает, что в отношении к C++ это слова-синонимы. Цитата(dxp @ Nov 17 2014, 16:47)  Правильно ли я понял, что инициализация и размещение выполняются исключительно путём виртуальных вызовов? Нет. Инициализация и размещение происходит при вызове конструктора (функции, одноименной с именем класса), который вызывается неявно при создании объекта. Конечно, при желании конструктор, как и любую другую функцию, тоже можно объявить виртуальным, но вам оно надо?  Цитата(dxp @ Nov 17 2014, 16:47)  И ещё поясните, пожалуйста, что такое "real-time объекты"? А фиг его знает!  Я полагаю, что это объекты , порождаемые динамически в процесе работы программы с коротким временем жизни - порождаем объект, используем, объект самоудалился. Но скорее всего эта терминология не из языка C++, а откуда-то еще.
|
|
|
|
|
Nov 17 2014, 14:28
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 17-11-11
Пользователь №: 68 371

|
Цитата(dxp @ Nov 17 2014, 17:47)  Не расскажете, чем виртуальные функции отличаются от виртуальных методов? И как одно "унифицируется" в другое? В С можно вызывать ф-и через указатели на эти ф-и. Я просто это называю виртуальными ф-ми. Всю инициализацию, в зависимости от того что вы хотите вызвать, естевственно Вы должны делать сами. В С++ это делается автоматом в зависимости от типа создаваемого объекта через таблицу виртуальных методов. Ну и указатель на объект не надо передавать самому. Это делает компилятор. Недостаток данного метода, и почему его нельзя использовать в приложениях критичных к времени исполнения (real-time) вот в чем. Вместо того чтобы просто взять и вызвать метод, С++ сначала определяет тип объекта, потом находит таблицу виртуальных методов, и только потом вызывает метод. Если я это делаю на С, то я просто беру и вызываю: my_object->function1(my_object, ...). my_object это структура объекта. Но при этом я сам руками должен инициализировать указатель на function1. В С++ я просто пишу: my_object->method(). А компилятор добавляет в зависимости от типа нужный метод. В общем на С++ это делает компилятор, а на С я сам. Если мне нужно чтобы метод быстро и часто вызывался без большого оверхеда, я использую С. Например метод фильтрации в обработке аудио. А если мне нужно использовать менеджер памяти для инициализоции кодека, то я использую метод mem_manager->Alloc(...), перед тем как кодек будет запущен. И мне вообще всеравно сколько он выполняется.  Как-то так.  Цитата(dxp @ Nov 17 2014, 17:47)  Правильно ли я понял, что инициализация и размещение выполняются исключительно путём виртуальных вызовов? Не совсем. Я имел в виду то, что если часть кода не критична к времени выполнения: парример инициализация кодека или олгоритма, то я использую виртуальные методы например для менеждера памяти: (Alloc, Free, Clean). Эти методы вызываются на этапе инициализации кодека, но не приложения. Но когда инициализируется приложение, оно уже определяет типы используемых менеджеров. И т.д. Еще поясню. У кодека внутри есть секция которая отвечает за инициализацию его самого. Именно эта секция размещает память, последоваетльность блоков и т.д. И здесь этот кодек вызывает виртуальные методы. А сами объекты били размещены приложением, или даже мной в ф-и main() в зависимости от конфигурации и типа приложения.  Цитата(dxp @ Nov 17 2014, 17:47)  И ещё поясните, пожалуйста, что такое "real-time объекты"? Это те объекты которые вызываются постоянна как поток и критичны ко времени исполнения и ресурсам. Например блоки фильтрации входного сигнала с АЦП. Если обобщить, то вот что получается. Например блок фильтра на 128 отсчетов выполняется за 100 мкС, а расчет коэффициэнтов для этого фильтра выполняется 3 секунды. Но ... расчет коэффициентов я делаю один раз, при старте приложения, а вызов фильтра я делаю 1000 раз в секунду на протяжении всей жизни приложения. В итоге получается что фильтр у меня написан на ассемблере, а расчет коэффициентов я могу написать хоть на С++ хоть на яве. Даже 10 секунд не будут критичны.  Так вот, фильтр в данном случае - real-time.
Сообщение отредактировал Russky - Nov 17 2014, 14:36
|
|
|
|
|
Nov 17 2014, 14:56
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(Russky @ Nov 17 2014, 13:58)  Мне показалось, что большенство ответов пытаются перевести обсуждение asm/C/C++/C# (ява как аналог C#) из технологической области в филосовскую. Это не правильно. Вижу не читали новейшее исследование по теме выбора языков - http://macbeth.cs.ucdavis.edu/lang_study.pdf Обязательно подучите TypeScript. Получите наиболее качественный код. Цитата(Russky @ Nov 17 2014, 16:28)  Так вот, фильтр в данном случае - real-time.  Ну нееее..т, это просто будет DSP блок и не более. А realtime-ом это станет если фильтр будет прерываться еще кучей задач, обслуживать несколько асинхронных входных и выходных потоков и все сделает вовремя.
|
|
|
|
|
Nov 17 2014, 14:58
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 17-11-11
Пользователь №: 68 371

|
Цитата(AlexandrY @ Nov 17 2014, 18:56)  Вижу не читали новейшее исследование по теме выбора языков - http://macbeth.cs.ucdavis.edu/lang_study.pdf Обязательно подучите TypeScript. Получите наиболее качественный код.   Странная статья. Я понимаю когда сравнивают С и раскаль или С# и яву. Но зачем все в кучу мешать?  Цитата(AlexandrY @ Nov 17 2014, 18:56)  Ну нееее..т, это просто будет DSP блок и не более.
А realtime-ом это станет если фильтр будет прерываться еще кучей задач, обслуживать несколько асинхронных входных и выходных потоков и все сделает вовремя. Да. Слово вовремя здесь решает.
|
|
|
|
|
Nov 17 2014, 15:25
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
QUOTE (Xenia @ Nov 17 2014, 21:15)  Википедия утверждает, что в отношении к C++ это слова-синонимы. Тов. Б.Страуструп не согласен с ru.wikipedia, он утверждает, ведя речь, конечно, конкретно про С++, что "Виртуальные функции иногда называют методами". (с). Это точная цитата. Заметьте, не виртуальными методами, а просто методами, сиречь, синонимами являются термины "виртуальная функция" и "метод". Конкретно в контексте ЯП С++. В других ЯП это может быть по-иному. Впрочем, товарищ, к которому был вопрос, уже пояснил, что виртуальными функциями он называет обычные функции, которые вызываются через указатель. Правда, непонятно, почему и что в них такого виртуального. Вызвал функцию обычным образом - она обычная, вызвал через указатель - стала виртуальной. Та же самая функция. Я вот всегда полагал, что функция - она сразу и всегда либо обычная, либо виртуальная, и это определяется квалификатором virtual в её объявлении и порождает вполне конкретное поведение. Ну, да ладно... QUOTE (Xenia @ Nov 17 2014, 21:15)  Но скорее всего эта терминология не из языка C++, а откуда-то еще. Посмею вас заверить, что к терминологии С++ это не имеет ни малейшего отношения. QUOTE (Russky @ Nov 17 2014, 21:28)  В С можно вызывать ф-и через указатели на эти ф-и. Я просто это называю виртуальными ф-ми. Всю инициализацию, в зависимости от того что вы хотите вызвать, естевственно Вы должны делать сами. Я до сих пор наивно полагал, что в С нет виртуальных функций. QUOTE (Russky @ Nov 17 2014, 21:28)  В С++ это делается автоматом в зависимости от типа создаваемого объекта через таблицу виртуальных методов. Ну и указатель на объект не надо передавать самому. Это делает компилятор. Недостаток данного метода, и почему его нельзя использовать в приложениях критичных к времени исполнения (real-time) вот в чем. Вместо того чтобы просто взять и вызвать метод, С++ сначала определяет тип объекта, потом находит таблицу виртуальных методов, и только потом вызывает метод. Вот этот момент можно поподробнее? Как "С++ сначала определяет тип объекта"? Он RTTI анализ с ним производит, что-ли? И когда я писал, например, на MSP430 программу, там вызов виртуальной функции вылился в в две быстрых, однотактовых регистровых команды: 1. загрузка vptr регистр; 2. косвенный вызов функции по адресу из vtbl, которая адресуется из регистра (со смещением, если указателей в vtbl несколько), загруженного на предыдущем шаге. В общем, я тут не видел, чтобы "С++ определял тип объекта". И, соответственно, каких-то накладных, мешающих real-time тоже не усматривается. Код на С (или асме), который будет звать функции из таблицы указателей, будет ровно таким же. Упомянутый тов. Б.Страуструп утверждал (в книжке "Дизайн и эволюция С++"), что когда проектировался механизм виртуальных функций, была цель получить максимально эффективное решение, при котором всё, что можно разрешить на этапе компиляции, должно быть разрешено на этом этапе, а для рантайма оставить только малое количество простых действий - как то: взять указатель vptr у конкретного экземпляра, по нему добраться до vtbl и по адресу из неё вызвать функцию. Никаких определений типов объекта на рантайме уже не выполняется, всё определено и проверено статически на этапе сборки.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Nov 17 2014, 15:28
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(Russky @ Nov 17 2014, 16:58)  Странная статья. Я понимаю когда сравнивают С и раскаль или С# и яву. Но зачем все в кучу мешать?  Почему же куча? Вы разве не знаете что одним из языков программирования beagleboard и других подобных встраиваемых плат является JavaScript? Дроны, квадракоптеры программируются на JavaScript. Я использую JavaScript в своих разработках. Теперь, когда узнал о TypeScript обязательно на него перейду. Все таки наиболее защищенный от ошибок язык.
|
|
|
|
|
Nov 17 2014, 15:30
|
Местный
  
Группа: Свой
Сообщений: 322
Регистрация: 2-07-04
Из: Minsk
Пользователь №: 240

|
QUOTE И когда я писал, например, на MSP430 программу, там вызов виртуальной функции вылился в в две быстрых, однотактовых регистровых команды: что-то мне подсказывает, что это не могли быть однотактовые регистровые команды )) что всего две - вполне верю.
|
|
|
|
|
Nov 17 2014, 16:05
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 17-11-11
Пользователь №: 68 371

|
Цитата(dxp @ Nov 17 2014, 19:25)  Та же самая функция. Я вот всегда полагал, что функция - она сразу и всегда либо обычная, либо виртуальная, и это определяется квалификатором virtual в её объявлении и порождает вполне конкретное поведение. Ну, да ладно... Я могу задать структуру и передавать эту структуру всем заинтересованным объектам как указатель. Эти объекты будут вызывать ф-ю через указатель в этой структуре. Но значение ф-и которую они будут вызывать определяю я, в зависимости от типа объекта. Это по своей сути то-же самое что и виртуальный метод, только таблица храниться не отдельно а в самой структуре. Но таблицу можно сделать статической. И т.д. В общем это детали реализации виртуальных методов. Но сам принцып остается неизменным, что объект который вызывает метод, не знает что за метод он вызывает. Это определяется объектом. Посмею вас заверить, что к терминологии С++ это не имеет ни малейшего отношения. Цитата(dxp @ Nov 17 2014, 19:25)  Вот этот момент можно поподробнее? Как "С++ сначала определяет тип объекта"? Он RTTI анализ с ним производит, что-ли? И когда я писал, например, на MSP430 программу, там вызов виртуальной функции вылился в в две быстрых, однотактовых регистровых команды:
1. загрузка vptr регистр; 2. косвенный вызов функции по адресу из vtbl, которая адресуется из регистра (со смещением, если указателей в vtbl несколько), загруженного на предыдущем шаге.
В общем, я тут не видел, чтобы "С++ определял тип объекта". И, соответственно, каких-то накладных, мешающих real-time тоже не усматривается. Код на С (или асме), который будет звать функции из таблицы указателей, будет ровно таким же. Упомянутый тов. Б.Страуструп утверждал (в книжке "Дизайн и эволюция С++"), что когда проектировался механизм виртуальных функций, была цель получить максимально эффективное решение, при котором всё, что можно разрешить на этапе компиляции, должно быть разрешено на этом этапе, а для рантайма оставить только малое количество простых действий - как то: взять указатель vptr у конкретного экземпляра, по нему добраться до vtbl и по адресу из неё вызвать функцию. Никаких определений типов объекта на рантайме уже не выполняется, всё определено и проверено статически на этапе сборки. Не совсем так, но в общем верно. Все зависит от компилятора и того как вы реализуете вызов. По личным наблюдениям, С++ в разы медленней (чисто вызов). Именно поэтому я использую в некоторых моментах именно С. Не потому что я против С++, а просто С быстрее. И еще учитавайте, что С++ компиляторы разные на разных платформах. В общем, если говорить о asm/C/C++, то на асме у меня 10 ф-й, на С - 20, а на С++ все остальное...  Как-то так.
|
|
|
|
|
Nov 17 2014, 19:21
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(Russky @ Nov 17 2014, 18:05)  По личным наблюдениям, С++ в разы медленней (чисто вызов). Именно поэтому я использую в некоторых моментах именно С. Не потому что я против С++, а просто С быстрее. И еще учитавайте, что С++ компиляторы разные на разных платформах.
Как-то так. Десять баллов!  Обсуждение действительно становится нескучным. Я тут недавно взял и переименовал все свои файлы в проекте с .c на .cpp. Просто ради эксперимента, чтобы проверить насколько легко перейти на C++. Вышло в лет, и медленней работать почему-то не стало . Потом правда вернул обратно. Зачем этот гем.. если все вокруг написано на C-и.
|
|
|
|
|
Nov 17 2014, 20:05
|

Профессионал
    
Группа: Свой
Сообщений: 1 261
Регистрация: 14-05-09
Из: Челябинск
Пользователь №: 49 045

|
Цитата(Russky @ Nov 17 2014, 17:58)  По идее переходя от этапа к этапу, т..е. от ами к С, к С++ и к С# мы жертвуем чем-то ради достижения чего-то. ... Канечно, при каждом переходе мы приносим в жертву производительность. .... Это паранойя что с++ медленнее с. Какая может быть жертва при переходе от С к С++? Как упадет производительность при вызове виртуальной функции? Сами же пишете, что компилятор всё сам сделает. Цитата Эти объекты будут вызывать ф-ю через указатель в этой структуре. Но значение ф-и которую они будут вызывать определяю я, в зависимости от типа объекта. Это по своей сути то-же самое что и виртуальный метод, только таблица храниться не отдельно а в самой структуре. Ну так с++ призван чтоб эту рутину за вас компилятор сделал.
|
|
|
|
|
Nov 17 2014, 20:52
|
Частый гость
 
Группа: Участник
Сообщений: 84
Регистрация: 17-11-11
Пользователь №: 68 371

|
Цитата(juvf @ Nov 18 2014, 00:05)  Это паранойя что с++ медленнее с. Какая может быть жертва при переходе от С к С++? Как упадет производительность при вызове виртуальной функции? Сами же пишете, что компилятор всё сам сделает. Уболтали! Вспомнил я почему я использую С вместо С++! Хотя изначально все было именно на С++!  В общем так. Действительно, разницы между С++ и С при вызовах виртуальных методов практически нет, НО! Разница появляется когда мы начинаем вызывать объекты из кешированной памяти. Если в случае с С я могу руками указать что структура будет размещаться в быстрой памяти (точнее я ее просто могу разместить динамически там), то в случае с С++ я не могу сказать компилятору чтобы он таблицу виртуальных методов для данного класса хранил в быстрой памяти. Либо я указываю что все таблицы для всех классов должны храниться там, а это как правило больше чем доступно памяти, либо ВМТ должна храниться во внешней памяти, и тогда облом с быстродействием...  Но еще скажу, что для С и для С++ я использую С++ компилятор.  Т.е. разница не в компиляторе как таковом, а в методах вызова.
|
|
|
|
|
Nov 18 2014, 05:35
|
Профессионал
    
Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757

|
Цитата(AlexandrY @ Nov 17 2014, 23:21)  Я тут недавно взял и переименовал все свои файлы в проекте с .c на .cpp. Просто ради эксперимента, чтобы проверить насколько легко перейти на C++. Вам мало троллинга в теме про SVN, вы пришил сюда порезвиться? Хорошо, покормлю немного. От того, что вы переименовали файлы, код как был на Си, так он на Си и остался. То, что компилятор Си-два-креста умеет компилировать код на Си, плюс ему, а не вам. Однако не всякий валидный код на Си является валидным кодом на Си-плюс-плюс. Вы, наверное, это и так знаете. Вот честно перепишите свой Си-код на Си-плюс-плюс, тогда и оцените, легко ли перейти на другой язык.
|
|
|
|
|
Nov 18 2014, 07:24
|

Ally
     
Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050

|
Цитата(andrew_b @ Nov 18 2014, 07:35)  От того, что вы переименовали файлы, код как был на Си, так он на Си и остался. То, что компилятор Си-два-креста умеет компилировать код на Си, плюс ему, а не вам. Однако не всякий валидный код на Си является валидным кодом на Си-плюс-плюс. Вы, наверное, это и так знаете. Вот честно перепишите свой Си-код на Си-плюс-плюс, тогда и оцените, легко ли перейти на другой язык. Что значит честно? Обязательно применить библиотеку шаблонов? Так они показали свою неэффективность. Cм. примеры выше. Или обязательно оформить модули в классы и придумать им предков с виртуальными функциями? Так это значит зафлудить свои тексты и разбросать семантические единицы по файлам, потерять скорость кодирования и усложнить отладку. Применить переопределение операторов? Ну это надо быть больным вообще на все голову, или слишком погруженным в предметную область, писать заточенные либы. А это нынче непозволительная роскошь писать либы. Что еще надо честно сделать?
|
|
|
|
|
Nov 18 2014, 08:21
|
Частый гость
 
Группа: Участник
Сообщений: 139
Регистрация: 9-11-12
Из: Санкт-Петербург
Пользователь №: 74 315

|
Цитата(andrew_b @ Nov 18 2014, 13:07)  Сначала ответьте на вопрос: зачем вы переименовали файлы из *.c в *.cpp? очевидно, чтобы лично убедиться, что "С++ в разы медленней (чисто вызов)"
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|