Главная страница
Навигация по странице:

  • Использовать абстрактную функцию и создавать объекты

  • 10 Шаблонные классы Параметризованный класс, тип данных в класс передается как параметр. Определение шаблонного класса template


  • 11 Контейнерные классы 11.1 Определение

  • Библиотека шаблонов STL

  • Контейнер

  • Ассоциативные

  • Итераторы Итератор

  • Аллокатор Аллокатор

  • Функциональные объекты Функциональные объекты

  • Общая функциональность контейнера

  • Функции последовательных контейнеров

  • Функции ассоциативных контейнеров

  • ООП. Пособие по ООП в С++. Создание сложных программных систем Объектно ориентированная технология


    Скачать 2.1 Mb.
    НазваниеСоздание сложных программных систем Объектно ориентированная технология
    Дата21.02.2022
    Размер2.1 Mb.
    Формат файлаpdf
    Имя файлаПособие по ООП в С++.pdf
    ТипАнализ
    #369034
    страница9 из 15
    1   ...   5   6   7   8   9   10   11   12   ...   15

    общими для различных производных классов. Т.е. это некоторая база, от которой наследуются другие классы.
    Класс характеризуется наличием хотя бы одной абстрактной чисто виртуальной функции.
    Формат чисто виртуальной функции
    virtual тип Имя (параметры)=0;
    Каждый производный класс должен определить свою версию реализации чисто виртуальной функции.
    Использовать абстрактную функцию и создавать объекты
    абстрактного класса нельзя.
    Можно создавать указатель на объект абстрактного класса и применять для него механизм полиморфизма.
    Чистая виртуальная функция полезна, когда у нас есть функция, которую мы хотим поместить в родительский класс, но реализацию оставить
    дочерним классам. Чистая виртуальная функция абстрактного родительского
    класса вынуждает дочерние классы переопределить эту функцию, иначе объекты этих классов создавать будет невозможно.
    Пример. Иерархия списковых классов.
    Определение структур Очередь, Стек и Дек основано на определении
    Списка. Так как это линейные структуры, то у них один набор базовых операций: вставить, удалить, получить доступ. сlass TList
    //Список
    { protected:
    Tnode *L;
    Int n; public:
    TList(){n=0;L=0;}

    TList(); virtual void Ins(Tinfo d)=0; virtual void del(int pos)=0; void print();
    };
    Class TQuele:public TList
    //очередь
    {
    Public:
    TQuele (){n=0;L=0;}
    TQuele (); void Ins(Tinfo d) {реализация метода} void del(int pos=0) {реализация метода};
    }; class TStek:public TList
    { public:
    TStek (){n=0;L=0;}
    TStek (); void Ins(Tinfo d) {реализация метода}; void del(int pos) {реализация метода};
    }; main()
    {
    TList O;
    TList *a[3];
    a[1]=new TQuele(); a[1]->Ins(10); a[1]->Ins(11); a[2]=new TStek(); a[2]->Ins(10); a[2]->Ins(11);
    }
    10 Шаблонные классы
    Параметризованный класс, тип данных в класс передается как параметр.
    Определение шаблонного класса
    template
    class Имя
    {
    T info;// поле типа Т
    T Имя метода(T x); //функция типа Т и параметр типа Т
    } где
    - параметр класса – тип.
    Объявление экземпляров шаблонного класса
    Типы классу передаются при создании экземпляра (объявлении переменной типа класс). Объявление связывает тип с экземпляром класса.
    Имя класса <тип> имя экземпляра;
    Пример – шаблон - массива, конструктор с одним параметром
    #include using namespace std; template class massiv
    { private:
    T *x; int n; public: massiv(){n=0;x=0;} massiv(int n1){n=n1;x=new T[n];}
    T* getx(); void set_x(int n1, T* x);
    };
    template
    T* massiv::getx()
    { return x;
    } template void massiv::set_x(int n1, T* x1)
    {int i; if(n && (n==n1))
    { for(i=0; i}
    } int _tmain(int argc, _TCHAR* argv[])
    { massiv a(3); int y[3]={1, 2, 3}; a.set_x(3,y); int*z=a.getx(); int i; for (i=0;i<3;i++) cout< b(3); float m[3]={1.1, 2.2, 3.3}; b.set_x(3,m); float*z1=b.getx(); for (i=0;i<3;i++) cout<}
    Пример шаблон - класс- массив, конструктор с несколькоми параметрами
    #include using namespace std;
    template
    class A
    {
    private:
    T1 a;
    T2 b; public:
    A(){a=0;b=10;}
    T2 getb();
    T1 geta();
    }; template
    T2 A::getb()
    { return b;
    } template
    T1 A::geta()
    { return a;
    } int main()
    {
    A O1; cout<}
    Определение методов шаблонного класса
    Реализуются вне класса, как шаблонные функции с параметром класса template void massiv::set_x(int n1, T* x1)
    { int i; if(n && (n==n1))
    { for(i=0; i}
    }
    Использование шаблона

    Все ссылки на класс, как тип данных, должны включать тип параметра в <имя типа>. void massiv::Metod(int n, massiv &x){} massiv a; massiv B; massiv D;
    Пример реализация перегрузки операций для шаблона.
    #include
    using namespace std; template class massiv
    { private: int n;
    T *x; public: massiv(
    int n1){x=
    new
    T[n1]; n=n1;} massiv(){x=0; n=0;} massiv(
    const massiv &O); int getN(); void operator
    +(massiv &O1)
    { for
    (
    int i=0; i} void operator -(int a);
    T& operator
    [](
    int i); void operator *(int a); void inp(); massiv& operator
    =(
    const massiv &O)
    { if
    (&O==
    this
    ) return *this; if
    (x) delete
    []x; if
    (O.n)
    {
    n=O.n; x=
    new
    T[n]; for
    (
    int i=0;i}else
    { x=0;n=0;
    } return *this;
    }
    }; template void massiv::inp()
    { if
    (n)
    { for
    (
    int i=0;i>x[i];
    } else cerr<<"No Object create";
    } template
    T& massiv::
    operator
    [](
    int i)
    { if
    (i<0 || i>=n) cerr<<
    "Oshibka"
    ; return
    *(x+i);
    } template int massiv::getN()
    { return n;
    } template massiv::massiv(
    const massiv &O)
    {

    *
    this
    =massiv(O.n); for
    (
    int i=0;i} template void massiv::
    operator
    -(
    int a)
    //из объекта вычисляется число, объект при вызове слева
    { for
    (
    int i=0; i} template massiv& operator
    *(T a, massiv &O)
    //внешняя, так как мы хотим использовать константу и перед объектом 2*О
    { massiv O1(O.getN()); for
    (
    int i=0;i(O[i])=((O[i]))*a; return O;
    } template void massiv::
    operator
    *(
    int a)
    // объект при вызове слева О*2
    { for
    (
    int i=0; i}
    /*massiv operator +(massiv &O1,massiv &O2)
    { massiv O(O1.n); for (int i=0; iO.x[i]=O1.x[i]+O2.x[i]; return O;
    }*/ template ostream& operator
    <<(ostream &os,massiv &d)
    //внешняя
    { os<<"Перегрузка <<";
    for
    (
    int i=0;i} template istream& operator
    >>(istream &is,massiv &O)
    //внешняя
    { for
    (
    int i=0;i>O[i]; return is;
    Контейнерные_классы_11.1_Определение'>11 Контейнерные классы
    11.1
    Определение
    Конейнер - объект, назначением которого является хранение объектов других типов и управление ими. Контейнер представляет определение некоторой структуры данных, которая реализуется как шаблонный класс.
    Классическим примером контейнеров являются списки, векторы, массивы.
    Иногда содержимое контейнеров называют
    последовательностями.
    Контейнерные классы – распостраненный прием разработки классов, использующих механизм композиции и наполнения для подключения некоторых объектов к управляющему объекту – контейнеру.
    Контейнерный класс содержит в своем определении несколько объектных полей или указателей на объекты.
    Если контейнерный класс использует метод композиции, то тип и количество управляемых объектов фиксированы.
    Если используется метод наполнения то подключение реализуется через указатель, следовательно контейнер может управлять как объектами некоторого базового типа, так и объектами наследниками этого класса.
    Так как контейнер представляет объект управления некоторой структурой объектов, то основной операцией контейнера является последовательная обработка объектов (доступ к объектам в cтруктуре). Такая обработка обеспечивается двумя способами:

    Первый базируется на специальной процедуре просмотра всех элементов контейнера. В эту функцию передается функция, реализующая алгоритм требуемой обработки элемента контейнера.
    Второй реализуется через определение итератора или класса итераторов, подходящего для данного вида контейнера. При помощи итератора может управлять контейнером, не зная фактических типов, используемых для идентификации элементов.
    Итератор должен обеспечить возможность реализации циклических действий вида
    Цикл Пока очередной элемент определен
    Выполнить обработку элемента
    Перейти к следующему элементу
    Конец Пока
    Поэтому итератор состоит из трех частей:
    • - метод позволяющий выполнить обработку с первого элемента
    • - метод, организующий переход к следующему элементу
    • - метод, позволяющий проверить окончание данных.
    Доступ к очередной порции данных при этом осуществляется через специальный указатель текущей порции данных (указатель на объект класса- элемента).
    11.2
    Библиотека шаблонов STL
    Это набор шаблонных классов и функций, реализующих многие популярные структуры данных и алгоритмы. Т.к. STL состоит из шаблонных классов и функций, то структуры данных и алгоритмы могут применяться к любым типам данных – в этом мощь STL.
    STL поддерживается: контейнерами, алгоритмами. Алгоритмы применяются к контейнерам через итераторы, а так же через другие стандартные элементы: аллокатор, функциональные объекты, привязки и отрицатели.
    Контейнер – это объект, который содержит другие объекты. (массив объектов).
    11.3
    Виды контейнеров
    Последовательные – реализуют последовательности значений – линейные структуры.
    Ассоциативные – таблицы, обеспечивающие эффективное извлечение значений на основе ключей. Объекты контейнера хранят пару: ключ-значение.

    11.4
    Алгоритмы
    Применяются к контейнерам: инициализация, поиск в К, сортировка в К, слияние К-ов, изменение содержимого контейнера.
    Не модифицирующие операции над последовательностями: кол-во элементов в контейнере (последовательности); количество элементов, удовлетворяющих условию; поиск подпоследовательности в последователности, первое вхождение элемента, применение алгоритма к диапазону значений (for …each).
    Модифицирующие операции над последовательностями:
    • Копировать последовательность – copy
    • Копирует наоборот – copy_backward
    • Заполнение части последовательности –fiel
    • Присваивание элементам последовательности генерируемое функцией значение – generate
    • Меняет местами элементы, указанные итераторами – iter_swap
    • Упорядочение последовательности расставляя элементы так: сначала все элементы для которых предикат ИСТИНА, а затем те, для которых ЛОЖЬ -partition.
    • И многие другие.
    Операции сортировки и необходимые ей алгоритмы: бинарный поиск; диапазон, в который элемент может быть вставлен без нарушения порядка следования элементов; входит ли одна последовательность в другую; сортировка диапазона; минимальное и максимальное двух значений; итератор на максимальный в последовательности.
    11.5
    Итераторы
    Итератор – объект, который играет «как бы » роль указателя на элемент контейнера. Позволяют перемещаться по элементам контейнера.
    5 типов итераторов:
    Произвольного доступа – сохраняет и извлекает элементы в произвольном порядке: BiIter.
    Двунаправленного доступа - сохраняет и извлекает элементы допускает перемещение вперед и назад. ForIter.
    Прямой - сохраняет и извлекает элементы, перемещение вперед.
    InIter.
    Входной – извлекает (но не сохраняет) значения, перемещение вперед. OutInter.

    Выходной – сохраняет, но не извлекает значения, перемещение вперед. RanIter.
    Итератор с большими возможностями можно применять вместо итератора с меньшими возможностями.
    Для итераторов поддерживаются операции с указателями, допустимыми для категории итератора:
    Так, входной итератор должен поддерживать операции: ->, ++, *, ==, !=
    Для выходного итератора и произвольного доступа: ->, ++, *, ==, !=, --,
    <, .>,>=, <=, +=, []
    11.6
    Аллокатор
    Аллокатор – объект, который выделяет контейнеру память. Для каждого контейнера STL создан собственный аллокатор. Можно определять свои аллокаторы, если это нужно специализированному приложению.
    11.7
    Функциональные объекты
    Функциональные объекты – это экземпляры классов, определяющих operator(). В STL определены Ф.О.: less() – больше ли один объект другого;plus(); minus(); multiplies(); divides().
    11.8
    Общая функциональность контейнера

    Поддержка присваивания

    Поддерживать операции сравнения

    Должны иметь конструктор по умолчанию (создание пустого контейнера) и копирующий конструктор.

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

    Должен предоставлять итераторы. Это гарантирует, что ко всем контейнерам можно применять алгоритмы.

    Все контейнера должны предоставлять функции: iterator begin() – итератор на 1 элемент const iterator begin() - константный итератор на 1 элемент iterator end() - итератор на последний элемент const iterator end() – size_type max_size() const - максимально возможное количество элементов size_type size() const – количество элементов в контейнере void swap (тип контейнера С) – обмен двух контейнеров

    Обратный итератор – это итератор, поддерживающий двунаправленный доступ .
    Содержит: revers_iterator rbegin() – на последний элемент revers_iterator rend() – на позицию, предшествующую первому элементу.
    11.9
    Функции последовательных контейнеров:
    void clear() –удаление элементов из контейнера iterator erase(iterator i) – удаление элемента в позиции i. iterator erase(iterator start, iterator end) - удаление элементов от start до end iterator insert(iterator I, const T&val) – вставляет val в позицию I контейнера.
    И др.функции.
    11.10
    Функции ассоциативных контейнеров
    void clear() pair equal_range(const key_type &K) – два итератора указывают const на диапазон контейнера, содержащий значение ключа К. iterator finde(const key_type &K) – возвращает итератор на ключ К.
    Если не найден, то на конец контейнера. iterator insert(const key_type &K) – key_compare key_comp() const – возвращает функциональный объект, сравнивающий два ключа.
    Пример. Применение базовых операций к последовательному контейнеру на основе вектора (vector).
    Создать контейнер
    Добавить элемент в контейнер
    Определить размер контейнера
    Использовать итератор для прохода по контейнеру
    Присвоить один контейнер другому
    Определить эквивалентность двух контейнеров
    Удалить элементы из контейнера
    Менять элементы контейнера
    Проверить контейнер на пустоту
    #include
    "stdafx.h"
    #include

    #include
    using namespace std;
    void show(
    const char
    *msg, vector<
    char
    > vect){ vector<
    char
    >::iterator itr; cout<(itr=vect.begin();itr!=vect.end();++itr) cout<<*itr<<
    " "
    ; cout<<
    '\n'
    ;
    } int
    _tmain(
    int argc, _TCHAR* argv[])
    {
    //объявление пустого конт vector<
    char
    > v;
    //объявление итератора для vector vector<
    char
    >::iterator itr;
    //получить итератор на начало itr=v.begin();
    //вставка символов в v. результат - итератор на вставляемый объект itr=v.insert(itr,
    'A'
    ); itr=v.insert(itr,
    'B'
    ); v.insert(itr,
    'C'
    );
    //отобразить содержимое v show("Содержимое v:",v);
    //объявление обратного итератора vector<
    char
    >::reverse_iterator ritr;
    //отобразить v в обратном порядке, используя обратный итератор for
    (ritr=v.rbegin();ritr!=v.rend();++ritr) cout<<*ritr<<
    ' '
    ; cout<<
    "\n\n"
    ;
    //создать другой вектор, идентичный первому vector<
    char
    > v2(v); show("Содержимое v2:",v2); cout<<
    "\n\n"
    ;
    //размер v cout<<
    "размер v="
    <"\n\n"
    ;
    //сравнить два контейнера if
    (v==v2) cout<<
    "Эквивалентны"
    <<
    "\n\n"
    ;
    //вставит символы в конец контейнеров v и v2 v.insert(v.end(),
    'D'
    ); v2.insert(v2.end(),
    'E'
    ); v2.insert(v2.end(),
    'X'
    ); show("Содержимое v:",v);
    show("Содержимое v2:",v2);
    //сравнить v(v"\n\n"
    ;
    //вставим Z в начало v v.insert(v.begin(),
    'Z'
    ); show("Содержимое v:",v);
    //удалить первый элемент из v2 v2.erase(v2.begin()); show("Содержимое v2:",v2); cout<<
    "\n\n"
    ;
    //очистить v v.clear(); if
    (v.empty()) cout<<
    "Теперь пуст"
    <<
    "\n\n"
    ; cin.get(); cin.get(); return 0;
    }
    Пример разработки шаблона – контейнер множество. Предусмотрев операции:
    • включить элемент в множество
    • входит ли элемент в множество
    • возвращает элемент множества
    • размер множества
    • пусто ли множество
    • объединение двух множеств
    • пересечение двух множеств
    • дополнение двух множеств
    • вывод множества
    • заполнение множества
    • Тестирвание шаблона на типах: int, char, класс Book
    • Определение и реализация шаблонного класса в одном файле заголовка
    Мoдуль class_Set class Set
    { private:
    T *x; int n; public:
    Set(){n=0;x=0;}

    Set(
    int n1){n=n1;x=
    new
    T[n];}
    // in-line
    Set(){
    delete
    []x;} void push_back(T a);
    //включитьэлемент в множество bool in(T a);
    //входит ли элемент в множество
    T operator[](int i);
    //возвращает элемент int size(); bool
    Empty();
    //пусто ли мнжество
    //объединение двух множеств
    Set & union_m(Set &S1,Set &S2);
    //пересечение двух множеств
    Set &intersect(Set &S1,Set &S2);
    //дополнение множества
    Set & acsept(Set &S1,Set &S2);
    //friend ostream& operator<<(ostream &os,Set &O); void
    Realloc(); friend ostream& operator
    <<(ostream &os,Set &O)
    { for
    (
    int i=0;i' '
    ; os<}
    };
    #include
    "stdafx.h"
    #pragma once
    #include
    using namespace std; template class Set
    { private:
    T *x; int n; public:
    Set(){n=0;x=0;}
    Set(
    int n1){n=n1;x=
    new
    T[n];}
    // in-line
    Set(){
    delete
    []x;} void push_back(T a);
    //включитьэлемент в множество bool in(T a);
    //входит ли элемент в множество
    bool
    Empty();
    //пусто ли мнжество
    //объединение двух множеств
    Set & union_m(Set &S1,Set &S2);
    //пересечение двух множеств
    Set &intersect(Set &S1,Set &S2);
    //дополнение множествак
    Set & acsept(Set &S1,Set &S2); friend ostream& operator
    <<(ostream &os,Set &O)
    { for
    (
    int i=0;i' '
    ; os<}
    };
    //включитьэлемент в множество template void
    Set::push_back(T a){ if
    (n==0) {x=
    new
    T[1];x[n]=a;n++;} else{ if
    (!(
    this
    ->in(a))) x=(T*) realloc(x, sizeof
    (T)*(n+1)); x[n]=a;n++;
    }
    }
    //пусто ли мнжество template bool
    Set::Empty()
    { return x==0;
    }
    //входит ли элемент в множество template bool
    Set::in(T a)
    { int i=0; while
    (i<
    this
    ->n && x[i]!=a)

    { i++;
    } return
    (i<
    this
    ->n);
    }
    //объединение двух множеств template
    Set & Set::union_m(Set &S1,Set &S2)
    { int i; n=S1.n; this
    ->x=
    new
    T[n]; for
    (i=0;i(i=0;i(!(
    this
    ->in(S2.x[i]))) this
    ->push_back(S2.x[i]); return *this;
    }
    //пересечение двух множеств template
    Set& Set::intersect(Set &S1,Set &S2)
    { int i,j; for
    (i=0;i{
    for
    (j=0;j{
    if
    ((S1.in(S2.x[j]))&&(!(
    this
    ->in(S1.x[j])))) this
    ->push_back(S2.x[j]);
    }} return *this;
    }
    //дополнение множествак template
    Set& Set::acsept(Set &S1,Set &S2)
    { int i,j;
    for
    (i=0;i{ for
    (j=0;j{ if
    (!(S2.in(S1.x[i])) &&(!(
    this
    -
    >in(S1.x[i])))) this
    ->push_back(S1.x[i]);
    }
    } return *this;
    }
    Модуль Book.h
    #pragma once
    #include

    using namespace std; class
    Book
    {private: string ISBN;
    //ключ string author; string Title; unsigned int year_published; string pablished; public:
    Book(void){ISBN="";author="";Title="";year_published=0;pablished="";}
    Book(string ISBN1,string aut, string T, unsigned int year, string pub); bool operator
    !=(Book &B); friend ostream& operator
    <<(ostream &os,Book &O); friend istream& operator
    >>(istream &is,Book &O);
    };
    Модуль Book.cpp
    #include
    "StdAfx.h"

    #include
    "Book.h"
    Book::Book(string ISBN1,string aut,string T,
    unsigned int year,string pub)
    {
    ISBN=ISBN1;author=aut;Title=T;year_published= year; pablished=pub;
    } bool
    Book::
    operator
    !=(Book &B)
    { return
    (ISBN!=B.ISBN);
    } ostream& operator
    <<(ostream &os,Book O)
    { os<'
    '
    <'
    '
    <'
    '
    <' '
    <} istream& operator
    >>(istream &is,Book &O)
    { is>>O.ISBN; is>>O.author; is>>O.Title; is>>O.year_published; is>>O.pablished; return is;
    }
    Основная прграмма
    // MySet_template.cpp: определяет точку входа для консольного приложения.
    //
    #include
    "stdafx.h"
    #include
    "class_set.h"
    #include
    "Book.h"
    #include

    void find_glasn(); int
    _tmain(
    int argc, _TCHAR* argv[])
    {

    Set<
    int
    > S;
    S.push_back(2);
    S.push_back(3);
    S.push_back(4);
    Set<
    int
    > S1;
    S1.push_back(2);
    S1.push_back(5);
    S1.push_back(4);
    Set<
    int
    > S2;
    //S2.union_m(S,S1);
    //S2.intersect(S,S1);
    S2.acsept(S,S1); cout<Set SB;
    Book B1("111","Shild","C++",2017,"Dialog");
    Book B2("110","Shild","C#",2017,"Dialog");
    SB.push_back(B1);
    SB.push_back(B2); cout<} void find_glasn()
    {
    //множество гласных букв string s=
    "аеиоуэюя"
    ;
    Set<
    char
    > glasnAll, glasnWord, S3; for
    (
    int i=0;i<
    int
    (s.size());i++) glasnAll.push_back(s[i]);
    //множество гласных букв слова Програмирование s="Программирование"; int n=s.size(); for
    (
    int i=0;i{ char x=s[i]; if
    (glasnAll.in(x))
    glasnWord.push_back(x);
    }
    //множество гласных,котрых нет в слове
    S3.acsept(glasnAll,glasnWord); s.erase();
    //формирование строки гласных for
    (
    int i=0;i<
    int
    (S3.size());i++)
    { char x=S3[i]; s=s+x;
    } cout<}
    11.11
    1   ...   5   6   7   8   9   10   11   12   ...   15


    написать администратору сайта