Форум программистов, компьютерный форум, киберфорум
ООП и паттерны
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 5.00/34: Рейтинг темы: голосов - 34, средняя оценка - 5.00
1980 / 836 / 115
Регистрация: 01.10.2012
Сообщений: 5,218
Записей в блоге: 2

Учебный пример ООП

13.09.2016, 11:26. Показов 9314. Ответов 123
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день

Знакомство ООП часто начинается с этого примера. Ну не "строчка в строчку" (это я взял первый попавшийся в гугле), но те же классы и методы.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// Базовый класс Фигура
// для него заданы методы, реализация которых
// отложена для выведенных классов
 
class Shape
{
public:
// Внешняя часть класса
    virtual bool Draw() = 0; // Перерисовать фигуру
    virtual bool Move(double _x, double _y) = 0; // Сдвинуть фигуру
    virtual bool Zoom(double scale) = 0; // Масштабировать
 
protected:
    // Защищенная часть класса, доступная только
    // выведенным из него классам
 
    double coordX; // Атрибут - координата X
    double coordY; // Атрибут - координата Y
};
 
// Класс Круг выведенный из класса Фигура
class Circle : public Shape
{
public:
    virtual bool Draw() {...}; // Реализация перерисовки
    virtual bool Move(double _x, double _y) {...}; // Реализация сдвига
    virtual bool Zoom(double scale) {...}; // Реализация операции масштабирования
 
private:
    // Внутренняя часть доступная только самому классу
    double radius; // Атрибут - длина радиуса
};
 
// Класс Квадрат выведенный из класса Фигура
class Square : public Shape
{
 
public:
    virtual bool Draw() {...}; // Реализация перерисовки
    virtual bool Move(double _x, double _y) {...}; // Реализация сдвига
    virtual bool Zoom(double scale) {...}; // Реализация операции масштабирования
 
private:
    // Внутренняя часть доступная только самому классу
    double side; // Атрибут - длина стороны квадрата
};
После первого знакомства прошло несколько лет (а для кого и много лет), теперь Вы обладаете гораздо большим опытом. Как изменилось Ваше отношение к этому примеру? Что в нем наивно (или просто плохо), а что остается верным и правильным?

С уважением
Игорь
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
13.09.2016, 11:26
Ответы с готовыми решениями:

Неизвестные переменные в сценарии(учебный пример)
Учебный сценарий l> <head> <title>Котировка акций от NASDAQ</title> </head> <body> <?php // Выбор обозначения...

Учебный пример реализации веб приложения или сайта
Нужен учебный(полноценно-рабочий) пример реализации веб приложения или сайта. Родные Erlang и OTP, а не Elixir.

Не работает учебный пример с БД: "произошла ошибка, связанная с сетью или с определенным экземпляром"
Начал писать учебный пример с msdn http://msdn.microsoft.com/ru-ru/library/bb386940.aspx написал тренировочный код: using System; ...

123
 Аватар для Fulcrum_013
2083 / 1576 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
16.09.2016, 21:31
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от EVP Посмотреть сообщение
Это существенно для числодробилок
Занимался в свое время кое каким научным числодроблением. Так вот полиморфизм в числодробительной части обычно притыкнуь некуда и незачем. Ни статический ни динамический. В основном это решение дифуров либо методом конечных объемов (сеток) либо методом конечных элементов. При этом усе елементы одинаковы, разница только в значениях парамтров, а в методе сеток вообще удобнее пользовать структуры массивов а не массивы структур особенно если шаги вычисления делаются синхронно для всех узлов сетки а сеток в методе несколько последовательно вычисляемых.
0
 Аватар для Fulcrum_013
