Когда словом недели выпало Процедура, то многие вздрогнули,
ибо перед внутренним взором встало, что-то подобное.
запах дезинфекции не забываем
Однако находчивые и креативные вомбатяне, что особенно
хочется отметить и новые участники ивента, доказали, что процедура это не
только запах больницы и сухие строчки кода, но и…
Лев 14 - новый папа выбранный на этой неделе и ребята из Евротура одобряют этот пост
Суровой методикой процедуры взлома шифров поделился lovefst,
методика проверенная 90-ми, к повторению не рекомендована, что только
добавляет шарма к посту
На этой неделе UrmasTormas напомнил, что песня это то, что
сильно помогало в процедуре изгнания фашисткой нечисти с территории Советского
Союза и Европы! История песни дорога на Берлин отличное тому подтверждение
Слово следующей недели такое, что грешно не отметиться постом!
слово недели на 12.05-18.05
Напоминаем правила ивента: 1.
Раз в неделю, по понедельникам случайно генерится слово. Это слово
будет основой для ваших постов. Неважно что вы сделаете, слепите,
нарисуете, напишите стих с этим словом, расскажете анекдот, свою историю
с этим словом, даже с помощью генератора мемов можно, абсолютно
неважно.
2. Ивент с данным словом длится до следующего понедельника, когда будет озвучено новое, случайно сгенерированное слово.
3.
Необязательно чтобы выпавшее слово было лейтмотивом. Ну например
выпадет слово кит - может быть картинка загадка о морских существах, на
которой изображен один кит, а найти надо дельфина. Или созданный
комикс/мем, в котором вообще речь о другом, но на пряжке у героя
изображен кит. Или может у вас завалялась история из жизни, где кит
просто был второстепенным объектом, или названием бара где все
происходило. Т.е. слово обязательно должно присутствовать в работе, но
может не являться ее заглавной темой. А может и являться.
4. Все посты публикуйте под тегом "Ивент Вомбата" и "Свобода".
@vombat просьба закрепить новое слово, пожаалуйста
Предупреждаю сразу, пишется сие ради лулза (рофла, кека, чебурека) и желания выговориться, тем самым снизить уровень стресса. Или не снизить. Или не стресса.
Общага (ааа, ммм, наркоти... общагааа...), как много в этом простом слове...Общага - это твой дом на время вахты, это место где есть возможность выдохнуть после долгого дня, где работа тебя не достанет (но это не точно). Но это если тебе повезет, и общага будет норм и соседи тоже. А бывает и наоборот. Начнем. ЩИКАРДОС+ Это редкий случай, когда тупо снимается квартира, на 2-3 комнаты и тебе заселяют туда. Часто так делают, когда с/у (строительный участок) только открывается, народа ещё мало и общагу ещё не нашли или не построили. Щикардос. Щикардос, это когда с/у стоит в относительных ебенях, но рядом есть санаторий или ещё какой пионерлагерь и ваша контора, вместо строительства модулей, тупо арендует вот этот вот всё. Зачастую, тут сразу всё в шоколаде, нормальные комнаты, по 2-3 кровати в один ярус, с туалетной/душевой комнатой прям в номере, чистота и порядок, никаких тараканов или (упасиХоспади) клопов. Но такое бывает редко. Щикардос на пол-шишечки. Когда также арендуют какое-то недоофисное здание времён перестройки (КОНТОРА ЁПТ), и переделывают его под общагу в темпе вальса. Это значит, что в каждую комнату постараются набить побольше двухъярусных кроватей, туалет-душевая будут в подвале или в хер-пойми-где, кухня будет выглядеть как два сраных чайника, унылая плитка и микроволновка, распиханных по подоконникам. Тоже неплохо, ибо зачастую такое практикуется, когда с/у находится в черте какого-нибудь города. А значит, рядом магазины и прочая ебутня. Модульные здания. Берется куча сэндвич-панелей, труб, профилей и прочего, и хуяк-хуяк-хуяк, быстренько строится общага. Как правило, все уже спроектировано, нарезано, подготовлено, остаётся только собрать. Есть фуфлыжные модуля, а есть и прям норм такие, теплые, аккуратные, удобные. Обычно все удобства в них есть, хоть и общего пользования. Отдельные вагончики. Те же самые модуля, только сральник на улице, умывальник типа "рукомойник-ведро". Есть с отоплением от электрообогревателя, а есть и с печкой-буржуйкой, то ещё "удовольствие". Бичарник/Клоповник.Тупо ушатанное здание, куда народ запихивают как сельдь в бочку. В комнатах по 18м² стоит по шесть двухъярусных кроватей, дышать нечем, зато не холодно, ибо наперженно/надышано. Крысы, тараканы, клопы, муравьи, алкаши, полный спектр паразитов и вредителей. Уборка отсутствует как таковая, ноги прилипают к полу, мухи прилипают к потолку, накурено везде, сплошная антисанитария, шанс выхватить спидорак и кишечную палочку 99,999999999%. В отдельных случаях попадаются такие бичарники , что люди умудряются ещё и спать по очереди, на одной кровати, типа ночная смена ушла, спит дневная и наоборот. Спасение тут только одно: "Ганс, неси огнемет!"
По видео понять сложно (особенно если ты не летяговед), но скорее всего перед нами красуется парочка обыкновенных гигантских летяг – самых распространённых представителей своего рода. Грызуны известны не только своими габаритами – весят они до 3 килограмм – но и приличными способностями к полёту. В идеальных условиях летяги могут пролететь до 450 метров за раз!
Моя сестра, бывшая Алина, но будучи гражданкой маленького, но гордого государства Израиль пользуется тележками. Да и в Европе в целом тележка - не возрастной ценз. А в России все же гордые! Мы не ищем лёгких путей. )) Я живу в крупном городе-миллионике, где нет смысла иметь свой автомобиль. Ну разве что какой-нибудь пробочно-дорожный мазохист мне возразит. Сегодня закупил много чего вкусного и оно весит ё-моё. Я с телегой, которую сшил сам. (На фото) Ну, я не телегу сшил, понятно. А эту хрень, которая надета на фигню с колёсами. Фигню с колесами я приобрел в Ашане. Без хрени, просто фигню. Потом сшил под фигню хрень. Ясно выразился, надеюсь?)) Ну я много чего шью. Обожаю брутальность в шитье! И чтобы стежок аж 6-7 мм.
Ну к теме. А то отвлёк себя и вас. Какого пениса в России все горазды? На подвиги, разумеется. Сегодня по дороге с большого Магнита встретил и старых и молодых. С огромными пакетами. Пёрли через слезу всю тяжесть. А я такой, насвистывая нецензурочку, боевым маршем да с телегою! )
На заднем плане моя любимая швейная машина. Перестроил стежок под 5-7 мм.
Ну я и по натуральной коже шью... Сумки, кошельки. Только не на продажу. Жена называет меня шьюха.))
Не рекомендуется принимать данную статью близко к сердцу или как истину в последней инстанции. Скорее как научпоп-грелку для мозгов. Тут довольно много упрощений, упущений или просто странно написанных моментов. Если что-то объяснено совсем криво, то добро пожаловать в комментарии.
Все сказанное далее применимо везде, но детали описаны для защищенного режима x86 (только я опустил префиксEдля регистров) и языков семейства C (в основном C и C++, местами C#). Для понимания рекомендуется знать про указатели и базово представлять, что происходит в процессоре.
Приятного чтения.
Думаю все помнят, что такое функция в математике
Начнем со сложного
Глоссарий
Чувствую, что большинство не имеет ни малейшего представления об указателях
В части про x86 я упоминал о том, что процессор представляет из себя бешенный самоуправляемый калькулятор, которому указом может быть разве что хранилище кода, аппаратный сброс и немаскируемое прерывание. И что у него есть системная шина, состоящая из шины адреса, шины данных и шины управления, к которой подключена память, хранящая данные и код.
А память это огромная одномерная полоска, в которой каждая ячейка имеет свой порядковый номер от 0 до 2^(разрядность шины адреса)-1. И указатель представляет из себя самую обычную численную переменную, хранящую номер (адрес) любой ячейки.
Я не понимаю, почему для многих это настолько сложная тема, а существенное количество новичков забрасывают изучение C после встречи с ними. Они в своей сути максимально элементарны (до тех пор, пока не нужно исправлять уязвимости и ошибки, которые появились в результате злоупотребления или неполного понимания нюансов).
Также существуют ссылки, так или иначе представляющие из себя подвид указателей, но обычно с запретом на арифметику с ними (основная сложность и опасность указателей) и/или подсчетом количества активных ссылок для сборки мусора.
Все языки или имеют указатели (Pascal, C, C++, блоки unsafe в C# и Rust), или являются ссылочными (Java, C#, Python, JS, т.д. (почти все современные языки)). С++ тоже имеет ссылки, но как синтаксический сахар над указателями, призванный упростить их передачу в функции и избавиться от проблемы нулевых указателей.
Ассемблер - если вы даже примерно не знаете, что это такое, то первую часть статьи вероятно можно пролистать и перейти на обсуждение парадигм.
Регистр - именованная численная переменная внутри процессора. Может иметь особое предназначение, а может просто использоваться для хранения любых чисел и арифметики. Их немного.
Инструкция - одиночная команда, представляет из себя последовательность из нескольких байт со специальным значением. Любая программа представляет из себя последовательность инструкций внутри памяти. Указатель на инструкцию, которая будет выполнена следующей, содержится в регистре IP, который сам увеличивается после выполнения каждой инструкции. По-хорошему стоило нарисовать пошаговую наглядную анимацию с демонстрацией всех регистров и куском ассемблерного кода, но мне лень, а в гугле я ничего толкового не нашел.
Метка - константа, содержащая адрес чего-либо. К примеру процедуры или глобальной переменной. Примерно как метка для goto в высокоуровневых языках, но универсальнее. Применяются при написании на ассемблере, в процессоре как таковые не существуют и разрушаются до обычных чисел при ассемблировании и линковке.
Разыменование - операция над указателем, когда тот превращается в переменную с адресом, который был записан в указателе (своеобразный пульт Д/У для переменной).
Парадигма - "стиль" написания и постройки архитектуры программы, частично определяется языком. Технически на том же C можно писать в практически любой парадигме (через костыли можно писать в стиле ООП, через макросы реализовать метапрограммирование, а через нестандартные расширения вообще ядерный бред), но родная для него - процедурная. А Go, к примеру, хоть и имеет недоклассы и методы, но лишен практически всех благ ООП и не сильно далеко ушел от C.
Синтаксический сахар - необязательная возможность, которая сокращает количество кода, повышает его читаемость или удобство поддержки
Стек
Большинство процессоров Фон-Неймановской архитектуры в своей конструкции предлагают механизмы стека. Кто играл в покер должны вспомнить стеки фишек. То есть некие значения, сложенные друг на друга (обычно это переменные, в частности адреса в памяти). При этом основными операциями являются добавление фишки на вершину (инструкция PUSH) и ее снятие (инструкция POP). Еще можно косвенно читать и заменять (перезаписывать) фишки относительно вершины (на вершину указывает регистр SP, неявно обновляется через POP и PUSH) или основания (указывает регистр BP) вглубь.
Стеки можно переключать (но не в MOS6502), это нужно для многозадачности
Помимо хранения локальных переменных стек позволяет делать довольно интересную вещь: мы можем положить на стек все необходимые аргументы (x в математике, но их может быть несколько), адрес следующей инструкции (взяв из указателя инструкции IP, это будет адрес возврата), после чего совершить прыжок на какой-нибудь другой адрес (сохранение адреса и прыжок делаются инструкцией CALL).
А на этом адресе может быть функция. Сначала она кладет текущий BP на стек, после чего приравнивает основание к вершине (BP к SP), тем самым создав для себя "новый стек" сразу после предыдущего (это еще называется стековым кадром), в котором якобы лежит только значение старого основания стека (BP), чтобы можно было восстановить его перед возвратом.
Серое это стековый кадр от предыдущей функции
После чего функция может прочитать переданные ей аргументы относительно основания своего стека вниз (технически это будет выход за границы текущего стека), выполнить с этим какие-либо действия (записать в файл, вывести в консоль, просто перемножить) и сохранить результат (обычно результат сохраняется не на стек, а в регистр AX).
После чего функция восстанавливает старое значение BP, сняв его со стека, и выполняет команду RET, которая снимает со стека адрес возврата и совершает переход на него, тем самым переключившись на инструкцию сразу после CALL.
И эта система так или иначе перекочевала в большинство высокоуровневых языков начиная с FORTRAN. К примеру в C CALL превратился в круглые скобки, RET в return, а адреса и метки в имена (при этом без скобок они все еще являются указателями, то есть адресами).
Пример кода (к сожалению, штатного форматирования не предусмотрено):
#include <stdio.h> int pow2(int x) { return x * x; } int main() { int y = pow2(16); // Вызов функции. В y будет сохранено число 256 printf("%p", pow2); // Без скобок вместо вызова просто выведет адрес функции return 0; // Возврат нуля из главной функции означает отсутствие ошибок. }
Такой стиль программирования называется процедурным (выделение кода в блоки называется структурным). А вот называть процедурный язык функциональным совершенно неправильно, ибо функциональное программирование ≠ процедурное, они даже в разных категориях (императивное и декларативное).
А теперь скомпилируем этот код и разберем ассемблерный листинг
Важно понимать, что стек в большинстве архитектур традиционно растет от больших адресов к меньшим (и в x86). То есть для того, чтобы отодвинуть его вершину вверх, от регистра SP нужно отнимать значения, а вот для ужимания и съедания ненужных значений к указателю на вершину значения прибавляют. И для доступа к значениям относительно основания или вершины это тоже важно учитывать. Это может звучать запутанно, но через время привыкаешь и всё становится очевидным.
Надеюсь это возможно будет разобрать. Код скомпилирован MSVC v19.28 для x86 со стандартными настройками в Godbolt
Post scriptum
Это всё довольно упрощенно. Как минимум, в защищенном режиме используется больше 5 разных соглашений о вызове, которые отличаются деталями реализации. Это было описание для cdecl, обычно используемого в C. Еще часто используются соглашения pascal, fastcall, thiscall, winapi и другие. Fastcall, к примеру, избегает хранения аргументов на стеке, если их возможно передать через регистры, что улучшает производительность. А winapi отличается от cdecl тем, что функция сама очищает стек от аргументов для себя при возврате. А еще я упустил, к примеру, сохранение регистров, которые функция может перезаписать и испортить, а потому обязана предварительно сохранить и перед возвратом восстановить, передачу переменного количества аргументов (как в printf) и возврат значений шире 32 бит (которые не влезут в EAX).
Плюс сейчас мало кто компилирует ПО под защищенный 32-битный режим, а в длинном режиме (AMD64) используется пара других соглашений, основанных на fastcall и имеющих несколько отличий друг от друга.
Так процедура или функция? Или подпрограмма?
Процедурное программирование предлагает делить код на подпрограммы, которые принято называть функциями и процедурами (функция обычно является наиболее понятным, частым и обобщенным названием, поэтому я его использую).
Процедура от функции отличается только тем, что функция возвращает какое-то значение (как в математике), а вот процедура этого не делает. Не во всех языках явно есть процедуры (в Pascal есть, но не в C). В таком случае их заменяют функции, возвращающие ничего (void, Unit, undefined, None).
Хотя и тут есть свои особенности. К примеру функция, возвращающая void в C и Java является прямым аналогом процедур, как-либо использовать возвращенное значение из такой функции невозможно, ибо его нет физически. А вот Unit в Kotlin это синглтон (а-ля единственная и уникальная константа уникального типа), ссылку на который можно присвоить в переменную, но в этом особого смысла нет. Undefined в JS и None в Python тоже уникальные константы специальных типов.
Но не тут-то было
Вроде бы процедура никогда не может ничего вернуть...
Только она этого никогда не делает напрямую. При она этом может записать результат в глобальную переменную, а еще часто принимает в себя указатели или ссылки, по которым может записать результат. Это еще удобно тем, что можно "вернуть" несколько значений. Пример:
void procedure(int x1, int *x2, int *x3) { // Функция ничего не возвращает, то есть это процедура *x2 = x1 * x1; // Разыменовываем указатель и записываем по его адресу результат. *x3 = x1 * x1 * x1; // Разыменовываем другой указатель и записываем по его адресу результат. } int y1, y2; procedure(16, &y1, &y2); // В y1 оказался результат, аналогичный прошлому примеру. А в y2 куб числа.
PS: оператор звездочка при указании типа превращает его в тип-указатель, а при применении на переменную-указатель разыменовывает ее до изначальной переменной. Амперсанд превращает переменную в указатель на нее (иногда еще называется оператором получения адреса).
То есть мы вернули сразу 2 разных значения из процедуры, которая якобы ничего не возвращает. Чудеса. Подобные чудеса есть в том числе в Pascal с явным делением на процедуры и функции (плюс там это сделано немного удобнее). Хотя механизм тут отличается от того, который используется в возврате значения из функции и совпадает с механизмом передачи обычных аргументов, поэтому никакой магии.
Еще про связь с математикой
Главное отличие функций в программировании от функций в математике в том, что они могут делать что-то на стороне и не обязаны возвращать одинаковый результат при одинаковых аргументах.
К примеру функция получения случайного числа по определению не может существовать в математике, если она не принимает в себя предыдущее случайное число или зерно для его видоизменения. Или функция записи в файл, возвращающая 0 в случае успеха и другое число при провале. Ко всему прочему, такая функция имеет побочный нематематический эффект, то есть запись в файл, что тоже недопустимо традиционной математикой без высоких абстракций.
Поэтому придумали чистые функции. По сути это ограничитель, которые делают функцию полным отражением таковой в математике. Им запрещено возвращать разные значения при одинаковых аргументах (точнее запрещено всё, что может такое позволить сделать), запрещено обращаться к нечистым функциям, запрещено обращаться к тому, что не является аргументом или локальной переменной, запрещены вообще любые действия, которые могут сделать что-то на стороне (даже функция sin() в C не всегда является чистой, ибо может зависеть от состояния FPU).
Чистые функции через ключевое слово pure явно есть в D и FORTRAN (проверка на чистоту во время компиляции), а также являются основой функционального программирования.
Чистая процедура тоже имеет право на жизнь, используя механизм со ссылками (на счет указателей не уверен из-за возможности арифметики над ними).
Функциональное программирование
Это очень сложная категория, которую постоянно путают с процедурным программированием. А еще это де-факто противоположный стиль: декларативный. Традиционное императивное программирование детально описывает процесс получения результата, а декларативное сам результат, без деталей реализации (хотя разделение обычно довольно нечеткое). При этом второй типичен для языков разметки типа HTML и CSS. То есть, условно, как одна и та же операция могла бы выглядеть в императивном и декларативном стиле:
document.tags.A.color = "blue" /* Императивный (JSSS). Сделать ссылки синими */
a { color: blue } /* Декларативный (CSS). Ссылки должны быть синими */
Почувствуйте разницу.
И функциональное программирование я никогда не изучал и слишком мало о нем знаю. Так что готовьтесь к ошибкам и не воспринимайте всё за чистую монету.
Внутри чистого функционального программирования
Основано полностью на математике, все функции обязаны быть чистыми. Операция присваивания запрещена (разрешены константы), переменных в привычном виде нет. Прикольно? Очень!
Во многих процедурных языках функции и процедуры являются объектами второго класса (не путать с классами из ООП), что не позволяет их свободно присваивать в переменные, передавать как аргументы в другие функции или возвращать из них (только через указатели). Функциональные языки расценивают функцию как объект первого класса, то есть их можно, а часто нужно передавать в другие функции напрямую.
Это дает некоторые преимущества, особенно в плане безопасности и при работе с многопоточностью (по причине неизменяемости данных и отсутствия глобального состояния), но вся концепция имеет один фатальный недостаток: вы мало чего полезного можете сделать, ибо что ввод, что вывод являются математически нечистыми, а потому запрещены. Вот такое вот гениальное изобретение безумных математиков.
Функциональное и процедурное программирование. Холст, масло
Каждый чисто функциональный язык выкручивается из этого по-своему, к примеру через монады. Это позволяет им существовать вне шуток и даже использоваться на практике.
Это не все особенности функциональных языков, но одни из самых важных. Самый известный такой язык: Haskell. Функциональные F#, Lisp, ML и многие другие не являются 100% чистыми.
Смешанное функциональное программирование
Последнее время часто используются смешанные языки, к примеру вместе с процедурным или объектно-ориентированным программированием, что избавляет от ограничений математики, но дает гибкость в том, что функциями можно оперировать как с любыми другими типами данных, а еще дает много очень удобного сахара вроде замыканий и лямбд. Это C#, Python, JS, частично Java и C++ (в них нужны костыли в виде интерфейсов из одного метода или оберток над указателями).
Особенности
Функции как объект первого класса. К примеру в C# это реализовано через систему делегатов, которые представляют из себя тип-обертку для функций:
Action<string> printer = Console.WriteLine; // Action<string> - тип-делегат. Неявно создаем его объект и присваиваем туда функцию printer("Hello, World!"); // Вызываем функцию через делегат
Локальные функции: как обычные, только вложенные в другую функцию (объявленные внутри нее)
void Func1() { // Глобальная функция void Func2() { // Локальная функция Console.WriteLine("В локальной функции"); } Func2(); }
Лямбды: возможность объявить безымянную функцию посреди кода (часто удобнее локальных)
var pow2AsLambda = x => x * x; // => - оператор лямбда-выражения pow2AsLambda(5); // Вернет 25
Замыкания (можно использовать вместе с лямбдами и локальными функциями):
int someValue = 42; var pow2AsLambda = x => x * x + someValue; // someValue будет захвачено замыканием, хотя напрямую не передано pow2AsLambda(5); // Вернет 67
Особенность замыканий в том, что они могут захватить локальную переменную родительской функции внутрь себя, продлевая ей время жизни за пределы блока с кодом. После чего такую лямбду можно передать в другую функцию, которая просто так не имеет доступа к someValue (в обычных условиях someValue вообще уже будет уничтожен), а вот переданная лямбда сможет ее прочитать или записать всегда и откуда угодно. И самое интересное то, что значение этой переменной будет сохранятся между вызовами к замыканию. То есть она становится глобальной, но видимой только из функции-замыкания.
ООП
Посмотрим на индекс TIOBE по популярности языков. Фиолетовым я пометил чистые функциональные языки. Языки, имеющие возможности, присущие функциональным языкам (смешанные) - синим, процедурным - красным, а объектно-ориентированным (ООП) - зеленым. Языки, в которых нельзя объявить функцию, принадлежащую самой себе или модулю, процедурными считать не совсем корректно (Java).
Не претендую на 100% точность
Видите фиолетовые точки? И я не вижу. А вот синих 12. В то же время красных и зеленых по 16. При этом реально применяемый чисто процедурный язык всего 1: С. Остальные имеют какую-либо встроенную поддержку других парадигм.
И сейчас практически всё большое ПО пишут в ООП. Ибо позволяет хоть как-то сдерживать структурированность кода после перехода с десятков тысяч строк к сотням (и миллионам).
Внутри
ООП является развитием идеи процедурного программирования. Проблема была в том, что помимо кода в программе существуют еще и данные, которые было бы неплохо связать с соответствующим им кодом. И через некоторое время после появления процедур появились структуры (они же записи в Pascal, не путать со структурным программированием).
Структуры были удобным способом объединить несколько переменных в единое целое. Пример:
typedef struct user_struct { char *username; int userid; int reputation; } user_t; user_t someuser = { "IvanKr08", 17002, 253 }; // Инициализируем значениями someuser.reputation += 10; // Обращаемся к полю
(Вместе с этим объявляем структуру новым типом через typedef, что не делается по умолчанию в C, в отличии от C++. Один из ярких примеров несовместимости C и C++):
После чего user_t превращается в новый тип, как int или char. Можно создать полноценную переменную типа user_t (или массив такого типа), а потом обратиться к какой-нибудь ее части (полю) через оператор точки (.). Можно сделать функцию, которая будет принимать или возвращать переменную типа user_t (к примеру someuser). Можно сделать указатель на user_t, тогда для обращение к полю используется оператор стрелки (->). Или можно встроить переменную типа одной структуры в другую, это тоже не запрещено. Внутри структурная переменная представляет из себя последовательно слепленные поля в одно целое.
Если поля разного размера, то часто добавляют пустоты между полей в целях выравнивания по размеру наибольшего поля и улучшения производительности, но это сложная тема
Возвращаемся к ООП
Суть ООП в том, что помимо полей структуры могут содержать процедуры и функции. Такая структура называется классом, переменная класса - объект, а процедура класса - метод.
Метод принципиально ничем не отличается от любой процедуры или функции, кроме того, что неявно принимает в себя специальный аргумент this (в Python это делается явно, в некоторых языках вместо this может быть self). Он содержит в себе ссылку/указатель на объект класса, от которого был вызван. Пример:
class User { public: char *username; int userid; int reputation;
void print() { printf("Пользователь \"%s\" (%i). Репутация: %i\n", this->username, this->userid, this->reputation); // Постоянно писать this-> не обязательно. Если локальной переменной с таким именем нет, то будет произведен доступ к полю } }; User someuser = { "IvanKr08", 17002, 253 }; // Инициализируем значениями someuser.print(); // Вызвали метод, print() неявно получил в себя указатель this, который указывает на someuser someuser.reputation += 10;// Обращаемся к полю someuser.print(); // Теперь вывод поменяется
Да, никто не мешает объявить обычную функцию, которая будет явно принимать в себя указатель на User и ничего не поменяется, и так повсеместно делают в C (тот же WinAPI на этом построен целиком и полностью), но ООП на самом деле крайне сложная, большая и холиварная тема, которая развивалась на протяжении 60 лет в разных направлениях и которую поднимать тут глупо. Только опишу еще несколько разновидностей методов:
Статичный метод - как обычный метод, только не получает в себя this и вызывается от имени класса, а не объекта (не someuser.method(), а User::method()). Зачем это нужно и в чем отличие от просто функции? Статичный метод можно спрятать за инкапсуляцией, плюс он привязан к классу, а не болтается в глобальном пространстве имен.
Конструктор - автоматически вызывается при создании нового объекта. Может иметь аргументы, тогда обязан явно вызываться как функция с именем класса, т.е. User("IvanKr08", 17002, 253)
Деструктор - есть в C++. В C# называется финализатором и имеет несколько важных отличий. Автоматически вызывается перед уничтожением объекта (к примеру выход из области видимости, явное удаление оператором delete или удаление сборщиком мусора в C#). Не может иметь аргументов.
Свойство - есть в Delphi и C#, куда перешел от первого. С точки зрения синтаксиса это поле, которое можно читать и записывать, только вместо прямого обращения в память вызываются соответствующие методы (set и get). Пример: ... int SomeProperty{ get =>42; set => Console.WriteLine("Set"); } ... test.SomeProperty = 10; // Значение никуда не сохранится, будет выведено "Set" в консоль Console.WriteLine(test.SomeProperty); // Всегда будет 42
Перегрузка оператора - специальный метод, который позволяет переопределить стандартные операции для типа. К примеру нельзя сложить два объекта User или User и число, но если перегрузить оператор +, то можно будет определить свою логику для этого (не обязательно, чтобы оно что-то реально складывало. Это может быть любое действие).
Индексатор - синоним перегрузки оператора квадратных скобок. Объект начинает вести себя как массив.
Функтор - перегрузка оператора круглых скобок (иначе называется перегрузкой оператора вызова функции). Позволяет "вызывать" объект так же, как и функцию. Звучит запутанно, но можно погуглить. Есть в C++. Также бывает функтор в функциональном программировании, но он не имеет ничего общего с функтором в C++.
Виртуальная функция (метод) - самый интересный и сложный тип, составляет основу полиморфизма. Вкратце объяснить его невозможно, но одним из ключевых принципов ООП является наследование, то есть один класс (наследник) копирует в себя все поля и методы другого класса (родитель), и может добавить новые. И суть в том, что указатель (ссылка) на объект класса-наследника может быть присвоен в переменную-указатель родительского типа. А самое интересное то, что любые обращения (к примеру вызовы методов), сделанные через родительский указатель, будут вести себя аналогично обращениям, сделанным напрямую через указатель с типом наследника. Это называется полиформизмом. Но это было бы не слишком полезным, если бы не возможность объявить метод в родительском классе виртуальным, а в наследнике полностью переопределить его код.
И то, что я забыл
Послесловие
Если вы осилили эти 3000 слов и даже смогли что-то понять, то найдите и распечатайте себе утешительную грамоту. А я устал и пойду искать смысл жизни...
UPD: исправлены косяки форматирования, очепятки, добавлено еще пару пунктов про разновидности методов и функциональное программирование.
Помню такой интересный случай. В детстве взял в библиотеке какую-то детскую книгу. Издание было немного странное, в том смысле, что несколько последних страниц оставили чистыми, без текста и картинок.
Ну и ребята начали туда писать свои отзывы. Кто о чем. Кто-то делился впечатлениями о книге. Кто-то предлагал дружить. Кто куда горазд. Было очень интересно. Я, помню, туда кота нарисовал. И шахматную задачку на диаграмме.
Я еще специально эту книгу опять взял через пару месяцев. Было интересно, что там кто ответит.
Город на самом юге Чехии, который будто сошёл со средневековой почтовой открытки, с населением в 12 тыс. человек.
Чески Крумлов с высоты второго этажа галереи, ведущей из местного замка
Городок расположен на реке Влтаве и впервые упоминается в 1240 году.
Как и любой уважающий себя чешский средневековый город, имеет прекрасную ратушу, костёл святого Вита и площадь с чумным столбом на ней.
Городской ров
Город до сих пор окружает ров. В самом городе сохранились дома как минимум с 15 века и за ними постоянно следят. Хочешь прикупить себе дом - пожалуйста, но надо будет отстёгивать крупную сумму на реставрационные нужды.
Крумловский замок
Крумловский замок - второй крупный замок по величине в Чехии (после Пражского Града). В него с одной стороны ведёт вымощенная дорога из булыжника из самого города, а с другой - трёхэтажная галерея. Замок был высечен в скале.
Ещё один вид с галереи
Город, прежде всего, является туристической достопримечательностью. Но также славится производством графита (карандаши KOH-I-NOOR как раз создают неподалёку), а также различными культурными событиями. Летом здесь проходят средневековые фестивали, на которые не так просто попасть. Но приедь в средневековом костюме - и проход будет бесплатным.
Также внутри города потрясающие средневековые таверны в старых домах, множество магазинов ювелирных изделий и настоек.
Одна из улочек
В городе можно не только любоваться зданиями, узкими уютными улочками или безумно вкусной едой, есть ещё и различные музеи. Так что провести в городе как минимум целый день - отличная идея.
14 июля 2015 года космический аппарат NASA "Новые горизонты" получил самые детальные на сегодняшний день снимки Никты — одного из пяти известных спутников Плутона.
Недавно исторические фотографии были объединены и обработаны с помощью современных алгоритмов машинного обучения, что позволило получить довольно детальное цветное изображение (ниже) загадочного объекта.
Никта, открытая 15 мая 2005 года космическим телескопом NASA/ESA "Хаббл" одновременно со спутником Гидра, представляет собой необычное небесное тело неправильной формы размером примерно 50 × 33 × 31 километров. Свое название спутник получил в честь древнегреческой богини ночи Нюкты (Никты).
Долгое время считалось, что Никта, как и другие малые спутники Плутона, образовалась из обломков, выброшенных при столкновении Плутона с крупным объектом пояса Койпера. Однако эта гипотеза не может объяснить удивительно высокую отражательную способность спутника. Современные исследования предполагают, что Никта сформировалась независимо от Плутона из первичного облака ледяных частиц — остатков материала, из которого формировалась Солнечная система. А уже после объект бы "похищен" Плутоном и превращен в его естественный спутник.
Поверхность Никты покрыта крупнозернистым водяным льдом, температура которого не поднимается выше -230°C. При таком экстремальном холоде лед приобретает прочность, сравнимую с земными горными породами.
Особый интерес ученых вызывает крупное темное пятно на поверхности спутника — след древнего столкновения с другим космическим телом. Красновато-коричневый материал в этой области мог принадлежать объекту-импактору или был выброшен из недр самой Никты.
В настоящее время NASA и Юго-западный исследовательский институт рассматривают возможность организации новой миссии к системе Плутона для детального изучения карликовой планеты и ее загадочных спутников. Это может помочь раскрыть тайны формирования и эволюции объектов как окраинах Солнечной системы, так и в ее внутренней области.
«День креветок» — это фестиваль, посвящённый одному из самых популярных морепродуктов в мире. Праздник отмечается ежегодно 10 мая. В этот день любители креветок могут собраться вместе, чтобы отдать дань уважения этим ракообразным, которые обычно называют ещё «морскими фруктами».
Креветки – самый популярный морской деликатес. Вообще - креветки очень интересные персонажи, а некоторые из них могут даже светиться в темноте. Это ракообразные, которые широко распространены по всему миру и встречаются как в соленых, так и в пресноводных водоемах, как в диком виде, так и на специальных фермах. Стоит заметить, что креветки, которые растут на воле питаются рачками и водорослями. Именно поэтому, они имеют более насыщенный аромат и прочные панцири. Тот факт, что они больше времени проводят в движении, повлиял и на их более плотное мясо.
Самой крупной креветкой в мире является черная тигровая. Некоторые представители этого вида достигают 36 сантиметров в длину и веса – целых 650 граммов. Интересно, но факт: самки весят больше, чем самцы.
Креветки безусловно низкокалорийный продукт. Они чрезвычайно богаты кальцием и протеином, а также легко перевариваются. Часто можно прочитать, что креветки содержат много холестерина, и это действительно так, но веществ, которые становятся причиной повышения уровня холестерина в крови, в них практически не содержится. В них много белка, который кстати участвует не только в процессах наращивания мышечной массы, но и в формировании волокон коллагена, а значит, в поддержании молодости кожи. Креветка содержит целый комплекс витаминов, таких как: провитамин А, который полезен для зрения; витамин А - источник молодости кожи; практически все витамины группы В, полезные для костей, ногтей и волос; витамин D и E, защищающие кровеносную систему; витамин С - гарант хорошего иммунитета. Кроме витаминного состава, польза креветок заключается еще и минеральном балансе. В креветках в необходимом организму количестве содержатся: кислоты Омега 3, магний, калий, железо, фосфор, фтор, медь, селен, цинк, хром и, конечно, йод. Добрая половина таблицы Менделеева дает нашему организму ценный запас жизненной энергии, а йод стимулирует работу щитовидной железы. 100 грамм креветок содержат суточную норму йода, что в сто раз больше, чем в говяжьем мясе.
Если вы пытаетесь сократить потребление мяса, но у вас по-прежнему всё в порядке с рыбой, креветки - отличный способ изменить свое меню. Они будут иметь прекрасный вкус и помогут укрепить здоровье сердца. Когда дело доходит до рецептов блюд из креветок, то тут существует бесконечное количество вариантов: жаренные на гриле креветки; паста с креветками в сливочно-чесночном соусе; вкуснейшее ризотто с креветками; варёные креветки (лучше подходят к пиву); спагетти и макароны с креветками; суп с креветками; различные варианты салатов; шашлычки из креветок и т.д. Нет сомнений, что креветки популярны по всему миру. Желаем вам сегодня - как можно больше приятных минут провести в компании этих милых и очень полезных для здоровья созданий.
На Марсе, в северных низменностях планеты, расположен удивительный природный феномен – кратер Королёва, настоящий ледяной оазис диаметром 82 километра. Он находится к югу от обширного поля дюн Olympia Undae, которое окружает часть северной полярной шапки планеты.
Кратер Королёва — это не просто впадина в марсианской поверхности, а уникальная природная морозильная камера, хранящая гигантские запасы водяного льда.
Естественный холодильник
Кратер Королева заполнен массивом льда толщиной 1,8 километра, который сохраняется круглый год. Это один из наиболее хорошо сохранившихся примеров марсианских кратеров, заполненных именно водяным льдом.
Механизм холодной ловушки
Кратер Королева представляет собой глубокую чашу, дно которой расположено почти на два километра ниже окружающей поверхности. Когда воздух проходит над ледяной поверхностью, он охлаждается и, становясь тяжелее, опускается вниз. Этот холодный воздух создает защитный слой непосредственно над льдом, действуя как изолятор.
Поскольку воздух – плохой проводник тепла, образуется своеобразный "щит", защищающий лед от нагревания и испарения. Благодаря этому естественному механизму кратер остается замороженным постоянно.
Исследования с орбиты
Первые снимки кратера были получены 4 апреля 2018 года камерой высокого разрешения HRSC космического аппарата ESA "Марс-экспресс". Для создания полной картины потребовалось объединить пять длинных полос изображений, снятых во время разных пролетов над кратером. Позже свой вклад в исследование внес и аппарат ESA Trace Gas Orbiter, который сфотографировал 40-километровый участок северного края кратера.
Кратер назван в честь Сергея Павловича Королёва, главного конструктора советской космической программы. Под его руководством были созданы первые искусственные спутники Земли в рамках программы "Спутник", осуществлены первые полеты человека в космос (программы "Восток" и "Восход", включая полет Юрия Гагарина в 1961 году), а также запущены первые межпланетные миссии к Луне, Марсу и Венере. Королев также работал над ракетами, которые стали предшественниками успешных носителей "Союз" – рабочих лошадок российской космической программы, используемых как для пилотируемых, так и для автоматических полетов.
1. Австралия. Я встречал множество европейских туристов, которые хотели проехать через глубинку, будучи крайне недостаточно подготовленными. Они не знали, что делать в чрезвычайной ситуации, и у них практически не было с собой воды. Это не шутка. Там все время погибают люди. Вам придется идти сотни километров при 40 градусах по Цельсию, прежде чем вы кого-то встретите, если что-то пойдет не так.
2. Новая Зеландия. У нас нет животных, насекомых, змей и т. д., которые могли бы вас убить. Но у нас есть самая большая дыра в нашем озоновом слое. Летом люди могут получить солнечные ожоги в течение 30 минут, находясь без защиты. Я обгораю в течение 15 лет. Если ты проведешь целый день на солнце без защиты, то гарантировано получишь солнечный ожог до волдырей. В прошлом году к нам приезжали туристы из Германии на месяц. Они пошли в поход, и один из них забыл солнцезащитный крем. Вечером на его лицо и руки было страшно смотреть.
3. Швеция. Это все здорово — элегантный дизайн и фрикадельки, пока не наткнешься на лесной дороге на лося. Действительно страшно ехать по шоссе, когда видишь, как несколько десятков оленей тусуются у обочины и смотрят на твою машину как-то напряженно. Но олени хороши тем, что они тусуются большими группами, и их легче увидеть издалека. А вот лось-монстр, который внезапно выскакивает на дорогу, — это настоящий кошмар!
4. Ирландия. Имеется серьезная и растущая проблема антисоциального поведения, которая не решается должным образом. Однажды я находился в центре Дублине средь бела дня, и этот обкуренный панк напал на меня, потому что ему показалось, что я неуважительно посмотрел на его девушку. Я слеп и ношу с собой трость, но он бы точно меня избил, если бы не появилась полиция. Чертово отсутствие здравого смысла.
5. Тринидад. Столица этого острова одно из самых опасных мест на земле. Семья жены оттуда. Мне не разрешают навещать их, потому что я белый. Они категорически настаивают, что не могут обеспечить мою безопасность. Даже моей жене и ее брату нужно везде иметь сопровождение, потому что они выросли не там, и местные жители это знают.
6. Ямайка. Я объездил все Карибские острова, и, хотя вы можете беспокоиться о том, что вас ограбят на других островах, именно на Ямайке стоит беспокоиться, что вас убьют. Наша самая любимая знаменитость находится в тюрьме пожизненно за убийство кого-то топором. Люди знают, что он виновен, и им все равно, и они все равно хотят, чтобы его освободили.
7. Непал. Восхождение на самые высокие горы мира привлекает сезонных туристов, но определенный процент всегда умирает, пытаясь туда подняться.
8. Дания. Многие немцы едут отдыхать на западное побережье полуострова Ютландия. Слишком многие из них не знают, что с Северным морем не шутят. Приливы и отливы довольно распространены и чертовски страшны. Течение и волны могут быть более жестокими, чем вы ожидаете, если вы не привыкли к морю. Вы можете спокойно купаться, но не будьте идиотом, и не отправляйтесь плавать на надувном матрасе, который ветром унесет в Англию, прежде чем вы поймете, что происходит.
Американцы обнаружили сокровища из музея Гогенцоллернов, среди них были предметы которые использовались при коронации короля Фридриха I и королевы Софии в 1701 году - два меча с золотыми и серебряными ножнами, драгоценный скипетр и две короны.