?

Log in

No account? Create an account

Девушка сверху
ilyachalov
Это было что-то похожее на туристический тур или выезд на натуру кружка молодых любителей изящных искусств.

Два десятка парней и девушек набились в странное транспортное средство, похожее на колхозный ЗИЛ-130. Только кузов у этого грузовика был раза в два длиннее обычного и сам грузовик при движении не рождал и малейшей тряски.

Вдоль одного из бортов тесно сбилось множество маленьких столиков с ноутбуками и мольбертами. Они все были разнообразных размеров и цветов, многие гибкие (даже дисплеи ноутбуков) и электронные (даже мольберты). Пассажиры расположились у ноутбуков и мольбертов, и в кузове яблоку было негде упасть.

Грузовик проезжал небольшой старинный городок, останавливаясь возле достопримечательностей. Пальцы строчили по клавишам, за грузовиком неслись шум разговоров, смех и разноцветные брызги красок.

Я сидел за ноутбуком в дальнем от кабины конце кузова, в углу. Мне тут нравилось, потому что, повернувшись в одну сторону, можно было общаться, а с другой стороны, когда выехали за город, были тишина, поля и безлюдная дорога до горизонта.

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

На поворотах ее прижимало ко мне и на очередной прямой я заметил, что в этом виновата не только инерция — она продолжала прижиматься.

Я повернулся к ней и мы поцеловались. Поцелуй получился смазанным из-за очередного поворота.

— Кто-то... — начала она, но я перебил, — Да, я не умею целоваться, но буду стараться...



Она оседлала мой торс, откинула мою голову на борт кузова и поцеловала. У нее был полный контроль над поцелуем. Мой язык проник между ее губ, а по телу волнами разливалось удовольствие.

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

Мы сейчас были похожи на сообщающиеся сосуды из физики. Только «сообщались» мы не в одном месте, а во всех местах соприкосновения. И вместо жидкости мы обменивались удовольствием. Этот обмен происходил в определенном ритме, ритме поцелуя. Я старался ласкать ее тело под этот же ритм. Вскоре это был уже один единственный сосуд, а не два отдельных.

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

В этот момент я проснулся.

Это второй пост по мотивам одного из моих эротических снов. Первый можно прочесть тут.


Иду. Курю. Милая Чарити
ilyachalov
Смотрел намедни танцевальную сцену «The Aloof» из старого американского фильма-мюзикла «Sweet Charity» 1969 года:



https://www.youtube.com/watch?v=e1Db3t3f5-Q

Ловлю себя на мысли, что всё это кажется очень знакомым. И тут вспомнил кайфовый видеоклип 1992 года на песню «Иду. Курю» из альбома группы «Ноль»:

https://www.youtube.com/watch?v=BEBmPj3Vojw
(песня начинается после первой минуты, сначала они там выпендриваются)

Ведь и то, как видеоклип снят, напоминает танцы из мюзикла, и даже некоторые музыкальные ходы скопированы. И там, и там актеры дымят, как паровоз. Причем видеоклип (режиссер — Алексей Розенберг, продюсер — Бахыт Килибаев) и песню делали разные люди.

Сокрытие имён при наследовании
ilyachalov
Еще одни грабли, описание которых стоило бы включить в главу 9 «Наследование» учебника Лафоре. Ученик с размаху наступает на них в упражнении 7 к этой главе, не понимая, в чём дело.

Задание к упражнению 7 главы 9. Даны два класса, которые нельзя изменять. Вот сокращенный код этих классов (это нерабочий вариант, в целях упрощения оставлены только методы с пустым телом; то же касается и других фрагментов кода в этом посте):
// базовый класс, реализующий счетчик, с одним методом
class Counter
{
public:
    Counter operator++ () // метод увеличения счетчика на 1 (префиксный инкремент)
    { }
};

// производный класс, добавляющий к счетчику еще один метод
class CountDn : public Counter
{
public:
    CountDn operator-- () // метод уменьшения счетчика на 1 (префиксный декремент)
    { }
};
Требуется добавить к счетчику методы постфиксного инкремента и постфиксного декремента.