2083 / 1576 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
16.09.2016, 21:38
Цитата Сообщение от EVP Посмотреть сообщение
Почему сравниваешь с ифами, если можно сравнить с вариантом с кортежами?
Потому как если реальный тип неизвестен в момент компиляции вариантов два: либо индирект вызов/переход по адресу из VMT либо ветвление на основе typeid до инструкции в которой записан обычный вызов/переход. Третьего не дано набором инструкций процессора. А если реальный тип должен быть известен в момент компиляции то кроме ветвящихся костылей вариантов вообще не существует.
0
510 / 272 / 60
Регистрация: 14.12.2010
Сообщений: 548
16.09.2016, 22:21
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Потому как если реальный тип неизвестен в момент компиляции вариантов два
Ну да,
Что может говорить хромой об искусстве Герберта фон Караяна? Если ему сразу заявить, что он хромой, он признает себя побежденным.
А если все типы известны?
А если ограничиться только известными типами?
А если их немного и динамическое расширение не требуется?

Мне представляется, что ты в крайность впадаешь. Выбирайся из неё.
Там за пределами динамического связывания есть жизнь Ну, мне так видится.
0
 Аватар для Fulcrum_013
2083 / 1576 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
16.09.2016, 23:17
Цитата Сообщение от EVP Посмотреть сообщение
Там за пределами динамического связывания есть жизнь
Меня сейчас больше другой вопрос волнует : есть ли жизнь в GPU.
Цитата Сообщение от EVP Посмотреть сообщение
А если все типы известны?
А если связи между ними нужно переключать динамически? Пример - типов пушек несколько а гашетка одна.
При этом сам принцип переключения на момент компиляции неизвестен (набор взаимосвязей переключателей и список установленных пушек в датапаке). Как на меня уж лучше иметь кое где виртуальные методы, но при этом иметь 100kb экзешки и 50кб хорошо читаемого кода, и пользоваться такими штукенциями как датабиндинг и т.п., чем тонны мозговныносящей свиньи, десятки метров экзешника и кучу ограничений. В результате и быстрее и надежнее будет. А от индирект вызовов все равно никуда не денешься ни c DX ни с OpenGL, их функционал на 100% из dll тянется а соответственно живет на индирект вызовах. Так же как и весь WinAPI.
Не от хорошей жизни с праметрическим полиморфизмом в HLSL ООП и динамическое связывание ввели.

Добавлено через 15 минут
Цитата Сообщение от EVP Посмотреть сообщение
А если все типы известны?
Цитата Сообщение от EVP Посмотреть сообщение
А если ограничиться только известными типами?
Если бы у бабушки было то что есть у дедушки нас бы вообще не было.
Цитата Сообщение от EVP Посмотреть сообщение
А если их немного и динамическое расширение не требуется?
Ну да типа сначала виртуальные методы забудь потом указатели забудь... а вот не получится очень многие весчи без указателей так же быстро и эффективно как с указателями. А если есть указатели а тем более размеры инстансов больше 32 байт то уже сугубо пофиг есть ли виртуальные методы или нету. Если б размеры инстансов до 32 байт к примеру были тогда да есть смысл вместо указателей сделать их эмуляцию на индексах массивов. Но даже долбанная пуля по минимуму 54 байта.
0
Модератор
Эксперт функциональных языков программирования
3141 / 2289 / 469
Регистрация: 26.03.2015
Сообщений: 8,920
17.09.2016, 00:01
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
В языках с автоматической сборкой мусора это всегда гемморойное дело.
Вы пишите о том, что знаете? Много программ на хаскеле написали и сталкивались с проблемами?

У хаскеля, действительно, проблемы с памятью. Они выражаются в том, что программу надо писать, понимая, как это будет выполняться на уровне железа. Но эти проблемы связаны с ленивостью языка. И хаскель - единственный ленивый функциональный язык, который я знаю. У других ФЯ таких проблем нет. Нет таких проблем и у С#.
0
 Аватар для Fulcrum_013
2083 / 1576 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
17.09.2016, 01:09
Цитата Сообщение от Shamil1 Посмотреть сообщение
У других ФЯ таких проблем нет. Нет таких проблем и у С#.
Угу. типа проблемы мертвых подписчиков вообще типа не существует.

