Ответы пользователя по тегу ООП
  • Почему в C++ нужно строить всю программу на ООП (длинный вопрос)?

    TrueBers
    @TrueBers
    Гуглю за еду
    Длинному вопросу — длинный ответ:

    при этом под полиморфизмом понимается динамический полиморфизм

    А почему вы отрицаете статический? У динамического, например, есть накладные расходы на vtable, инвалидации кешей, и т. п. Если бы STL использовал динамический полиморфизм, у нас бы не было такой эффективности. А у статического таких проблем нет.

    инкапсуляция (то есть в C++ это будет выражено классом с private и public функциями-членами)

    Инкапсуляция — это совсем не про private и public. А скорее про интерфейс и его сокрытую реализацию.
    www.ddj.com/cpp/184401197

    Про отрисовку виджетов, на самом деле, вопрос холиварный. С виджетами изначально мы имеем поломанный интерфейс. Т. е. Widget может добавить в себя тип Widget* или Widget&. А теперь делаем так:
    class Widget {
    public:
      void add(shared_ptr<Widget> child);
    };
    
    auto root = make_shared<Widget>();
    root->add(root); // о_О шта?

    Мы так сделать можем, а значит интерфейс неверный. Кучи проверок в функции add() никому не нужны. Есть такой мужик Sean Parent, может слышали, вот он предложил этой проблеме замену на другую структуру данных со статическим полиморфизмом, без ненужных оверхедов. Они это используют в Фотошопе. На каком ещё языке это можно сделать столь эффективно?

    мы не знаем в данном месте кода, какой это именно виджет, но нам нужно вызвать draw, который может быть разным в зависимости от типа виджета

    А как же мы у STL-контейнеров тогда это вызываем и всё прекрасно работает без наследования и виртуальных функций?

    Вы скажете, что virtual call быстрее switch

    Не факт, зависит от оптимизатора и количества функций. Адекватный оптимизатор разворачивает свитч в jump-table, который на пару процентов может быть быстрее, чем виртуальный вызов. При этом, точно так же, он может девиртуализировать виртуальную функцию если она используется в элементарном базовом блоке, например, в цикле.

    От vector'а не рекомендуется наследоваться

    От него и никогда не требуется этого. Достаточно набросать адаптер, идеология C++ в трёх, как вы сказали, китах: контейнеры, итераторы и алгоритмы. Написав адаптер, он будет работать со всей стандартной библиотекой и алгоритмами, чего обычно более, чем достаточно. Например, те же std::queue, std::priority_queue и std::stack являются адаптерами и могут изменять вектор (и не только), ни от кого при этом не наследуясь.

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

    Ну, дык, верно. Вас собеседуют же не всегда гении. Бывают дурни, задроты, идеалисты, холиварщики, ЧВСшники. Ничего хорошего от них обычно не стоит ждать. От таких надо валить подальше просто.

    Насчёт виртуальных функций в Си и прочих притаскиваний функций плюсов в этот язык. Считаю, что это дурость, когда можно просто создать coding convention для плюсового кода, и писать на нём в стиле Си, но при этом юзать множество полезных плюсовых фич. Это верный подход, имхо. А когда начинается имитация этого всего: забыл инициализировать, или где-то, непойми где, инициализировал не тем, пока найдёшь проблему, вместо того, чтоб просто открыть код конструктора.

    Итого, мой ответ:
    1. Своей задаче — свой инструмент. Не забивайте гвозди микроскопом, он вам пригодится целым для другого.
    2. Не холиварьте. Если так "положено", но нихрена ни в какие рамки не лезет, не нужно это дальше туда пихать. Нужно переступить через гордость и идеалы, и сделать по-другому.
    3. Выжимайте максимум из каждой парадигмы и технологии. Благо, в C++ этого навалом. Где-то функциональщина больше попрёт, где-то лучше шаблонами нагородить. А уж где не получилось, придётся костыли пихать.
    Ответ написан
    2 комментария
  • C++. Как происходит возвращение локального объекта функциями?

    TrueBers
    @TrueBers
    Гуглю за еду
    samp *ob;
        ob = &func();


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

    Включите все уровни предупреждений в вашем компиляторе и он вам скажет, что вы неправильно делаете. По крайней мере clang и gcc об этом скажут по умолчанию. Думаю, что и вижуал студия справится.
    Ответ написан
    Комментировать
  • Как правильно написать MutexLocker?

    TrueBers
    @TrueBers
    Гуглю за еду
    А чем не угодил std::lock_guard?
    Ответ написан