Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

OO Design with C++: 6. Templates & Patterns

1,138 views

Published on

Published in: Technology
  • Be the first to comment

OO Design with C++: 6. Templates & Patterns

  1. 1. C++: шаблоны, часть 1 Дмитрий Штилерман, Рексофт
  2. 2. Шаблоны: прагматический подход <ul><li>В C++ шаблоны возникли из практических потребностей разработчиков библиотек. </li></ul><ul><li>Шаблоны классов: </li></ul><ul><ul><li>Обобщенные контейнеры. </li></ul></ul><ul><ul><li>Обобщенные потоки. </li></ul></ul><ul><li>Шаблоны функций: </li></ul><ul><ul><li>Замена стандартных макросов ANSI C </li></ul></ul><ul><ul><li>Операции над обобщенными контейнерами и потоками. </li></ul></ul>
  3. 3. Если бы не шаблоны классов... <ul><li>Указатели на «что-то» (void*)  отказ от статической типизации. </li></ul><ul><li>Указатели на искусственный базовый класс  неоправданное усложнение иерархии, злоупотребление наследованием. </li></ul>class Stack { void push(void*); void* pop(); }; void f() { Stack s; s.push((void*) new Cat); Dog* dog = (Dog*) s.pop(); dog->bark(); }; class StackElem {/*???*/}; class Stack { void push(StackElem*); StackElem* pop(); }; class Cat : public StackElem {}; class Dog : public StackElem {};
  4. 4. Если бы не шаблоны функций... <ul><li>Макросы  отказ от статической типизации, ошибки кодирования , неожиданности при вычислении . </li></ul><ul><li>Перегрузка  утомительное и чреватое ошибками копирование кода. </li></ul><ul><li>Указатели на искуственный базовый класс  см. выше. </li></ul>#define max(a,b) ((a>b) ? (a) : (b)) const Comparable& max(const Comparable&, const Comparable&); int max(int a, int b) {return (a>b) ? a : b;} short max(short a, short b) {return (a>b) ? a : b;} long max(long a, long b) {return (a>b) ? a : b;} float max(float a, float b) {return (a>b) ? a : b;} double max(double a, double b) {return (a>b) ? a : b;}
  5. 5. Когда использовать шаблоны - самый простой критерий <ul><li>Перечисленные выше примеры «кривого кода» - типичные индикаторы того, что пора применить шаблоны. </li></ul><ul><ul><li>Повторения одного и того же кода, отличающиеся только именами типов. </li></ul></ul><ul><ul><li>Искуственные базовые классы, не предоставляющие никакого содержательного интерфейса. </li></ul></ul><ul><ul><li>Сложные параметризованные макросы (не содержащие специальных лексических операций типа склейки или преобразования в строку). </li></ul></ul>
  6. 6. Параметры шаблонов <ul><li>Non-type parameters ( template<int N> ): на практике почти не употребляются (например, в стандартной библиотеке - ни одного). </li></ul><ul><li>Type parameters (template<class T>): подставляемый тип может быть любым, но делаются некоторые предположения о его интерфейсе («должна быть функция f , которую можно вот так вот вызвать»). </li></ul><ul><li>Важный момент : интерфейс, требуемый шаблоном, реализовывается без применения наследования («у нас просто есть функция f , мы ее не наследуем и не переопределяем »). </li></ul>
  7. 7. Instantiation <ul><li>Отношение классификатор-объект a.k.a. class-instance: </li></ul><ul><ul><li>class C {…}; C x; Объект x - экземпляр класса C (instance). </li></ul></ul><ul><ul><li>template<class T> class C {…}; C<D> x; Класс C<D> - экземпляр шаблона C (instantiated class). Объект x - экземпляр класса C<D> (instance). </li></ul></ul><ul><ul><li>template<class T> void f(T) {…} … f<int>(0); Функция f<int> - экземпляр шаблона f (instantiated function). </li></ul></ul><ul><li>Действие компилятора по созданию экземпляра шаблона - instantiation ( инстанциация? инстанцирование ? создание экземпляра ? ). </li></ul>
  8. 8. Шаблон как область действия <ul><li>Шаблон класса не есть класс! Следовательно, шаблон класса не есть область действия ( scope ). template<class T> class C {static void g();}; Нет никакой C::g! Есть C<int>::g, C<std::string>::g и т.д. </li></ul><ul><li>Как сделать шаблон областью действия (т.е. создавать функции/данные, относящиеся ко всем экземплярам шаблона)? Унаследовать шаблон от базового класса, не являющегося шаблоном. class B {static void g();}; template<class T> class C : … B {…}; </li></ul><ul><li>Какое наследование ( public/private, virtual etc. ) применить? Зависит от моделируемого отношения ( “is-a” etc. ) и интерфейса (public etc.), к которому относится имя (C::g). </li></ul>
  9. 9. Specialization <ul><li>Отдельная реализация шаблона при конкретных значениях одного или нескольких параметров. </li></ul><ul><li>Результат - класс или функция (если зафиксированы все параметры) или шаблон с меньшим числом параметров. </li></ul><ul><li>Применения: </li></ul><ul><ul><li>Оптимизированные версии. </li></ul></ul><ul><ul><li>Информационные классы (traits) . </li></ul></ul>template<class T> void MyCopy(T* dst, T* src, int n) { if(dst && src && (dst != src) for(int i = 0; i < n; i++) dst[i] = src[i]; } template<> void MyCopy<int>(int* dst, int* src, int n) {memmove(dst, src, n);}
  10. 10. Реализация шаблонов <ul><li>В первом приближении, шаблоны - это макросы с проверкой типов. </li></ul>template<class T> class Stack {public: Stack() {} void push(T) {…} T pop() {…} }; void f() { Stack<int> is; Stack<string> ss; } class Stack_int {public: Stack_int() {} void push(int) {…} int pop() {…} }; class Stack_string {…}; void f() { Stack_int } А что во втором приближении ? Проблема «code bloating». Template instantiation
  11. 11. Понятие связывания ( linkage) <ul><li>Файл (translation unit) C++ есть последовательность объявлений ( declarations ). Каждое объявление вводит одно или несколько имен ( names ). </li></ul><ul><li>Имя может иметь внешнее или внутреннее связывание ( external / internal linkage). </li></ul><ul><ul><li>Внешнее связывание  имя видно из других файлов. Примеры: глобальные функции; классы. </li></ul></ul><ul><ul><li>Внутреннее связывание  имя не видно из других файлов. Примеры: имена , объявленные как static, inline или const. </li></ul></ul><ul><li>Физический смысл: имена с внешним связыванием видны компоновщику через заголовок объектного файла . </li></ul><ul><li>Имя с внешним связыванием должно быть уникально в программе ( иначе - ошибка компоновки ). </li></ul>
  12. 12. Какое связывание имеет экземпляр шаблона ? <ul><li>Файлы компилируются независимо. Какое связывание имеет foo<X> в file1.cpp и file2.cpp? </li></ul><ul><li>Внешнее нельзя, т.к. будут дублирующиеся имена. </li></ul><ul><li>Внутреннее можно, но тогда копии кода будут содержаться в нескольких файлах (« code bloating », «раздувание кода»). </li></ul><ul><li>Стандарт молчит, имплементации выкручиваются. Основной способ - нестандартные компоновщик, формат объектного файла и специальный вид связывания. </li></ul><ul><li>Та же проблема с inline virtual методами. </li></ul>// foo.h template<class T> void foo(T* p) {p->xyz();} // file1.cpp #include “foo.h” void bar1(X* x) {foo(x);} // file2.cpp #include “foo.h” void bar2(X* x) {foo(x);}
  13. 13. Generic programming <ul><li>Немолодая идея (младше ATD , старше OOP ). </li></ul><ul><li>В оригинальном виде: максимально полное разделение структур данных и обрабатывающих их алгоритмов. </li></ul><ul><li>“ Programming with concepts” A concept is a family of abstractions that are all related by a common set of requirements, where the requirements consist of valid expressions, associated types, invariants and complexity guarantees. </li></ul><ul><li>В строго типизированных языках ( Ada, C++ ) приводит к механизму параметризованных типов . В безтиповых и близких к ним ( Smalltalk, скриптовые языки) получается само собой. </li></ul>
  14. 14. П аттерны (1) <ul><li>Существующие общие определения паттерна: </li></ul><ul><ul><li>A description of communicating objects and classes that are customized to solve a general problem in a particular context. (GoF) </li></ul></ul><ul><ul><li>A three-part rule, which expresses a relation between a certain context, a problem, and a solution. (Alexander) </li></ul></ul><ul><ul><li>An especially clever way of solving an entire particular class of problems. (Eckel) </li></ul></ul><ul><li>Более узкое определение паттерна с точки зрения современного OOD: </li></ul><ul><ul><li>Паттерн есть параметризованная кооперация. </li></ul></ul>
  15. 15. П аттерны (2) <ul><li>Два основных определения: </li></ul><ul><ul><li>Сommunicating objects that are customized to solve a general problem in a particular context. </li></ul></ul><ul><ul><li>П араметризованная кооперация. </li></ul></ul><ul><li>Как соотносятся эти два определения? </li></ul><ul><ul><li>«Кооперация»  « communicating objects », « general problem ». </li></ul></ul><ul><ul><li>«Параметризованная»  « customized », « particular context ». </li></ul></ul><ul><li>Какова связь с параметризованными типами и generic programming? </li></ul><ul><ul><li>Паттерн реализуется в виде набора взаимосвязанных шаблонов. </li></ul></ul><ul><ul><li>Паттерн используется путем подстановки в шаблоны классов, используемых в конкретном контексте. </li></ul></ul>
  16. 16. Пример: паттерн Observer

×