Добавлено через 25 минут
Цитата Сообщение от Shamil1 Посмотреть сообщение
Но эти проблемы связаны с ленивостью языка
Ну если программист не знает нужны ли данные передаваемые в функцию это уже само по себе проблема.
0
1980 / 836 / 115
Регистрация: 01.10.2012
Сообщений: 5,218
Записей в блоге: 2
17.09.2016, 09:40  [ТС]
Цитата Сообщение от Shamil1 Посмотреть сообщение
А если надо выводить на экран не Квадраты, а, например, Заказы?
У Вас частный случай общей задачи. Есть промежуточный язык/формат/протокол, поэтому задача сразу решается сама собой: один класс переводит данные в этот формат, а другой - из этого формата. В общем случае так не получится.
Да, и видимо ничего другого и нет. Напр если мы рисуем OpenGL то все объекты обязаны иметь минимум фейсы и вертексы которые должны быть доступны рисовальщику по чтению.

Если Model-View (Qt) то объект должен быть табличкой (строки/столбцы), где ячейки могут хранить фиксированный набор типов (хотя он велик и расширяем статически). Без этого "view" нечего рисовать

Если же никакой общности нет (Квадраты и Заказы), то остается откатиться в процедурное программирование, возможнно с темплейтами для "отрисовки всех"

В любом случае смешивать данные и отрисовку - грубая ошибка архитектуры
Цитата Сообщение от EVP Посмотреть сообщение
Нет, разница в скорости огромна.
Да бог с Вами, времена таких мышиных оптимизаций давно канули в Лету
0
 Аватар для Fulcrum_013
2083 / 1576 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
17.09.2016, 12:20
Цитата Сообщение от Igor3D Посмотреть сообщение
Напр если мы рисуем OpenGL то все объекты обязаны иметь минимум фейсы и вертексы которые должны быть доступны рисовальщику по чтению
Только при этом они полями объекта не являются а живут себе в буфере. Так же и с элементами заказа.
Цитата Сообщение от Igor3D Посмотреть сообщение
Если же никакой общности нет (Квадраты и Заказы), то остается откатиться в процедурное программирование, возможнно с темплейтами для "отрисовки всех"
Поля заказа это обычно те же прямоугольники с вписанным в них текстом.
Цитата Сообщение от Igor3D Посмотреть сообщение
В любом случае смешивать данные и отрисовку - грубая ошибка архитектуры
Ну все обычно сводится к тому что объекты не напрямую рисуются а так или иначе управляют своей отрисовкой через внешний отрисовщик.

Добавлено через 9 минут
Цитата Сообщение от Igor3D Посмотреть сообщение
Да бог с Вами, времена таких мышиных оптимизаций давно канули в Лету
Не совсем. Учитывая разницу скорости доступа к кешу и к ОЗУ ликвидация гонки указателей может производительность и в 50 раз поднять. Но опять же слишком большое разростание кода устраивает гонку указателей уже по переходам а не по данным. При этом доступ к данным инстанса все равно вызывает промахи кеша если телепатор-предсказатель предкеширования не смог стелепатить куда доступ будет.

Добавлено через 5 минут
При этом никакой разнецы нет будут закешированы данные инстанса до вызова при VMT-лукапе или изнутри вызываемой функции при доступе. При этом код вызываемой функции окажется в кеше гораздо вероятнее для динамического полиморфизма нежели для статического, как и то что сама VMT будет в кеше, особенно если типов не очень много.
0
1980 / 836 / 115
Регистрация: 01.10.2012
Сообщений: 5,218
Записей в блоге: 2
17.09.2016, 14:35  [ТС]
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Учитывая разницу скорости доступа к кешу и к ОЗУ ликвидация гонки указателей может производительность и в 50 раз поднять.
Розкажи, розкажи мені, поле
(Павло Тичина)
0
Модератор
Эксперт функциональных языков программирования
3141 / 2289 / 469
Регистрация: 26.03.2015
Сообщений: 8,920
17.09.2016, 20:55
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Угу. типа проблемы мертвых подписчиков вообще типа не существует.
Не существует. При необходимости можно использовать слабые ссылки. А написать код так, чтобы память текла, можно и на языках без автоматической сборки мусора.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Ну если программист не знает нужны ли данные передаваемые в функцию это уже само по себе проблема.
Ленивость языка открывает множество новых возможностей. Но их использование без потери производительности требует дополнительной квалификации.
0
 Аватар для Fulcrum_013