Решение. Так как заданные классы нельзя изменять, создадим новый класс с помощью наследования и добавим в него требуемые методы:
class Counter2 : public CountDn
{
public:
    Counter2 operator++ (int) // постфиксный инкремент
    { }
    Counter2 operator-- (int) // постфиксный декремент
    { }
};
Напишем программу для проверки работы нового класса:
int main()
{
    Counter2 c1;
    
    ++c1; // ошибка
    --c1; // ошибка
    c1++; // работает
    c1--; // работает
    
    return 0;
}
Компилятор «не видит» методы из двух родительских классов. Почему же не работает наследование?

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

В главе 9 учебника сказано, что при наличии в базовом и производном классах методов с одинаковыми именами при вызове такого метода от объекта производного класса компилятор сначала ищет метод в производном классе и, если не находит, тогда ищет метод в базовом классе. Получается, что метод производного класса «закрывает видимость» на метод с таким же именем в базовом классе.

А вот про то, что то же самое работает даже при разном количестве параметров (или разном типе параметров) у методов с одинаковым именем из базового и производного классов, в учебнике не сказано и дойти до этого самому, без подсказки, очень непросто.

В данном упражнении два новых метода для постфиксного инкремента и постфиксного декремента «закрывают видимость» на методы родительских классов из-за того, что их имена совпадают.

Чтобы в данном случае методы родительских классов «стали видны» в нашем новом классе, можно объявить их имена с помощью ключевого слова using:
https://docs.microsoft.com/ru-ru/cpp/cpp/using-declaration

Например:
class Counter2 : public CountDn
{
public:
    using CountDn::operator++;
    using CountDn::operator--;
    Counter2 operator++ (int) // постфиксный инкремент
    { }
    Counter2 operator-- (int) // постфиксный декремент
    { }
};

Обсуждение на Киберфоруме (август 2014 г.):
http://www.cyberforum.ru/cpp-beginners/thread1240110.html

Конструктор базового класса в теле производного
ilyachalov
Одна из редких ошибок в оригинале учебника Лафоре. Выношу фрагмент программы со стр.946 (цитата неточная, но смысл ошибки передает):

Посмотреть кодCollapse )
Вот здесь свежее (март 2019 г.) обсуждение:
http://www.cyberforum.ru/cpp-beginners/thread2425673.html

Обсуждение — атомное: от мнения, что книжка Лафоре — «неиссякаемый источник кульков для семечек», до полного экстаза в виде пожелания «ставиться ею по вене».

Сначала о том, что это вообще за программа. Данная программа не имеет большого практического смысла, ее назначение чисто учебное. По условиям упражнения (упражнение 2 к главе 9, стр.424 оригинала) имеется базовый класс и его нельзя изменять. Ученик должен написать производный класс, в котором (конкретно в конструкторе с одним параметром) требуется выполнить дополнительные проверки для заданного параметра. В приложении G учебника на стр.946 как раз и дается возможная программа-решение этого упражнения с указанной ошибкой.

Смысл решения. Конструктору производного класса задается в качестве параметра строка в виде массива символов. Если эта строка по длине не укладывается в размер SZ, то в поле str базового класса копируется только часть заданной строки размером SZ - 1 (последнее место в массиве символов оставлено для нулевого символа '0', означающего конец строки). Если же заданная строка укладывается в размер SZ, то (ошибка) вызывается конструктор базового класса, в который и передается заданная строка.

В чем ошибка. Как я понимаю, из тела конструктора производного класса нельзя вызвать конструктор базового класса. Это нарушило бы принцип, по которому конструктор базового класса должен завершить свою работу перед началом работы конструктора производного класса.

Конструктор базового класса может быть вызван в конструкторе производного класса только в списке инициализации членов класса.
Pstring::Pstring(const char s[]) : String(s) // так можно
{
    String(s);         // не является вызовом конструктора базового класса

    String::String(s); // не является вызовом конструктора базового класса
                       // для текущего объекта
}
Оператор String(s); в теле этого конструктора — то же самое, что и String s;, то есть объявление нового объекта класса String. К объекту, для которого вызван конструктор производного класса, этот новый объявленный объект не имеет никакого отношения, а значит, хоть программа отработает без технических ошибок, но она всё же отработает не так, как планировалось.

Что делать. Для процитированного в начале поста фрагмента кода проще всего заменить String(s); на strcpy(str, s);.

