Почитаешь со мной новый draft, %username%?
Почитаешь со мной новый draft, %username%?

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

DISCLAIMER: мне пояснили, что подобное восприятие является довольно непопулярным. Не принимайте близко к сердцу, если стандарт вас разочарует.

В этой статье я буду пользоваться 20м стандартом. B - base, D - derived.

Начнём с каста вверх: 7.3.11 Pointer conversions, пункт 3. Это standard conversion.

D -> B
D -> B

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.

B -> D
B -> D

Но стандарт и это объясняет парой фраз. В самом деле, если мы пытаемся сделать целое из части, то результат определён лишь в случае, когда целое уже существует. Почему при этом не удаётся создать D из виртуального B? Потому что B не принадлежит ни одному целому. Даже low-level абстракции не понадобились.

Все эти простые вещи спустя лекции и гугл дошли до меня только через стандарт. Он ответил на много тупых вопросов.

Надеюсь, и вы прониклись лаконичностью оригинала C++. Так или иначе, этот случай мотивировал меня дать шанс стандарту как источнику информации. Вэлком в комменты :)

P.S. Изначально я хотела сделать пост, но там можно только 1 картинку. Поэтому стиль и формат получились соответствующие. Нравятся ли вам подобные вольные маленькие статьи?

Комментарии (19)


  1. skovoroad
    10.10.2023 08:39
    +2

    "Указатель просто сдвигается на базовый подобъект производного класса... "

    ... , а отношения с правильной таблицей виртуальных функций образуются сами по волшебству.


    1. x6x4 Автор
      10.10.2023 08:39

      Это уже другой уровень абстракции и вроде бы не имеет отношения к посылу статьи. Или что вы имели в виду?


    1. reficul0
      10.10.2023 08:39
      +1

      AFAIK:
      1. Пока нет виртуальных методов - это просто попытка реинтерпретировать указатель (a.k.a. сдвиг).
      2. При появлении виртуальных методов - это всё ещё просто сдвиг. Но теперь мы можем провалидировать даункаст через таблицу виртуальных функций, используя dynamic_cast.
      3. Как только появляется виртуальное наследование, dynamic_cast ещё и производит резолвинг смещения до интересующего нас адреса памяти по созданной специально для этого таблице смещений (не путать с vtable).

      Но реализация механизмов динамического диспатчинга и виртуального наследования - implementation defined. Стандарт не обязавает разработчиков компиляторов использовать именно vtable и таблицу смещений при виртуальном наследовании.


  1. 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 недели, именно столько у нас ушло для того, чтобы пройти и понять все эти концепции. Но для первоклассников, которые учат таблицу сложения такой метод не подходит, согласны?


    1. Sequoza
      10.10.2023 08:39
      -1

      Спасибо вам огромнейшее. Всегда думал, что один я такой ретард, который посмотрит в стандарт в самую последнюю очередь.


      1. x6x4 Автор
        10.10.2023 08:39

        Нет, это не так. Я писала как раз исходя из точки зрения, что все стандарт смотрят последним. И что возможно, он не так страшен, как кажется.


    1. x6x4 Автор
      10.10.2023 08:39

      Спасибо за подробный отклик!
      По порядку:

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

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

      > У ученика вопрос: сколько будет 3+2. Его шлют к аксиомам Пеано

      Ваш пример рассматривает вопрос, по сути близкий к "что" - я же имела в виду вопросы "почему" и "зачем" ("для чего"). Естественно, на вопрос "сколько" ответ будет 5. А вот на вопрос "почему" или "как устроено сложение" уже куда лучше подойдёт указанная вами последовательность. (Для 7 класса, такое в учебном плане, конечно, круто - мне казалось, это вузовская программа.)

      Вопрос, за сколько и что можно понять, дискуссионный - в общем-то, о нём я и высказывалась. Мне показалось, что в этом конкретном случае стандарт даёт возможность понять нужное довольно быстро и точно. У вас опыт общения со стандартом иной - хорошо. Для меня он такой :)

      > Но для первоклассников, которые учат таблицу сложения такой метод не подходит, согласны?
      Смотря как объяснить и что конкретно ребёнок хочет узнать. Здесь посыл был по поводу того, где искать ответы на вопросы. Стандарт - лишь одна из многих возможностей. Но по моему мнению, она имеет объективные преимущества как справочник.


      1. Goron_Dekar
        10.10.2023 08:39

        Вопрос "почему" и "как устроено сложение" дети проходят... 3 раза!

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

        Второй - в первом/втором классе. Там рассказывают про таблицу сложений и про сложение в столбик. Тогда сложение устроено как обращение к таблице заученных констант с разбиением сложных операций на серию простых. И это другое описание того, "как устроено сложение"

        И, наконец, третий - 7/8 класс, алгебра, Пиано и прочее.

        Так же и со стандартом. Он написан понятно только для тех, кто уже прошел ранние стадии, и понимает, о чём идёт речь. Причём понимает хорошо, и ему очевидны тонкости, но он хочет уточнить какие-то архиредкие нюансы. Для новичков стандарт непонятен. И ровно потому, что написан таким языком, чтобы описать сразу и базовое поведение, и сложное. Да, стандарт лаконичен. Да, он точен. Но нет, он непонятен. Как раз потому, что точен и лаконичен. Люди, которые его писали, специально шлифовали формулировки, выбрасывая из них всё лишнее.

        И, да, вопрос звучал про использование стандарта новичками. Новичкам не нужен справочник, им нужен учебник.


        1. x6x4 Автор
          10.10.2023 08:39

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


          1. boldape
            10.10.2023 08:39
            +1

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

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

            Задача со зведочкой, когда можно безопасно уменьшать счётчик релаксед операцией?

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

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


            1. x6x4 Автор
              10.10.2023 08:39

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

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


              1. boldape
                10.10.2023 08:39

                Я отрицаю лишь отсутствие понятных и полезных моментов в стандарте

                Ну это же совершенно очевидно. Представьте себе вселенную где стандарт с++ НЕ содержит ни единого понятного и/или полезного момента. Зачем такой стандарт кому то нужен, если по факту, в такой вселенной, им нельзя пользоваться?

                постулируй я понятность всего стандарта, пришлось бы проделать куда более серьёзную работу

                Никакая работа не сможет доказать кому либо понятность стандарта, т.к. понятность категория субъективная.

                С вами спорят, потому что вы настаиваете на том, что если ВЫ нашли что то полезное и понятное в стандарте, то и остальным стоит тоже его читать. Но читать стандарт кому либо стоит лишь только в том случае если этому человеку понятно то что он прочтет, а не потому что кому то другому это понятно. Очевидно, не попробовав не узнаешь навярнека, но многие находят разумным положиться на мнение коллективного разума и даже не пробовать.

                Коллективный разум на основе опыта утверждает, что вы ненормальная/крайне редкая, в смысле распределение вероятности, вы случайный всплеск на хвостах распределения, т.к. нормальным студентам стандарт не понятен от слова совсем. И не только студентам, но и многим опытным разработчикам тоже.


                1. x6x4 Автор
                  10.10.2023 08:39

                  Теперь поняла, спасибо за пояснения.

                  Насчёт вселенной: ну смотря для кого, понятие понятности/полезности субъективно. Вполне вероятно, что и в нашей вселенной есть те, кому ничего не понятно и не полезно. И не обязательно всем пользоваться стандартом, кому-то это просто может быть не надо.

                  Насчёт работы: ну не обязательно всем доказывать, можно было просто какое-то более обширное и аргументированное исследование провести. Опять же, кому понравится, тому понравится. Всем в любом случае не доказать, вне зависимости от объективности/субъективности.

                  Насчёт спора: я вроде не настаиваю, а предлагаю, на основе своего опыта. Если многие не хотят пробовать, по идее можно вообще не предлагать ничего. Но это же не так - люди довольно успешно делятся друг с другом опытом. И я в общем-то не понимаю, чем моя статья отличается от обычного предложения.

                  Могу ли я как-то её улучшить, или сама идея говорить о стандарте не имеет смысла?


                  1. boldape
                    10.10.2023 08:39
                    +1

                    Я вот буквально сегодня читал один короткий фрагмент стандарта раз 10 наверное, что бы окончательно осознать, что то как мне надо и то как оно работает на мракософтовском компиляторе на шланге и гцц работает по другому и это согласно стандарту нормально, потому что имплементэйшен дефаинд.

                    Говорить о стандарте действительно смысла мало, он нужен по факту только компиляторо строителям. Ничего улучшать не надо, уже все сделано - cppreference.com это с++ Вики на основе стандарта и с немного более понятным языком и примерами. А ещё много неважных(в контексте) слов стандарта выброшено, и это читается на порядок легче чем стандарт. Я на самом деле пользуюсь именно этим ресурсом 99,99% времени. Вот только сегодня я заглянул в настоящий драфт, а до этого лет 10 назад туда смотрел потому что цппреф в целом понятней, в том числе и за счёт вёрстки, и потому что показывает историю изменений от версии к версии и структура лучше.

                    Но это же не так - люди довольно успешно делятся друг с другом опытом. И
                    я в общем-то не понимаю, чем моя статья отличается от обычного
                    предложения.

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

                    Обычный плюсовик послушает вас и пойдет читать стандарт, поймет что он не может понять что там написано, растроиться по этому поводу, его самооценка немного на время упадет и вообще он безрезультатно потрати свое время. Какой же это хороший совет/опыт с его точки зрения? Ещё раз хороший совет/опыт это такой который ЛЁГОК для применения большинству целевой аудитории и при этом реально помогает что то понять/улучшить.


                    1. x6x4 Автор
                      10.10.2023 08:39

                      Хорошо, большое спасибо, теперь поняла. Впредь постараюсь думать о возможных последствиях для ЦА.


  1. kekoz
    10.10.2023 08:39

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


    1. x6x4 Автор
      10.10.2023 08:39

      Ну компилятор не может противоречить стандарту. Он может реализовывать как угодно, но в его рамках.

      Или у вас есть кейсы, где не так?


      1. boldape
        10.10.2023 08:39

        Есть, это называется багами в компиляторе или не полным соответствием. От того факта, что вы обнаружите несоответствие реального поведения стандарту ваша жизнь не улучшится, т.к. с вероятностью 146% вы не сможете заменить компилятор и вам придется искать воркароунд для вашей проблемы. И таких случаев больше чем вам кажется, особенно часто такое случается с недавно стандартизированным поведением/семантикой.


        1. Goron_Dekar
          10.10.2023 08:39

          Хуже того: завтра компилятор уже поменяют за вас, и там бага не будет. Но ваш код уже написан с учётом этого бага.