2083 / 1576 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
17.09.2016, 21:20
Цитата Сообщение от Shamil1 Посмотреть сообщение
А написать код так, чтобы память текла, можно и на языках без автоматической сборки мусора
В языках с ручной сборкой мусора гораздо труднее утечь память чем в языках с автоматической. А если уж вдруг что то течет то находится мгновенно. Кстати висящая ссылка гораздо в этом плане лучше чем мертвый подписчик. Т.к. вылетит ссразу и известно где.

Добавлено через 4 минуты
Цитата Сообщение от Shamil1 Посмотреть сообщение
Ленивость языка открывает множество новых возможностей.
Разве что это ООП язык. Но и возможности во первых не такие уж и большие (кешировние изменений состояний с перевычислением по потребности а не по изменению), во вторых стоимость обеспечения ленивости может оказаться гораздо выше экономии вычислений от ее использования.
А вот если это касается просто передачи параметров в функции, то если программист не знает какие из заказанных им же данных ему нужны это уже очень большие проблемы.
0
Модератор
Эксперт функциональных языков программирования
3141 / 2289 / 469
Регистрация: 26.03.2015
Сообщений: 8,920
17.09.2016, 23:05
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Но и возможности во первых не такие уж и большие
Откуда Вам знать, если Вы этим не пользуетесь?

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
(кешировние изменений состояний с перевычислением по потребности а не по изменению)
Это далеко не единственная возможность использования ленивости.
В строгих языках так же нередко используется ленивость, но её приходится задавать явно, и это усложняет код.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
во вторых стоимость обеспечения ленивости может оказаться гораздо выше экономии вычислений от ее использования
экономия вычислений от использования ленивости может оказаться гораздо выше стоимости обеспечения ленивости

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
А вот если это касается просто передачи параметров в функции, то если программист не знает какие из заказанных им же данных ему нужны это уже очень большие проблемы.
Большие проблемы - это отсутствие опыта.
Элементарный пример: функция для поиска значения по ключу может принимать вторым аргументом значение, которое необходимо вернуть, если ключ не найден. Например, при чтении настроек (файлов конфигурации) такой подход используется почти всегда. Понадобится ли второй аргумент?
А парсер методом рекурсивного списка писали когда-нибудь?
Есть варианты использования и посложнее. Но чтобы их понять, нужно знать про алгебраические типы данных и сопоставление по образцу.
0
 Аватар для Fulcrum_013
2083 / 1576 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
17.09.2016, 23:48
Цитата Сообщение от Shamil1 Посмотреть сообщение
Понадобится ли второй аргумент?
Сколько с такими делами не сталкивался,а этот второй аргумент обычно константный.
Цитата Сообщение от Shamil1 Посмотреть сообщение
А парсер методом рекурсивного списка писали когда-нибудь?
Разве что рекурсивный парсер формул. Только там такая штука нафиг не нужна. Да и парсер такой применим разве что для чего то очень простого если оно нужно экстренно.
Цитата Сообщение от Shamil1 Посмотреть сообщение
Есть варианты использования и посложнее. Но чтобы их понять, нужно знать про алгебраические типы данных и сопоставление по образцу.
АДТ - фактически логичский высер математиков понятия не имеющих как комп фунциклит, фактически являющийся параметрическим полиморфизмом.
0
Модератор
Эксперт функциональных языков программирования
3141 / 2289 / 469
Регистрация: 26.03.2015
Сообщений: 8,920
18.09.2016, 00:34
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Сколько с такими делами не сталкивался,а этот второй аргумент обычно константный.
Этот второй аргумент может подгружаться форматироваться и/или подгружаться из ресурсного файла.
string.Format("{0:0.0}", Resourses.MyFile.MyKey)

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Только там такая штука нафиг не нужна. Да и парсер такой применим разве что для чего то очень простого если оно нужно экстренно.
Опять Вы пишите категоричные заявления о том, чего не знаете.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
АДТ - фактически логичский высер математиков понятия не имеющих как комп фунциклит, фактически являющийся параметрическим полиморфизмом.
Уверен, что те, кто писал компиляторы для многочисленных языков программирования, использующих АТД, лучше Вас понимают, как "комп фунциклит".
Про "параметрический полиморфизм" Вы ошибаетесь.
0
 Аватар для Fulcrum_013