А вообще можно создать отдельный метод, в котором и выполнить необходимые проверки, а затем при обращении в списке инициализации членов класса к конструктору базового класса вызвать этот метод для параметра. Например:
Pstring::Pstring(const char s[]) : String(test(s))
{ }

const char* Pstring::test(const char s[])
{
    // здесь выполнить проверки
}

Вот тут еще близко к этой теме пишут:
https://ravesli.com/urok-119-delegiruyushhie-konstruktory/

Два слона против коня
ilyachalov
Интересный анализ очень редкого пятифигурного эндшпиля «Два слона против коня»:

https://www.youtube.com/watch?v=HgHJwp5hBG0

На канале Алексея Пугача, тренера и КМС по шахматам из Днепропетровска (Украина, с 2016 г. город переименован в Днепр). Канал зарегистрирован в 2012 году, у него 82,5 тыс. подписчиков.

Автор провел большую аналитическую работу, что вызывает уважение. По его расчетам такое окончание бывает один раз на 63 тысячи партий. И такая редкость произошла 13.09.2019 г. в партии российского гроссмейстера Даниила Юффы (1997 г.р.) и его английского коллеги Люка МакШейна (1984 г.р.) на Кубке Мира 2019 в городе Ханты-Мансийске (Россия). Кубок начался 9 сентября и должен закончиться 4 октября.


«Крепость Клинга-Хорвица» за черных в углу a8

Исторически окончание считалось ничейным с тех пор, как его анализ выполнили Джозеф Клинг (1811-1876) и Бернхард Хорвиц (1807-1885).

Задача слабой стороны (король и конь) заключается в том, чтобы построить так называемую «крепость Клинга-Хорвица» в одном из четырех углов шахматной доски и после этого стоять до тех пор, пока у соперника не закончится терпение или пока не войдет в действие правило 50 ходов.

Возможность для сильной стороны (король и два слона) выиграть, оказывается, существует и Алексей Пугач рассматривает, как это сделать, в своем видеоролике. Для «белкового» шахматиста это очень сложно, если противник не допустит ошибок.

Люк МакШейн, похоже, был знаком с принципами защиты слабой стороны в этом эндшпиле, за этим очень интересно наблюдать в анализе Алексея Пугача. Даниил Юффа так и не смог взломать крепость противника и соперники согласились на ничью.

Ада Якушева и Варвара Визбор
ilyachalov
До чего ж похожи голоса и лица... (Я в курсе, что Варвара — внучка Ады.)



Ада Якушева (1934-2012), автор песни и исполняет она же:
«Вечер бродит по лесным дорожкам»
https://www.youtube.com/watch?v=MPtoPRp0dvc



Варвара Визбор (1986 г.р.)
«Ты — моё дыхание»
(автор песни — Ада Якушева, поет — Варвара Визбор, играет на гитаре Юрий Визбор (внук))
https://www.youtube.com/watch?v=gY9C3mAJpfo

Оператор извлечения из потока и std::getline
ilyachalov
В языке программирования C++ в консольной программе с помощью оператора извлечения >> из потока std::wcin получаем данные от пользователя:

https://ru.wikipedia.org/wiki/Iostream

С помощью этого оператора можно извлечь символьную строку в переменную подходящего типа. Если в строке, полученной от пользователя, есть пробелы, то в переменную попадет только часть строки до первого пробела. Поэтому для извлечения из потока строки с пробелами (до символа новой строки L'\n') учебники рекомендуют использовать функцию std::getline. Это азы.

https://en.cppreference.com/w/cpp/string/basic_string/getline
https://ru.cppreference.com/w/cpp/string/basic_string/getline (по-русски)

А вот дальше начинается интересное.

Сравнивая описания этой функции по этим ссылкам, замечаем, что в русской версии почему-то отсутствует очень интересный и важный раздел «Notes». В нем отмечается, что, применяя ввод, использующий в качестве разделителей пробельные символы (пробелы, символы табуляции, символ новой строки и т. п.) (пример такого ввода: int n; std::wcin >> n;), нужно помнить, что пробельный символ-разделитель, до которого извлекаются данные, останется после операции извлечения в потоке ввода. Если после этой операции извлечения мы переключимся на применение функции std::getline для извлечения из потока строк, то первая извлеченная строка будет тем самым оставшимся от предыдущего извлечения пробельным символом. В большинстве случаев такое поведение программы является нежелательным.

