Upgrade to Pro — share decks privately, control downloads, hide ads and more …

АФТИ ООП 2014-2015. Лекция II/10

АФТИ ООП 2014-2015. Лекция II/10

Oleg Dashevskii

April 27, 2015
Tweet

More Decks by Oleg Dashevskii

Other Decks in Education

Transcript

  1. OBJECT POOL 
 (ПУЛ ОБЪЕКТОВ) • Вместо вызова new и

    delete берём объект из пула. Когда не нужен — возвращаем. • +: не теряется время на конструирование и уничтожение. • –: если пула недостаточно? • –: невозвращение приводит к быстрому исчерпанию пула. • Пример применения: пул соединений с сервером БД.
  2. NULL OBJECT
 (ОБЪЕКТ-ЗАГЛУШКА) • Полная реализация какого-нибудь интерфейса, которая ничего

    не делает (все методы с пустыми телами). • Вместо nullptr можно передавать указатель на объект такого класса — избавившись тем самым от nullptr!
  3. class Logger { public: virtual void debug(const std::string &) =

    0; virtual void info(const std::string &) = 0; virtual void warn(const std::string &) = 0; virtual void error(const std::string &) = 0; virtual void fatal(const std::string &) = 0; }; class StreamLogger : public Logger { public: StreamLogger(std::ostream &os); void debug(const std::string &) override; // …а также info, warn, error и fatal }; class BigDoer { public: BigDoer(Logger *log); void doIt() { if (log) log->debug("Starting"); // ... if (log) log->debug("Almost done"); // ... if (log) log->debug("Finished"); } };
  4. class NullLogger : public Logger { public: void debug(const std::string

    &) override {} // …а также info, warn, error и fatal }; class BigDoer { Logger &log; public: BigDoer(Logger &_log); void doIt() { log.debug("Starting"); // ... log.debug("Almost done"); // ... log.debug("Finished"); } };
  5. SERVANT (СЛУГА) • Разновидность паттерна Command. • Некоторое поведение из

    иерархии классов выносится в отдельный класс (слугу). Слуга оперирует объектами, которые ему дали, «своего» у него ничего нет. • Лёгкий и недорогой способ соблюдать Single Responsibility Principle.
  6. struct Point { int x = 0; int y =

    0; }; class Movable { public: virtual void setPosition(const Point &p) = 0; virtual Point position() const = 0; }; class Triangle : public Movable { int A, B, C; Point pos; public: // ... void setPosition(const Point &p) override { pos = p; } Point position() const override { return pos; } }; struct Mover { static void moveTo(Movable &obj, const Point &newPos) { Point prevPos = obj.getPosition(); std::cout << "Moving from " << prevPos << " to " << newPos << std::endl; obj.setPosition(newPos); } static void moveBy(Movable &obj, int dx, int dy) { Point prevPos = obj.getPosition(); Point newPos { prevPos.x + dx, prevPos.y + dy }; moveTo(obj, newPos); } };
  7. MVC (МОДЕЛЬ- ПРЕДСТАВЛЕНИЕ-КОНТРОЛЛЕР) • Модель: оперирует данными в логике задачи.

    Ничего не знает о способах их представления и о взаимодействии с пользователем. • Представление: отображает данные модели, не оперируя с ними и не взаимодействуя с пользователем. • Контроллер: получает запросы пользователя и посылает их модели и представлению.
  8. EVENT LOOP 
 (ЦИКЛ ОБРАБОТКИ СОБЫТИЙ) • Прямые вызовы методов

    заменяются на помещение запроса в очередь сообщений. • В цикле обработки сообщений очередь разгребается. • Все обработки должны быть быстрыми.
  9. class MessageLoop; class Object { MessageLoop *loop; public: bool processMessage(int

    message, void *data) = 0; }; struct QueueItem { Object *object; int message; void *data; clock_t time; }; class MessageLoop { std::vector<QueueItem> queue; public: // ... void sendMessage(Object *obj, int message, void *data); void postMessage(Object *obj, int message, void *data, unsigned delay = 0); void run(); };
  10. ОБЪЕКТНЫЙ ФАЙЛ FILE.OBJ • Машинный код функций и методов, объявленных

    в file.cpp. • Память под объявленные глобальные и статические переменные. • Ссылки на внешние функции и методы. • Ссылки на глобальные переменные.
  11. РАБОТА ЛИНКЕРА • Операционная единица: имя. Каждый объектный модуль (в

    т.ч. библиотечный): • Предоставляет какие-то имена (функции, переменные...) • Требует какие-то имена. • Линкер удовлетворяет зависимости (все начинается с имени main). • Ошибки: • Имя требуется одним из модулей, но не предоставляется ни одним из них. • Одно и то же имя предоставляется более, чем одним модулем.
  12. ИСПОЛНЯЕМЫЙ ФАЙЛ • Содержит все нужные имена (и ничего лишнего).

    Все ссылки на имена в объектных файлах были разрешены. • По построению зависит от объектных файлов и библиотек (те зависят от исходных файлов). • Для выполнения не нужно больше ничего (за исключением динамических библиотек).
  13. КАК ПОДКЛЮЧИТЬ БИБЛИОТЕКУ? • Первый вариант — просто скопировать её

    исходные *.cpp и *.h файлы в свой проект. • Второй вариант — воспользоваться готовой сборкой.
  14. Компилятор Исходник Объектник *.h файлы
 библиотеки Линкер Исп. файл *.lib

    файлы
 библиотеки Подключаем готовую сборку библиотеки
  15. ДИНАМИЧЕСКИЕ БИБЛИОТЕКИ • Код и данные, соответствующие именам, находятся в

    отдельном файле (*.dll). • Статическая линковка DLL — в исполняемый файл включаются ссылки на DLL-файлы. Без них он просто не запустится. • Динамическая подгрузка DLL — файл открывается прямо в процессе исполнения программы. Используется для плагинов.
  16. СТРУКТУРИРОВАНИЕ ИСХОДНЫХ ФАЙЛОВ • Проще всего: один класс (или namespace)

    — 1 .h-файл и 1 .cpp-файл. • Объявления пространств имён, типов, классов, констант и т.п. — в .h файл. • Определения inline-функций — туда же. • Шаблоны классов, специализации, шаблонные методы обычных классов — туда же. • Определения обычных функций и методов — в .cpp-файл! Рядом можно положить объявления и определения вспомогательных классов (внутри namespace { }).
  17. КРУПНЫЕ БЛОКИ ПРОЕКТА • Главный результат: набор исполняемых файлов. •

    Вспомогательные результаты: DLL и LIB. • Всё общее выносится в библиотеки.