2083 / 1576 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
18.09.2016, 01:43
Цитата Сообщение от Shamil1 Посмотреть сообщение
Этот второй аргумент может подгружаться форматироваться и/или подгружаться из ресурсного файла. string.Format("{0:0.0}", Resourses.MyFile.MyKey)
Типа дефаултные настройки грузим из другого конфига. Тогда уж проще подгрузить дефаултный, скомбинировать с просто конфигом, а результат как надо отформатировать.

Добавлено через 42 минуты
Цитата Сообщение от Shamil1 Посмотреть сообщение
Уверен, что те, кто писал компиляторы для многочисленных языков программирования, использующих АТД, лучше Вас понимают, как "комп фунциклит".
Про "параметрический полиморфизм" Вы ошибаетесь.
Уверен что весь этот АДТ не более чем логический высер людей очень далеких от программирования. И именно из идеи типов-мутантов и растет невозможность смены значения переменной, а не из каких от других. потому как обрабатывать смену значения в рантайме буде слишком накладно при таком подходе к типам. В общем в результате хаскель это не более чем кастрированный бейсик с поддержкой перегрузки операторов. При этом мутирующие типы реально необходимы крайне редко.
0
Модератор
Эксперт функциональных языков программирования
3141 / 2289 / 469
Регистрация: 26.03.2015
Сообщений: 8,920
18.09.2016, 13:09
Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Типа дефаултные настройки грузим из другого конфига. Тогда уж проще подгрузить дефаултный, скомбинировать с просто конфигом, а результат как надо отформатировать.
Ресурсный файл - это не конфиг. Ресурсный файл содержит локализованные строки. Значения будут разные для разных пользователей (с разными языковыми настройками).

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

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
Уверен что весь этот АДТ не более чем логический высер людей очень далеких от программирования.
Ваша уверенность основана на некомпетентности. "Не читал, но осуждаю".

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
И именно из идеи типов-мутантов и растет невозможность смены значения переменной, а не из каких от других. потому как обрабатывать смену значения в рантайме буде слишком накладно при таком подходе к типам.
Идея неизменямых переменных независима от АТД. Неизменяемые переменные имеют много преимуществ по сравнению с изменяемыми. В большинстве языков присутствуют и те, и другие. Даже в Вашем любимом С++ специальный синтаксис, который гарантирует, что функция не меняет свои аргументы.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
В общем в результате хаскель это не более чем кастрированный бейсик с поддержкой перегрузки операторов.
Я Вам уже писал, что АТД - это не "фактически являющийся параметрическим полиморфизмом". Вы очень часто очень категорически пишите о том, чего не знаете.

Пример параметрического полиморфизма:
Haskell
1
2
3
4
myfunc x y = x + y
 
a = myfunc 1 2
b = myfunc 1.0 2.0
Параметрический полиморфизм реализуется за счёт того, что компилятор создаёт несколько версий одной функции.

Вот пример использования АТД:
Haskell
1
2
3
4
5
data Color = Square Double | Circle Double | Rectangle Double Double
 
myfunc (Square a) = a * a
myfunc (Circle r) = 3.14 * r / 2
nyfunc (Rectangle a b) = a * b
Компилятор создаст лишь один вариант функции, а требуемое поведение реализуется за счёт таблицы переходов.

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
При этом мутирующие типы реально необходимы крайне редко.
Простой пример:
Получение целочисленного значения из базы данных. Функция возвращает либо целое число, либо NULL.
Аналогично, поиск целочисленного значения по ключу в словаре (вместо традиционной корявой конструкции с out параметрами).
И, кстати, код "Вариант 1" - это неуклюжая попытка имитировать АТД. (Неуклюжая, потому что enum может принимать не только значения из списка)
0
510 / 272 / 60
Регистрация: 14.12.2010
Сообщений: 548
18.09.2016, 13:32
Цитата Сообщение от Igor3D Посмотреть сообщение
времена таких мышиных оптимизаций давно канули в Лету
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <vector>
#include <iostream>
#include <chrono>
 
