Мне очень понравилось, как элегантно стандарт описывает преобразования между базовыми и производными типами. Это кратко, но не теряет суть, чем грешат популярные статьи по теме. Давайте посмотрим на это поближе.
DISCLAIMER: мне пояснили, что подобное восприятие является довольно непопулярным. Не принимайте близко к сердцу, если стандарт вас разочарует.
В этой статье я буду пользоваться 20м стандартом. B - base, D - derived.
Начнём с каста вверх: 7.3.11 Pointer conversions, пункт 3. Это standard conversion.
The result of the conversion is a pointer to the base class subobject of the derived class object. И никаких картинок не надо - сразу ясно, как будет происходить этот самый slice (он же срез - устоявшееся название для сдвига указателя при касте вверх). Указатель просто сдвигается на базовый подобъект производного класса. А если вариантов несколько, то и указатель некуда двигать.
Каст вниз - самое неочевидное, на мой взгляд. 7.6.1.8 Static cast, пункт 2.
Но стандарт и это объясняет парой фраз. В самом деле, если мы пытаемся сделать целое из части, то результат определён лишь в случае, когда целое уже существует. Почему при этом не удаётся создать D из виртуального B? Потому что B не принадлежит ни одному целому. Даже low-level абстракции не понадобились.
Все эти простые вещи спустя лекции и гугл дошли до меня только через стандарт. Он ответил на много тупых вопросов.
Надеюсь, и вы прониклись лаконичностью оригинала C++. Так или иначе, этот случай мотивировал меня дать шанс стандарту как источнику информации. Вэлком в комменты :)
P.S. Изначально я хотела сделать пост, но там можно только 1 картинку. Поэтому стиль и формат получились соответствующие. Нравятся ли вам подобные вольные маленькие статьи?
Комментарии (19)
Goron_Dekar
10.10.2023 08:39+5Стандарт не рекомендуют новечкам потому, что это в значительной степени юридический документ. А не все люди умеют читать юридические документы. Вот я не умею. И приведённый пример отлично это иллюстрирует: вам понадобилось написать дополнение к приведённым абзацам, хотя поинт вашей же статьи в том, что ничего не надо, всё и так понятно.
Увы, я прекрасно понимаю, как работает кастинг производных типов в плюсах, поэтому не могу вам рассказать, что именно неясно в этих абзацах. Но каждый раз, когда я сталкиваюсь с вещами, которые я в плюсах понимаю плохо, то стандарт мне не помогает. Его формулировки точны и лаконичны, но не являются ответом на мои вопросы.
Попробую в пример из математики. У ученика вопрос: сколько будет 3+2. Его шлют к аксиомам Пеано (https://ru.wikipedia.org/wiki/Аксиомы_Пеано).
1) 1 является натуральным числом;
2) Число, следующее за натуральным, тоже является натуральным;
3) 1 не следует ни за каким натуральным числом;
4) Если натуральное число a a непосредственно следует как за числом b b, так и за числом c c, то b b и c c тождественны;
5) (Аксиома индукции.) Если какое-либо предположение доказано для 1 (база индукции) и если из допущения, что оно верно для натурального числа n n, вытекает, что оно верно для следующего за n n натурального числа (индукционное предположение), то это предположение верно для всех натуральных чисел.И определению сложения для натуральных чисел.
Да, из этих двух основ легко можно понять (и доказать!), что 3+2 = 5. И мы в 7 классе это делали. За 2 недели, именно столько у нас ушло для того, чтобы пройти и понять все эти концепции. Но для первоклассников, которые учат таблицу сложения такой метод не подходит, согласны?
Sequoza
10.10.2023 08:39-1Спасибо вам огромнейшее. Всегда думал, что один я такой ретард, который посмотрит в стандарт в самую последнюю очередь.
x6x4 Автор
10.10.2023 08:39Нет, это не так. Я писала как раз исходя из точки зрения, что все стандарт смотрят последним. И что возможно, он не так страшен, как кажется.
x6x4 Автор
10.10.2023 08:39Спасибо за подробный отклик!
По порядку:> вам понадобилось написать дополнение к приведённым абзацам, хотя поинт
вашей же статьи в том, что ничего не надо, всё и так понятно.Ну дополнения включают либо мои мысли, либо повторение предложений на скринах на русском. Объяснять я точно целью не ставила. Ставила целью показать, насколько хорош бывает стандарт и что стоит давать ему шанс, если у кого-то есть изначальное предубеждение.
> У ученика вопрос: сколько будет 3+2. Его шлют к аксиомам Пеано
Ваш пример рассматривает вопрос, по сути близкий к "что" - я же имела в виду вопросы "почему" и "зачем" ("для чего"). Естественно, на вопрос "сколько" ответ будет 5. А вот на вопрос "почему" или "как устроено сложение" уже куда лучше подойдёт указанная вами последовательность. (Для 7 класса, такое в учебном плане, конечно, круто - мне казалось, это вузовская программа.)
Вопрос, за сколько и что можно понять, дискуссионный - в общем-то, о нём я и высказывалась. Мне показалось, что в этом конкретном случае стандарт даёт возможность понять нужное довольно быстро и точно. У вас опыт общения со стандартом иной - хорошо. Для меня он такой :)
> Но для первоклассников, которые учат таблицу сложения такой метод не подходит, согласны?
Смотря как объяснить и что конкретно ребёнок хочет узнать. Здесь посыл был по поводу того, где искать ответы на вопросы. Стандарт - лишь одна из многих возможностей. Но по моему мнению, она имеет объективные преимущества как справочник.Goron_Dekar
10.10.2023 08:39Вопрос "почему" и "как устроено сложение" дети проходят... 3 раза!
Первый раз - в саду-школе, через яблоки и пальцы. И там рассказывают, что сложение устроено так, что ты прибавляешь по одному до того, как закончится второй аргумент.
Второй - в первом/втором классе. Там рассказывают про таблицу сложений и про сложение в столбик. Тогда сложение устроено как обращение к таблице заученных констант с разбиением сложных операций на серию простых. И это другое описание того, "как устроено сложение"
И, наконец, третий - 7/8 класс, алгебра, Пиано и прочее.
Так же и со стандартом. Он написан понятно только для тех, кто уже прошел ранние стадии, и понимает, о чём идёт речь. Причём понимает хорошо, и ему очевидны тонкости, но он хочет уточнить какие-то архиредкие нюансы. Для новичков стандарт непонятен. И ровно потому, что написан таким языком, чтобы описать сразу и базовое поведение, и сложное. Да, стандарт лаконичен. Да, он точен. Но нет, он непонятен. Как раз потому, что точен и лаконичен. Люди, которые его писали, специально шлифовали формулировки, выбрасывая из них всё лишнее.
И, да, вопрос звучал про использование стандарта новичками. Новичкам не нужен справочник, им нужен учебник.
x6x4 Автор
10.10.2023 08:39Ну я новичок, и мне было так понятнее. Я написала для таких же новичков, как я, чтобы они имели в виду такую возможность. Я понимаю вашу позицию, поскольку я была точно такого же мнения до момента, который сподвиг меня на статью. Но я не понимаю, что именно вы пытаетесь донести.
boldape
10.10.2023 08:39+1Что бы оценить вашу собственную веру в стандарт как хороший и понятный источник предлагаю вам выполнить следующее упражнение найдите соответствующие разделы про модель памяти, все эти хэпенс бефо атомики и вот это все.
Покурити эту часть пару дней, а затем на свежую голову решите контрольный пример на понимание - почему в шаред поинтере конструтор увеличивает счётчик с помощью релаксед операции, а деструктор уменьшает с помощью релиз операции.
Задача со зведочкой, когда можно безопасно уменьшать счётчик релаксед операцией?
Ну и что бы добить сразу курсовая, напишете свой шаред поинтер где используется только релаксед операции, но при этом его нельзя использовать не правильно.
Вот когда вы это сделаете и вспомните сколько раз вы заглядывали в стандарт пока делали и перечитывали одно и тоже по газилиону раз вот тогда ваша вера в понятность его величества стандарта пошатнется, но ничего лучше стандарта я все равно не находил. Так что стандарт он большой и разный, а вы судите о нем только по небольшому кусочку.
x6x4 Автор
10.10.2023 08:39Спасибо за совет, довольно интересно, посмотрю. Но хотелось бы отметить, что у меня нет никакой "веры" и ни о чём я, вроде как, не сужу категорически. Я отрицаю лишь отсутствие понятных и полезных моментов в стандарте - я не постулирую его понятность целиком.
Моя статья - контрпример к первому утверждению. Очевидно, постулируй я понятность всего стандарта, пришлось бы проделать куда более серьёзную работу. Мне же достаточно было показать, что есть как минимум что-то достойное внимания. Почему захотелось показать? Потому что меня это впечатлило, мне понравилось. В этом весь смысл.
boldape
10.10.2023 08:39Я отрицаю лишь отсутствие понятных и полезных моментов в стандарте
Ну это же совершенно очевидно. Представьте себе вселенную где стандарт с++ НЕ содержит ни единого понятного и/или полезного момента. Зачем такой стандарт кому то нужен, если по факту, в такой вселенной, им нельзя пользоваться?
постулируй я понятность всего стандарта, пришлось бы проделать куда более серьёзную работу
Никакая работа не сможет доказать кому либо понятность стандарта, т.к. понятность категория субъективная.
С вами спорят, потому что вы настаиваете на том, что если ВЫ нашли что то полезное и понятное в стандарте, то и остальным стоит тоже его читать. Но читать стандарт кому либо стоит лишь только в том случае если этому человеку понятно то что он прочтет, а не потому что кому то другому это понятно. Очевидно, не попробовав не узнаешь навярнека, но многие находят разумным положиться на мнение коллективного разума и даже не пробовать.
Коллективный разум на основе опыта утверждает, что вы ненормальная/крайне редкая, в смысле распределение вероятности, вы случайный всплеск на хвостах распределения, т.к. нормальным студентам стандарт не понятен от слова совсем. И не только студентам, но и многим опытным разработчикам тоже.
x6x4 Автор
10.10.2023 08:39Теперь поняла, спасибо за пояснения.
Насчёт вселенной: ну смотря для кого, понятие понятности/полезности субъективно. Вполне вероятно, что и в нашей вселенной есть те, кому ничего не понятно и не полезно. И не обязательно всем пользоваться стандартом, кому-то это просто может быть не надо.
Насчёт работы: ну не обязательно всем доказывать, можно было просто какое-то более обширное и аргументированное исследование провести. Опять же, кому понравится, тому понравится. Всем в любом случае не доказать, вне зависимости от объективности/субъективности.
Насчёт спора: я вроде не настаиваю, а предлагаю, на основе своего опыта. Если многие не хотят пробовать, по идее можно вообще не предлагать ничего. Но это же не так - люди довольно успешно делятся друг с другом опытом. И я в общем-то не понимаю, чем моя статья отличается от обычного предложения.
Могу ли я как-то её улучшить, или сама идея говорить о стандарте не имеет смысла?
boldape
10.10.2023 08:39+1Я вот буквально сегодня читал один короткий фрагмент стандарта раз 10 наверное, что бы окончательно осознать, что то как мне надо и то как оно работает на мракософтовском компиляторе на шланге и гцц работает по другому и это согласно стандарту нормально, потому что имплементэйшен дефаинд.
Говорить о стандарте действительно смысла мало, он нужен по факту только компиляторо строителям. Ничего улучшать не надо, уже все сделано - cppreference.com это с++ Вики на основе стандарта и с немного более понятным языком и примерами. А ещё много неважных(в контексте) слов стандарта выброшено, и это читается на порядок легче чем стандарт. Я на самом деле пользуюсь именно этим ресурсом 99,99% времени. Вот только сегодня я заглянул в настоящий драфт, а до этого лет 10 назад туда смотрел потому что цппреф в целом понятней, в том числе и за счёт вёрстки, и потому что показывает историю изменений от версии к версии и структура лучше.
Но это же не так - люди довольно успешно делятся друг с другом опытом. И
я в общем-то не понимаю, чем моя статья отличается от обычного
предложения.Отличие вашего опыта от обычного предложения в целевой аудитории. Хороший совет это такой совет который будучи дан любому рандомному человеку (имеется ввиду без уникальных способностей /середнячок) ему поможет, а ваш опыт/совет поможет только избранным, поэтому он не хороший, а особенный.
Обычный плюсовик послушает вас и пойдет читать стандарт, поймет что он не может понять что там написано, растроиться по этому поводу, его самооценка немного на время упадет и вообще он безрезультатно потрати свое время. Какой же это хороший совет/опыт с его точки зрения? Ещё раз хороший совет/опыт это такой который ЛЁГОК для применения большинству целевой аудитории и при этом реально помогает что то понять/улучшить.
x6x4 Автор
10.10.2023 08:39Хорошо, большое спасибо, теперь поняла. Впредь постараюсь думать о возможных последствиях для ЦА.
kekoz
10.10.2023 08:39В жизни вообще (и в программировании в частности) довольно часто встречается печальное несоответствие между «Как должно быть» и «Как есть на самом деле». Стандарт — это первое. А второе — конкретный компилятор.
x6x4 Автор
10.10.2023 08:39Ну компилятор не может противоречить стандарту. Он может реализовывать как угодно, но в его рамках.
Или у вас есть кейсы, где не так?
boldape
10.10.2023 08:39Есть, это называется багами в компиляторе или не полным соответствием. От того факта, что вы обнаружите несоответствие реального поведения стандарту ваша жизнь не улучшится, т.к. с вероятностью 146% вы не сможете заменить компилятор и вам придется искать воркароунд для вашей проблемы. И таких случаев больше чем вам кажется, особенно часто такое случается с недавно стандартизированным поведением/семантикой.
Goron_Dekar
10.10.2023 08:39Хуже того: завтра компилятор уже поменяют за вас, и там бага не будет. Но ваш код уже написан с учётом этого бага.
skovoroad
"Указатель просто сдвигается на базовый подобъект производного класса... "
... , а отношения с правильной таблицей виртуальных функций образуются сами по волшебству.
x6x4 Автор
Это уже другой уровень абстракции и вроде бы не имеет отношения к посылу статьи. Или что вы имели в виду?
reficul0
AFAIK:
1. Пока нет виртуальных методов - это просто попытка реинтерпретировать указатель (a.k.a. сдвиг).
2. При появлении виртуальных методов - это всё ещё просто сдвиг. Но теперь мы можем провалидировать даункаст через таблицу виртуальных функций, используя
dynamic_cast
.3. Как только появляется виртуальное наследование,
dynamic_cast
ещё и производит резолвинг смещения до интересующего нас адреса памяти по созданной специально для этого таблице смещений (не путать с vtable).Но реализация механизмов динамического диспатчинга и виртуального наследования - implementation defined. Стандарт не обязавает разработчиков компиляторов использовать именно vtable и таблицу смещений при виртуальном наследовании.