Задать вопрос
Ответы пользователя по тегу ООП
  • Обьясните в чём суть инкапсуляции?

    TrueBers
    @TrueBers
    Гуглю за еду
    Оу, май, 4 человека ответили, и ни один не понимает, что такое инкапсуляция... деградация какая-то, алё!

    Причём тут защита данных? Причём тут контроль доступа? Сокрытие данных? Геттеры, сеттеры? private, public?
    Это всё не имеет никакого отношения к инкапсуляции, это всё побочные эффекты, либо способы реализации в конкретном языке.

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

    ООП и его фишки тут не причём. Ни геттеры, ни сеттеры, ни private\public никакого отношения к этому не имеют. Инкапсуляция может быть даже статической, когда, например разрешаются модули во время компиляции, и язык вообще не должен быть объктно-ориентированным при этом. Инкапсуляция может реализовываться вообще распределённо по разным нодам, которые реализуют интерфейс. Да и ещё чёрт знает как. Скрывать данные не нужно от пользователя. Часто даже удобно обратное -- не писать кучу бойлерплейта, а просто дать возможность пользователю сконфигурировать интерфейс через изменение стейтов в его реализации напрямую, если позволяет платформа, соблюдая инварианты. Это будет более верным архитектурным дизайном, нежели городить какие-то костыли "вдруг пользователь идиот и всё поломает".

    На этом всё, это и есть инкапсуляция.
    Ответ написан
    Комментировать
  • Почему в 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?
    Ответ написан