#define DEFAULT_COUNT 10000000
 
class A{
public:
    virtual int call(int _i, int _k)
    {
        return _i * _k;
    }
};
 
class B {
public:
    int call(int _i, int _k)
    {
        return _i * _k;
    }
};
 
template<typename Func, typename T, size_t N = DEFAULT_COUNT>
std::pair<double, std::vector<int>> test(T& a, Func _f)
{
    std::vector<int> vdata(N, 1);
 
    auto vstart = std::chrono::high_resolution_clock::now();
    for (auto& i : vdata)
    {
        i = _f(a, i, 2);
    }
    auto vend = std::chrono::high_resolution_clock::now();
 
    std::chrono::duration<double> vdelta = vend - vstart;
    return std::make_pair(vdelta.count(), std::move(vdata));
}
 
int main()
{
    A a;
    B b;
 
    auto ra = test(a, [](auto& a, int i, int k) { return a.call(i, k); });
    auto rb = test(b, [](auto& a, int i, int k) { return a.call(i, k); });
    auto rd = test(a, [](auto& a, int i, int k) { return i * k; });
    
    std::cout << "a" << ra.first << std::endl;
    std::cout << "b" << rb.first << std::endl;
    std::cout << "d" << rd.first << std::endl;
    std::cout << "a/b == " << ra.first / rb.first << std::endl;
    std::cout << "a/d == " << ra.first / rb.first << std::endl;
    std::cout << "b/d == " << rd.first / rd.first << std::endl;
 
    auto iterA = ra.second.begin();
    auto iterB = rb.second.begin();
    auto iterD = rd.second.begin();
 
    bool eq = true;
    for (; iterA != ra.second.end(); ++iterA, ++iterB, ++iterD)
    {
        if (*iterA != *iterB)
        {
            eq = false;
            break;
        }
        if (*iterA != *iterD)
        {
            eq = false;
            break;
        }
    }
 
    std::cout << "eq == " << eq << std::endl;
    
    return 0;
}
/*Output:
a0.0323317
b0.015641
d0.0150073
a/b == 2.06711
a/d == 2.06711
b/d == 1
eq == 1
*/

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

Так, например, переделка кода с Java на C++
без изменения алгоритмов проводит к увеличению скорости до 20 раз,
за счёт убирания ненужных косвенных вызовов и последующих оптимизаций компилятора.

Вот такие нынче времена
0
1980 / 836 / 115
Регистрация: 01.10.2012
Сообщений: 5,218
Записей в блоге: 2
18.09.2016, 16:06  [ТС]
Цитата Сообщение от EVP Посмотреть сообщение
Тут виртуальность дала просадку по скорости в два раза.
Компилятор не смог устранить виртуализацию, хотя, теоретически, мог бы это сделать.
А давайте попробуем добавить малюююсенькую нагрузку, а то на холостом ходу мы кеш меряем
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <vector>
#include <iostream>
#include <chrono>
#include <cmath>
 
#define DEFAULT_COUNT 10 * 1000 * 1000
 
inline float Calc( int a, int b )
{
    return atan2((float) a + 0.5f, (float) b);
//  return a * b;
}
 
class A{
public:
    virtual int call(int _i, int _k)
    {
        return Calc(_i, _k);
    }
};
 
class B {
public:
    int call(int _i, int _k)
    {
        return Calc(_i, _k);
    }
};
 
template<typename Func, typename T, size_t N = DEFAULT_COUNT>
std::pair<double, std::vector<int>> test(T& a, Func _f)
{
    std::vector<int> vdata(N, 1);
 
    auto vstart = std::chrono::high_resolution_clock::now();
    for (auto& i : vdata)
    {
        i = _f(a, i, 2);
    }
    auto vend = std::chrono::high_resolution_clock::now();
 
    std::chrono::duration<double> vdelta = vend - vstart;
    return std::make_pair(vdelta.count(), std::move(vdata));
}
 