Например, следующий фрагмент кода технически отработает без ошибок:
int n; wcin >> n;
wstring line; getline(wcin, line);
Однако, программа с таким кодом не даст возможности пользователю ввести строку для переменной line, так как функция std::getline извлечет из потока std::wcin символ новой строки L'\n', оставшийся там после операции извлечения числа n, сочтет этот символ новой строки данными от пользователя и завершит работу, ничего не поместив в переменную line.

Для исправления этой ситуации в вышеупомянутом разделе «Notes» рекомендуют три способа. 1) Сначала дополнительно вызвать функцию std::getline для извлечения оставшегося от предыдущей операции символа новой строки, а потом уже вызывать эту функцию для получения от пользователя, собственно, запрашиваемой строки:
int n; wcin >> n;
wstring line; getline(wcin, line); getline(wcin, line);

2) Удаление ведущих пробельных символов из потока ввода с помощью функции (манипулятора потока) std::ws (https://en.cppreference.com/w/cpp/io/manip/ws):
int n; wcin >> n;
wstring line; getline(ws(wcin), line);
Тут нужно иметь в виду, что если пользователь введет в начале запрашиваемой строки пробелы, то они тоже будут удалены. Не всегда это удобно.

3) Удаление всех ненужных символов из потока ввода с помощью метода ignore потока ввода (https://en.cppreference.com/w/cpp/io/basic_istream/ignore):
int n; wcin >> n;
wcin.ignore(numeric_limits<streamsize>::max(), L'\n');
wstring line; getline(wcin, line);

* * *

Рассмотрим ситуацию посложнее. Предположим, есть класс, у которого имеются строковое поле line, числовое поле n и метод для получения данных от пользователя getdata, который сначала запрашивает у пользователя строку с помощью функции std::getline, а затем запрашивает число с помощью операции извлечения из потока ввода.

Если программист, использующий этот класс, напишет консольную программу и создаст в ней один объект этого класса, запросив у пользователя данные через метод getdata объекта, то проблем не будет.

Если же программист создаст в программе несколько объектов этого класса и станет вызывать методы этих объектов один за другим, то для первого объекта всё пройдет правильно, а для следующих объектов получится накладка, так как возникнет именно нежелательная ситуация, которая рассматривалась выше: функция std::getline из второго объекта будет вызвана после операции извлечения числового значения из потока ввода для первого объекта.

Автор описываемого класса, по идее, должен написать код метода getdata так, чтобы этих накладок не возникло. То есть метод getdata должен срабатывать и для случая, когда перед вызовом функции std::getline было извлечение из потока ввода числа с помощью оператора извлечения >>, и в случае, когда такого извлечения не было.

Из описанных трех способов решения проблемы в данном случае сработает только второй, с помощью функции std::ws. Пример кода метода getdata:
getline(ws(wcin), line);
wcin >> n;

Но есть еще такой вариант:
if (wcin.peek() == L'\n') wcin.ignore();
getline(wcin, line);
wcin >> n;
То есть с помощью метода peek (https://en.cppreference.com/w/cpp/io/basic_istream/peek) потока ввода мы определяем, есть ли в потоке ввода ненужный символ новой строки. И если есть, то удаляем его. В этом варианте ведущие пробелы во введенной пользователем строке сохраняются (в некоторых случаях это важно).

Батя с Ютуба
ilyachalov
Подписался на канал Виталия Орехова (1,21 млн подписчиков):

https://www.youtube.com/user/VitaliyOrekhov

Это юмористический канал, зарегистрированный 26.10.2014 года. Виталию под тридцать, снимает юмористические скетчи в стиле «Осторожно, модерн!» и «Маски-шоу».

Виталий играет в скетчах множество ролей, в том числе и женских. Привлекает 5-6 постоянных актеров. Особо подписчикам он полюбился в роли Бати. Виталий серьезно занимался и занимается фитнесом.

Вот несколько роликов из моих любимых (осторожно, много мата!):

Как Батя на работу устраивался (самая жесть начинается после первой минуты)
https://www.youtube.com/watch?v=y2CMt6l9Ui0

Батя и Смуглянка
https://www.youtube.com/watch?v=SwskVpn_k1s

Случай в подъезде
https://www.youtube.com/watch?v=eaWG-GgwnqY

Батя и «Тула»
https://www.youtube.com/watch?v=2QH4xQMBgAw

Батя и «Урал» (в байк-центре)
https://www.youtube.com/watch?v=j4vKdc_zVoE

Батя. Интервью на молодежном конгрессе
https://www.youtube.com/watch?v=-fvfOFDrF3o

Про здоровый образ жизни:

Заруба доктора Орехова. Диагноз — Турникмен.
https://www.youtube.com/watch?v=79r_nZg9X_k

Хищница против Травоядной
https://www.youtube.com/watch?v=slEdjv3FG54

Батя против Алексея Столярова (у него на канале)
https://www.youtube.com/watch?v=aMPd9tAQ9ls

Маски в качалке
https://www.youtube.com/watch?v=XTw9P2i469I

Музыкальный дуэт Just Play
ilyachalov
Явился к шапочному разбору.

Наткнулся в Youtube на музыкальный дуэт двух девушек под названием «Just Play» (не поют, только играют). Одна играет на скрипке, другая — на фортепиано. Посмотрел ролики и сразу подписался, но оказалось, что группа недавно развалилась. Просуществовала, вроде бы, с января 2017 года (эта дата указана у них в «ВКонтакте») чуть больше двух лет.

Участницы:
Александра Кузнецова (фортепиано)
Евгения Скачкова (скрипка)

Очень красивые каверы на произведения, входящие в список моих любимых:

Кавер на песню «Лирика» группы «Сектор газа»
https://www.youtube.com/watch?v=8w8abiWWG4o

Кавер на песню «Камнем по голове» группы «Король и шут»:
https://www.youtube.com/watch?v=-dXMgwzljIM

Кавер на саундтрек из фильма «Бумер» (автор музыки — Сергей Шнуров):
https://www.youtube.com/watch?v=Oc_p_DFVJaU

Канал на Youtube:
https://www.youtube.com/channel/UC5M__I2WLT0FOFtRM7OhHxw

Страница во «ВКонтакте»: https://vk.com/justplaymuz

Общее и частное наследование
ilyachalov
Продолжаю изучать учебник Лафоре. Смутил перевод заголовка одного из подразделов главы 9 «Наследование».

Оригинал (стр. 396):

Public and Private Inheritance


Перевод (стр. 383):

Общее и частное наследование


По-моему, крайне сомнительное решение. Это важно, потому что далее в книге эти термины используются довольно часто.

Объясню, почему такой перевод плох. На этой странице вводятся два новых понятия — «общее наследование» и «частное наследование», при этом не объясняется, что это такое. Почему же автор в оригинале не счел нужным это разъяснять? Дело в том, что слова «private» и «public» — это зарезервированные (или ключевые) слова языка C++, их значение уже было разъяснено в книге ранее. Поэтому читателю оригинала на английском всё остается понятным, а читатель перевода на русский начинает усиленно чесать репу и соображать, что же всё это значит (слава богу, есть программные примеры, которые переводчику сложно испоганить).

Что же делать переводчику? Вообще обычно зарезервированные слова не переводят. Можно было перевести, например, так:

Виды наследования: public и private


Но даже если принято решение перевести эти зарезервированные слова, выбранный перевод подходит плохо, сбивает читателя с толку. У меня первая мысль при слове «общий» — значит, относится к нескольким объектам (викисловарь сообщает о том же). А дело совершенно не в этом.

Как я понимаю, в США (Лафоре ведь — американский автор) если над входом в парк висит табличка «public», то подразумевается, что парк общественный и любому члену общества в него открыт доступ. А если висит табличка «private», то имеется в виду, что это частная собственность и вход запрещен всем, кроме владельцев парка. Исходя из этого, лучше было бы выбрать для перевода слова «открытый» и «закрытый», а не «общий» и «частный». Например:

Наследование открытого и закрытого видов

или

Наследование с открытым и закрытым доступом к базовому классу


В интернете пользователи учебника Лафоре продолжают распространять термины «общее наследование» и «частное наследование». Например:
https://prog-cpp.ru/cpp-child/

Авторы же статьи в википедии, посвященной наследованию в программировании, поступили умнее и не стали переводить зарезервированные слова: ссылка.