Кресты / Говнокод #27655 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
Если у меня есть приватный метод, то зачем мне его объявлять в .h-файле?
Хочу только в .cpp написать вспомогательный метод и только там его использовать.
А вынужден копипастить сигнатуру ещё и в .h.

Запостил: 3_dar 3_dar, (Updated )

Комментарии (151) RSS

      • Ну так-то он прав: значение имеют только ПЕРЕМЕННЫЕ (потому что занимают место) и публичные методы.

        ООП гоавно
        Ответить
    • Фу. Говно, в котором нужно будет дублировать вызовы паблик методов? И из-за которого утяжеляется навигация из-за JAWA-подобной лапши, которая нихуя не делает? Нет уж, спасибо.
      Ответить
      • Наверное можешь сделать рядом класс Util, объявить его другом, и вынести код туда
        Ответить
        • И в него передавать this? Хуйня какая-то.
          Ответить
          • Ну да, а что?

            Я бы вообще вынес всё в свободные функции и передавл зис, если не нужно приватных полей.


            Ладно, давай дожемся Борманда и ISO
            Ответить
            • Давайте подождём j123123 и он расскажет, что в «С» никаких методов нет и this всегда передавался явно.
              Ответить
              • И будет прав. В "си" такой проблемы нет в принципе.

                Пока ООПушки решают какие-то выдуманные проблемы, сишники пишут код
                Ответить
      • А зачем дублировать? Ты не обязан проксировать вызовы в импл, читай поля импла да и всё. А импл будет тупо для данных и приватных методов.
        Ответить
    • Пимпл от хорошей жизни не юзают... Он нужен либо ради стабильного ABI либо чтобы сишное наследие с макроснёй и прочими ужасами всем клиентам не прилетало.
      Ответить
      • Pimple это прыщ, кстати. Справедливо ли утверждение, что в этом треде мы решаем надуманные прыщепроблемы?
        Ответить
  • Ка на счет этого?

    class my_genius_class_impl;
    class my_genius_class
    {
    ...
    private:
    my_genius_class_impl *_pimpl;
    ...
    }

    Все приватное пихаешь в my_genius_class_impl и описываешь и используешь в скрытых cpp и hpp.

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

    Оп, оп, джава-стайл.

    Минус такой же как у пимпла -- надо кучу и лишняя индирекция.
    Ответить
    • Чем это от пимпла отличается? Приведи реальный пример.
      Я ненавижу pimpl не за кучу, а за ненужную вложенность вызовов.
      Ответить
      • В пимпле у тебя класс косплеит value type, а кишки прячет в куче.

        С интерфейсами класс надо таскать по указателю, как в джаве. Зато кишки не разбросаны и можно сделать несколько реализаций.
        Ответить
        • Так Инью и говорит, что с затратами на кучу он еще может смириться, а писать много буков ему не нравится
          Ответить
      • > вложенность вызовов

        А ты не вкладывай. Считай, что импл -- это просто структурка с полями и хелперами. Никто не заставляет делать "красиво" и проксировать вызовы в импл.
        Ответить
        • // roost.h
          struct Roost {
              void kukarek();
          private:
              void kok();
          };
          
          
          // roost.cpp
          #include "roost.h"
          
          void Roost::kukarek() {
              kok();
          }
          void Roost::kok() {
              cout << "kok\n";
          }



          Переведи на то, что ты предлагаешь. Я не понимаю.
          Ответить
          • Приват с полями в RoostImpl у которой всё публичное. Roost держит RoostImpl по unique_ptr. Roost::kukarek зовет m_impl->kok() или лезет к полям m_impl сразу и делает всю работу если она несложная.

            Impl не обязан быть классом с полноценной инкапсуляцией, он наружу не торчит
            Ответить
            • > Impl не обязан быть классом с полноценной инкапсуляцией, он наружу не торчит

              Ясно. Для меня то это один хуй.
              Ответить
              • А мне вообще похуй на всякие инкапсуляции, я даже слов таких не знаю!
                Ответить
                • Ну как видишь Борманжу тоже похуй: он предлагает сделать полностбю публичного питуха и обернуть его питухом-интерфейсом

                  Именно потому я за "питон" (нет)
                  Ответить
                  • Я считаю инкапсуляцию инструментом, а не смыслом жизни.

                    В общем-то даже в джаве не парятся и разрешают доступ из всех соседей по пакету.
                    Ответить
                    • К приватным не разрешают:)

                      Но вообще я бы так сказал: приватно всё, что не документировано. Насиловать язык чтобы сэмулировать приватность и правда не всегда нужно
                      Ответить
                • Инкапсуляция — это хорошо, на ней интернет держится. А оопитухи-угнетатили просто культурно аппроприировали наш термин.
                  У нас в ``Erlang'', кстати, правильная инкапсуляция.
                  Ответить
    • Почему вообще существует эта проблема?

      Чтобы я случайно в чужой класс не влез?
      Ответить
      • Потому что труп страуса не решился запилить модули в своё время, оставил сишные хедера, в которых все кишками наружу.

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


          Почему не разрещить .cpp файлу добавить любой метод, если в .h файле явно указать его как имеюшщий на такое право?
          Ответить
          • Потому что "свой" и "чужой" цпп невозможно отличить (это НЕ модули, это просто подстановка текста, нет никакой связи между цпп и аш), вся суть private теряется.
            Ответить
            • Так я и предлагаю ввести физгармонию, позволяющую это делать. Чтобы "h" мог явно сказать "вот мой главный cpp"
              Ответить
        • > Потому что труп страуса не решился запилить модули в своё время, оставил сишные хедера, в которых все кишками наружу.

          Переходи на "D".
          Ответить
  • на .xyz нельзя написать "прив*тный метод"
    какой багор
    Ответить
  • А вообще, можешь по заветам d++ ебашить хедер онли и течь.

    Никакого дублирования, топовый пирфоманс, никаких проблем с разбиением на аш и цпп.
    Ответить
    • >Никакого дублирования
      кроме кода в .o?
      Ответить
        • Так это понятно, но файлы-то насруца
          И скомпилируются два раза
          Ответить
          • А зачем второй раз, кстати? В труъ хедер онли у тебя один main.cpp, всё остальное в хедерах.
            Ответить
            • Ну если я напишу код в .h файле и подключу его в два места, то у меня же он два раза скомпилируется и насрётся в два .o файла, не?

              > тебя один main.cpp, всё остальное в хедерах.
              аааа, гггг
              ну ок
              Ответить
        • Вот именно по этому ротоёб и за "рты"


          За одно нет проблемы с системой сборки: не нужно никакие сложные файлы писать
          Ответить
    • Тоже вариант. Я так делал в своём личном проекте. Но на работе не получится, иначе по 3 часа собираться будет на каждое изменение.
      Ответить
      • А еще приятно когда его шесть человек поправили одновременно, и случился мёрдж конфликт
        Ответить
          • main.cpp-то всё равно нужен чтобы их подключать
            Ответить
            • А зачем тебе менять «main.cpp» ради правки отдельных файлов? Питух 1 правит «1.hpp», питух 2 — «2.hpp», «main.cpp» не меняется. Никаких «мёрдж-конфликтов».
              Ответить
            • А зачем тебе менять «main.cpp» ради правки отдельных файлов? Питух 1 правит «1.hpp», питух 2 — «2.hpp», «main.cpp» не меняется. Никаких «мёрдж-конфликтов».
              Ответить
              • А в это время четвертый питух подключает petuh4, а пятый тоже свой petuh4, и пиздец.

                Хотя проблема конечно несколько надуманная, я согласен.

                Можно ли подключить автоматически все .hpp файлы в папке?
                Ответить
            • В нём просто триггеришь разворечивание мегашаблона и всё.
              Ответить
        • > его

          Его? В бусте вон тыщи хедеров которым не нужны цппшки. Никто не мешает разбивать код по разным хедерам.
          Ответить
          • main.cpp-то всё равно нужен чтобы их подключать
            Ответить
            • А зачем тебе менять «main.cpp» ради правки отдельных файлов? Питух 1 правит «1.hpp», питух 2 — «2.hpp», «main.cpp» не меняется. Никаких «мёрдж-конфликтов».
              Ответить
              • А в это время четвертый питух подключает petuh4, а пятый тоже свой petuh4, и пиздец.

                Хотя проблема конечно несколько надуманная, я согласен.

                Можно ли подключить автоматически все .hpp файлы в папке?
                Ответить
                  • Жалко.

                    Можно сделать такой API для плагинов, и писать их в виде hpp
                    Ответить
                    • > Можно сделать такой API для плагинов, и писать их в виде hpp

                      Это ваш мозг на крестах.
                      Ответить
            • А зачем тебе менять «main.cpp» ради правки отдельных файлов? Питух 1 правит «1.hpp», питух 2 — «2.hpp», «main.cpp» не меняется. Никаких «мёрдж-конфликтов».
              Ответить
              • А в это время четвертый питух подключает petuh4, а пятый тоже свой petuh4, и пиздец.

                Хотя проблема конечно несколько надуманная, я согласен.

                Можно ли подключить автоматически все .hpp файлы в папке?
                Ответить
                • > Можно ли подключить автоматически все .hpp файлы в папке?
                  Используя PHP в качестве препроцессора — да.
                  Ответить
              • А в это время четвертый питух подключает petuh4, а пятый тоже свой petuh4, и пиздец.

                Хотя проблема конечно несколько надуманная, я согласен.

                Можно ли подключить автоматически все .hpp файлы в папке??
                Ответить
                • > Можно ли подключить автоматически все .hpp файлы в папке??

                  find -name "*.h" -exec echo '#include "{}"' \; >main.cpp
                  Ответить
                  • sed не нужен
                    find .  -name '*.h*' -exec echo "#include<"{}">" > main.cpp \;
                    Ответить
                      • да, так еще пижже

                        find вообще мощная питушня очень
                        Ответить
                        • > мощная питушня

                          Правда я вообще не помню его опции, обычно просто высираю список файлов и другими тулами обрабатываю (i.e. find | grep). Поэтому -printf сразу в голову не пришёл.
                          Ответить
                          • Советую иногда освежевать знания)

                            Он умеет несколько условий по OR или AND объединять например
                            Ответить
                    • Можно вот так ещё, чтобы на лету без генереций:
                      gcc main.cpp `find -name "*.h" -printf '-include %p '`
                      Главное чтобы хедер с бармин-инъекцией не прилетел.
                      Ответить
            • В нём просто триггеришь разворечивание мегашаблона и всё.
              Ответить
        • Смысле? У меня много .h файлов и 1 .cpp. На каждое изменение троттлица проц и Clion зависает всё это говно парсить.
          Ответить
  • «Pimpl» не обязан использовать кучу.
    #include <string>
    #include <cstdio>
    
    // peetooh-kishki.hpp
    class PeetoohImpl {
    public:
        PeetoohImpl(std::string name) : name(std::move(name)) {}
    
        void private_kukareku() const
        {
            std::printf("%s: kukareku!\n", name.data());
        }
    
        static PeetoohImpl *cast(void *impl) noexcept
        {
            return reinterpret_cast<PeetoohImpl*>(impl);
        }
    
        static const PeetoohImpl *cast(const void *impl) noexcept
        {
            return reinterpret_cast<const PeetoohImpl*>(impl);
        }
    
        std::string name;
    };
    
    constexpr size_t PEETOOH_IMPL_SIZE = sizeof(PeetoohImpl);
    constexpr size_t PEETOOH_IMPL_ALIGN = alignof(PeetoohImpl);
    
    // peetooh-public.hpp
    // #include "peetooh-kishki.hpp"
    class Peetooh {
    public:
        Peetooh(std::string name);
        void public_kukareku() const;
    
        std::aligned_storage_t<PEETOOH_IMPL_SIZE, PEETOOH_IMPL_ALIGN> impl;
    };
    
    // peetooh-public-impl.cpp
    Peetooh::Peetooh(std::string name)
    {
        new (&impl) PeetoohImpl(std::move(name));
    }
    
    void Peetooh::public_kukareku() const
    {
        PeetoohImpl::cast(&impl)->private_kukareku();
    }
    
    int main()
    {
        auto peetooh = Peetooh("Petya");
        peetooh.public_kukareku();
        
        return EXIT_SUCCESS;
    }

    https://gcc.godbolt.org/z/hv33eT7jd
    Единственная проблема — прокинуть в публичный интерфейс размер и выравнивание приватного питуха. А так — полный зирокост.
    Ответить
    • эм
      а не придеца потом пересобирать всё когда размер внутреннего питуха изменица?
      Ответить
      • Придётся. Но тут уж или рыбку съесть…
        Собственно, если ты не используешь такой «pimpl» и изменяешь публичный класс — тебе всё равно придётся всё пересобирать.
        Ответить
        • Я думал смысл пимпла в том, чтобы в тайне от клиентов ковырять внутренние кишки, а так ABI всё равно поломается же

          Впрочем, API не сломается, так что выпускать новый .h не придется
          Но клиента нужно будет перебрать

          или нет?
          Ответить
          • Оригинального, который через кучу — да. А вот такой зирокост-пимпл работает только для скрытия кишков, но не абстрагирования от них.

            API тоже сломается: размер публичного-то петуха тоже изменится.
            Ответить
    • Почитай тред. Мне похуй на кучу/не кучу. Мне чтобы кода меньше было.
      Ответить
    • > reinterpret_cast
      > std::aligned_storage_t
      > new (&impl)
      > alignof
      > void*
      > noexcept

      Выебнулся, молодец. В моём коде такой хуйни нет.
      Ответить
      • Ну тогда кучу соси

        Без плейсмент нью ты никак не
        Ответить
        • Лол. Просто вместо указателя делаешь не указатель.
          Ответить
          • А какой тогда смысл в отделении имплементации? Тебе её придётся демонстрировать всем желающим.
            Ответить
            • Ты точно понял что мне нужно?

              https://govnokod.xyz/_27655/#comment-658861

              Здеся не объявлять kok() в h-нике.

              Можно сделать pimpl как с указателем, так и без него. Тогда приватные методы не нужно описывать в .h. Но исходную проблему (количество кода) это не решает.
              Ответить
              • Ну да, а я что предложил?
                // peetooh-public.hpp
                // #include "peetooh-kishki.hpp" <- как избавляться от этого — вопрос другой
                class Peetooh {
                public:
                    Peetooh(std::string name);
                    void public_kukareku() const;
                
                    std::aligned_storage_t<PEETOOH_IMPL_SIZE, PEETOOH_IMPL_ALIGN> impl;
                };

                «private_kukareku()» — это и есть твой «kok».

                > количество кода
                Если твоя проблема именно в количестве кода — то тебе действительно нужно описывать весь класс в .hpp. Меньше ты в любом случае никак не сделаешь.
                Ответить
                • Меня бы устроило описывать только public методы в h. Вопрос был в том почему крестопетухи не предоставили такой возможности. Одному мне это не нравится?
                  Я меняю сигнатуру приватного метода и мне нужно подправить это в двух местах, когда этого можно было избежать.
                  Ответить
                  • > Вопрос был в том почему крестопетухи не предоставили такой возможности
                    Потому что компилятор должен иметь возможность скомпилировать твой класс исключительно по его объявлению. Грубо говоря, .h-файл — это не только API, а ещё и ABI. Без объявления приватных членов ABI объявить невозможно без грязных хаков.
                    Ответить
                    • Чтобы в таблице виртуальных методов были правильные смещения? А если вместо приватных методов и полей в хедере написать foo, bar, baz, чтобы секреты не раскрывать?
                      Ответить
                      • > Чтобы в таблице виртуальных методов были правильные смещения?
                        В том числе, да.

                        > А если вместо приватных методов и полей в хедере написать foo, bar, baz, чтобы секреты не раскрывать?
                        Какая обфусцированная «Java» )))
                        Ответить
                      • А если мои приватные методы не виртуальны?
                        Ответить
                • Нахуй так сложно? Почему не
                  class Pituh {
                      PituhImpl impl;
                  public:
                      void kukarek() {
                          impl.kukarek();
                      }
                  };

                  ?
                  Ответить
                  • Потому что я привёл реальный пример именно каноничного «pimpl» в статической форме. Твой пример, разумеется, тоже будет работать, и, возможно, решать твою задачу (я не знаю, подходит ли это тебе), но это не «pimpl».

                    P.S. А ещё у меня там тупая утечка — помнил о ней, но забыл поправить перед постингом. Какой багор )))
                    Ответить
                      • В контексте разговора — тем, что он не решает задачу, для которой создан «pimpl» — полное сокрытие приватной реализации. Справедливости ради, «pimpl» через кучу ещё решает задачу бинарного отвязывания публичного интерфейса от приватного — у статического с этим похуже.

                        Для твоей задачи он, возможно, и лучше.
                        Ответить
                        • > полное сокрытие приватной реализации

                          Чем мой пример не подходит?
                          Ответить
                          • Тем, что для того, чтобы сделать «PituhImpl impl» — тебе в любом случае придётся сделать #include «PituhImpl.hpp», в котором лежат твои приватные методы. В моём варианте это не обязательно (хотя с инклудом и проще).
                            Ответить
                            • Не подумал. В моём примере нужно где-то в отдельном файле объявить PituhImpl и все его методы (в т.ч приватные).
                              И тут мы опять приходим к вопросу - писать в одном impl.hpp, или разносить в .cpp. Тогда нахуй оно надо?
                              Ответить
                            • В твоём примере тоже нужно инклудить PituhImpl.hpp. Иначе как ты его методы вызывать собрался без хедера?
                              Ответить
                              • В моём примере иклудить его надо только в .cpp, что позволяет скомпилировать реализации обоих классов, упаковать в «.dll» и выдать клиенту заголовочный файл, содержащий исключительно публичные методы, и скомпилированную библиотеку, обеспечивая тем самым полное* сокрытие реализации.

                                * Против «IDA Pro» нет приёма.
                                Ответить
                                • Теперь понятно. Я указал, что на стеке у меня будет вот эта вот структура (заинклудя её).
                                  А ты указал, что у тебя тут будет некое говно вручную предпосчитанного размера (без инклуда).
                                  Ответить
                                    • То есть мой пример неюзабельный. Я смог наебать самого ISO!
                                      Ответить
                                    • А как ты размер узнаешь? Вручную захардкодишь, а в cpp static_assert заебенишь? )
                                      Ответить
                                      • Ну да. В скомпилированной библиотеке он точно меняться не будет.
                                        Ответить
                                        • Нахуй так ебаться. Уж лучше укокозатель.
                                          Ответить
                                • > * Против «IDA Pro» нет приёма.

                                  Прыжок в середину инструкции.

                                  ** Такой прыжок невозможен в RISC-процессорах и в процессорах, требующих выравнивания адреса перехода.
                                  Ответить
                                  • > ** Такой прыжок невозможен в RISC-процессорах***

                                    *** Но у некоторых RISC-процессоров, таких как "ARM" с набором инструкций "thumb-2" таки возможен. Правда х.з. получится ли там что-то разумное и полезное.
                                    Ответить
                                    • Такие трюки на ARM будут сопоставимы с программированием на Malbolge. Одна только запись immediate чего стоит!
                                      Ответить
                                      • addi    s0,sp,688        ;1d00
                                        auipc   zero,0x1d000     ;1d000017
                                        
                                        addi   tp,a4,1           ;00170213
                                        
                                        addi    a2,sp,708        ;05d0                	
                                        li      a7,42            ;05d00842

                                        Два реальных примера коллизий.
                                        Ответить
                                    • > Но у некоторых RISC-процессоров, таких как "ARM" с набором инструкций "thumb-2"
                                      И у MIPS16, и даже у тех, который имеют слово RISC прямо в названии.
                                      Реальный пример:
                                      add(x):
                                       lui	a1,0x30   ;000305b7
                                       add	a0,a0,a1  ;952e
                                       ret              ; 8082
                                      Ответить
                                    • > *** Но у некоторых RISC-процессоров, таких как "ARM" с набором инструкций "thumb-2" таки возможен. Правда х.з. получится ли там что-то разумное и полезное.

                                      https://govnokod.ru/20245#comment335899

                                      я об этом писал.
                                      Ответить
                                  • Идея с прыжком без асмовставки: заставляем компилятор сгенерировать инструкцию mov регистр, константа. Например, вызвать какую-нибудь функцию с соглашением fastcall/sysvabi/msabi или оператор return. В бинарнике для x86_64 будет байт b8...bf, за которым следует константа. Нужно взять адрес метки оператора, увеличить на единицу и сделать computed goto. Тогда мы выполним не mov, а опкод, записанный в константе. Правда, можем соснуть, если запустим компилятор с другими ключами оптимизации.

                                    «IDA Pro» дизассемблирует только одну из веток: либо исходную функцию с mov, либо сгенерированный нами опкод.
                                    Ответить
                                    • > «IDA Pro» дизассемблирует только одну из веток

                                      Но у неё в названии не просто так есть буква "I". Так что в отличие от автоматических дизасмов ты всегда можешь переключиться между этими ветками.
                                      Ответить
                                    • > «IDA Pro» дизассемблирует только одну из веток: либо исходную функцию с mov, либо сгенерированный нами опкод.

                                      Это проблема «IDA Pro». Дизассемблировать можно по всем возможным смещениям, и визуализировать это как-то так https://i.imgur.com/LvuS6Zt.png
                                      Ответить
                  • Потому что изменение размера impl приведет к нарушению ABI
                    Ответить
  • Переходи на PHP. При желании там можно писать полностью процедурным стилем, безо всяких приватных, публичных, статических, хуических методов. Тупо прописываешь функцию и течёшь.
    Ответить
    • Всегда так делаю, Именно поэтому я против «C#» и «Java», в которых даже хеллоуворлд нельзя написать без классов.
      Ответить

Добавить комментарий

Где здесь C++, guest?!

    А не использовать ли нам bbcode?


    8