int main()
{
    A a;
    B b;
 
    auto ra = test(a, [](A & a, int i, int k) { return a.call(i, k); });
    auto rb = test(b, [](B & a, int i, int k) { return a.call(i, k); });
    auto rd = test(a, [](A & a, int i, int k) { return Calc(i, k); });
    
    std::cout << "a" << ra.first << std::endl;
    std::cout << "b" << rb.first << std::endl;
    std::cout << "d" << rd.first << std::endl;
    std::cout << "a/b == " << ra.first / rb.first << std::endl;
    std::cout << "a/d == " << ra.first / rb.first << std::endl;
    std::cout << "b/d == " << rd.first / rd.first << std::endl;
 
    auto iterA = ra.second.begin();
    auto iterB = rb.second.begin();
    auto iterD = rd.second.begin();
 
    bool eq = true;
    for (; iterA != ra.second.end(); ++iterA, ++iterB, ++iterD)
    {
        if (*iterA != *iterB)
        {
            eq = false;
            break;
        }
        if (*iterA != *iterD)
        {
            eq = false;
            break;
        }
    }
 
    std::cout << "eq == " << eq << std::endl;
    
    return 0;
}
А теперь во сколько раз?

Цитата Сообщение от EVP Посмотреть сообщение
Так, например, переделка кода с Java на C++
без изменения алгоритмов проводит к увеличению скорости до 20 раз,
за счёт убирания ненужных косвенных вызовов и последующих оптимизаций компилятора.
"Без нолика" (т.е. вдвое) мне кажется более реалистичным. Конечно если исходный текст наплевательски относится к скорости, то можно и в 100 раз - но это уже не проблема языка
0
510 / 272 / 60
Регистрация: 14.12.2010
Сообщений: 548
18.09.2016, 19:38
Цитата Сообщение от Igor3D Посмотреть сообщение
А давайте попробуем добавить малюююсенькую нагрузку, а то на холостом ходу мы кеш меряем
Мы же сильные стороны рассматриваем каждой техники
Указатель - барьер для оптимизаций.
Увеличив косвенность вдвое, скорость падает ещё в два раза, итого более четырёх раз.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <vector>
#include <iostream>
#include <chrono>
 
#define DEFAULT_COUNT 10000000
 
class A{
public:
    virtual int call(int _i, int _k)
    {
        return get(_i) * get(_k);
    }
    virtual int get(int _x)
    {
        return _x;
    }
};
 
class B {
public:
    int call(int _i, int _k)
    {
        return get(_i) * get(_k);
    }
    int get(int _x)
    {
        return _x;
    }
};
 
template<typename Func, typename T, size_t N = DEFAULT_COUNT>
std::pair<double, std::vector<int>> test(T& a, Func _f)
{
    std::vector<int> vdata(N, 1);
 
    auto vstart = std::chrono::high_resolution_clock::now();
    for (auto& i : vdata)
    {
        i = _f(a, i, 2);
    }
    auto vend = std::chrono::high_resolution_clock::now();
 
    std::chrono::duration<double> vdelta = vend - vstart;
    return std::make_pair(vdelta.count(), std::move(vdata));
}
 
int main()
{
    A a;
    B b;
 
    auto ra = test(a, [](auto& a, int i, int k) { return a.call(i, k); });
    auto rb = test(b, [](auto& a, int i, int k) { return a.call(i, k); });
    auto rd = test(a, [](auto& a, int i, int k) { return i * k; });
    
    std::cout << "a" << ra.first << std::endl;
    std::cout << "b" << rb.first << std::endl;
    std::cout << "d" << rd.first << std::endl;
    std::cout << "a/b == " << ra.first / rb.first << std::endl;
    std::cout << "a/d == " << ra.first / rd.first << std::endl;
    std::cout << "b/d == " << rb.first / rd.first << std::endl;
 
    auto iterA = ra.second.begin();
    auto iterB = rb.second.begin();
    auto iterD = rd.second.begin();
 
    bool eq = true;
    for (; iterA != ra.second.end(); ++iterA, ++iterB, ++iterD)
    {
        if (*iterA != *iterB)
        {
            eq = false;
            break;
        }
        if (*iterA != *iterD)
        {
            eq = false;
            break;
        }
    }
 
    std::cout << "eq == " << eq << std::endl;
    
    return 0;
}
/*Output:
a0.0806079
b0.0165149
d0.0144553
a/b == 4.88092
a/d == 5.57634
b/d == 1.14248
eq == 1
*/

Цитата Сообщение от Igor3D Посмотреть сообщение
"Без нолика" (т.е. вдвое) мне кажется более реалистичным.
Java безопасный язык, в нём всё косвенно. Отсюда и такое число (до 20 раз).
Как увеличение порядка косвенности работает смотри выше.

ЗЫ: Не призываю выкидывать виртуальность, а лишь указываю,
что есть ряд случаев, когда она тормозит программу и её можно устранить с выгодой.
0
 Аватар для Fulcrum_013
2083 / 1576 / 169
Регистрация: 14.12.2014
Сообщений: 13,614
18.09.2016, 21:01
Цитата Сообщение от Shamil1 Посмотреть сообщение
Компилятор создаст лишь один вариант функции, а требуемое поведение реализуется за счёт таблицы переходов
В любом случае будут созданы все нужные варианты. Разница будет только в том когда и каким образом будет выбираться адрес перехода.

Добавлено через 9 минут
Цитата Сообщение от Igor3D Посмотреть сообщение
А теперь во сколько раз?
А если еще и инстанс взять потяжелее взять то вообще сравняется. Простой не индирект вызов дает а нелокальность данных.

Добавлено через 20 минут
Цитата Сообщение от Shamil1 Посмотреть сообщение
Идея неизменямых переменных независима от АТД. Неизменяемые переменные имеют много преимуществ по сравнению с изменяемыми. В большинстве языков присутствуют и те, и другие. Даже в Вашем любимом С++ специальный синтаксис, который гарантирует, что функция не меняет свои аргументы.
Не путайте предохранитель от случайного изменения данных в месте их использования и принципиальную невозможность изменять значение. Первое не более чем предохранитель обеспечивающий безопасность. Второе полный идиотизм ведущий к очень высокому росту как потребной памяти так и вычислений. При этом абсолютно никаких преимуществ неизменяемые переменные не дают. Либо алгоритм параллелится либо не параллелится, не зависимо от того есть или нету возможность изменения переменных.
А насчет независимости то вы ошибаетесь,неопределенность фактического типа АДТ при возможности многократного присваивания ведет к комбинаторному взрыву при генерации кода.

Добавлено через 16 минут
Цитата Сообщение от EVP Посмотреть сообщение
Отсюда и такое число (до 20 раз)
такое число в Java от JVM. УМТ имеет квадрачитное время по сравнению со специализированной MT

Добавлено через 3 минуты
Цитата Сообщение от Shamil1 Посмотреть сообщение
Неизменяемые переменные имеют много преимуществ по сравнению с изменяемыми
Для примера их превосходства распараллельте мне плиз уточнение изолированного корня нелинейного уравнения методом Ньютона. Какие преимущества дадут при этом неизменяемые переменные?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.09.2016, 21:01

ООП пример
Доброго времени суток. Тут отыскался один пример в конспекте. Записал на лекции спустя рукава. Хочу восстановить. Где-то что-то...

Пример ООП на D
Пример из книги Язык программирования D Андрей Александреску стр.49 1.6. Интерфейсы и классы Даны числа, нужно найти минимум,...

Не работает пример с ООП
Здраствуйте. Помогите пожалуйста, я не понимаю, как создать простейший объект (например из двух переменных) в паскале и что для этого...

Нужен пример использования ООП
Вот ООП в JavaScript есть, но каким боком его можно использовать? Я еще не сталкивался с такими вещами, в которых процедурно-функциональный...

Нужен пример с использованием ООП
Дарова всем, хотел спросить вас, может кто знает ссылку на инфу о объект - ориентированном программировании в Visual Basic? Я уже весь инет...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru