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

  • 5.8.5 Методы класса Это статические методы. 5.8.5.1 Статические методы

  • 5.9.1 Виды конструкторов 1.

  • 5.9.2 Правила по применению конструктора

  • Создание и инициализация объектов (экземпляров класса)

  • Применение методов к объектам Формат применения метода к объекту Имя объекта .

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


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

    const
    {
    тело функции
    }
    Спецификатор const нужно указывать как в объявлении, так и в определении постоянной функции - члена.
    Такая функция может быть вызвана для объектов и константных
    объектов, вызов не константных функций для константных объектов приведет к ошибке. class
    CNode
    {
    int data;
    CNode *next; public:
    CNode (
    int d){ data=d; next=0;} void insert_after(CNode *q); int get_data() const {return data
    ;}
    CNode *get_next();
    }; int main(
    int argc, _TCHAR* argv[])
    {
    CNode l(0);
    CNode a(2),b(3),c(4); a.insert_after(&b); b.insert_after(&c); l=a.get_next();cout<(l)
    { cout<get_data(); l=l->get_next();
    }
    //константный объект и константный метод const
    CNode A(2); cout<//выполняется cout<//выполняется
    cout<
    //ошибка к константному объекту нельзя
    //применять не константный метод return 0;
    }
    5.8.4.4 Дружественные функции
    Методы класса используются для реализации свойств объекта. В виде дружественных функции оформляются действия, не представляющие свойства класса, но концептуально входящие в состав класса и нуждающиеся в доступе к его скрытым полям, например, переопределение операции вывода объекта в поток вывода.
    Правила использования и реализации:

    Объявляется внутри функции (только прототип).
    friend тип функции Имя (список параметров);


    В качестве параметра ей должен передаваться объект, ссылка или указатель на объект, так как указатель this ей не доступен.

    Дружественная функция может быть внешней функцией или методом другого класса.

    Определение дружественной функции осуществляется вне класса, действие спецификатора доступа на нее не распространяется. сlass B{ private: float d; public:
    B(){d=4;} friend float f(B &O); friend float Add(B &O); //ff – метод касса B
    }; float f(B &O)
    { return d*2;
    } float A::Add(B &O){……}
    Применение дружественных функций
    1)
    Одну функцию надо сделать доступной двум классам.
    Например, имеется класс Линейный однонаправленный список и
    Очередь. Надо реализовать операцию проверки для Линейного списка, входит ли элемент очереди в список, и так же: входит ли элемент очереди в список. class Quele; class List; int find(const List L, const Quele Q)
    {
    Tnode *q=L->L;
    While(q)
    {
    While(!Q->Empty())
    { if(q->getX()==Q->getx())return 1;
    Q.pop();
    } q=q->next;

    }return 0;
    }
    Можно эту функцию сделать членами обеих классов, но тогда работа приложения будет не эффективной так как, доступ к значению элементов – функции-члены get, используемые в функции, должны выполнять контроль на существование элемента, включенного в проверку.
    Нельзя сделать одну функцию членами двух различных классов. Но язык
    С++ предоставляет механизм включения одной внешней функции в различные классы, причем эта функция получает доступ к закрытым и открытым членам класса – эта функция в классе оформляется как друг. class List
    {protected: struct Tnode
    { int x;
    Tnode *next;
    };
    Tnode *L; public:
    List(){L=0;cout<<"****";} void Insert(int x); int getX(Tnode &q);
    Tnode * get_List(); friend find(const List &L,const Quele &Q);
    }; class Quele
    {
    ………………….
    Tnode *Q; friend find(const List &L,const Quele &Q);
    …………………
    }
    //реализация дружественной функции int find(const List L, const Quele Q)
    {
    Tnode *q=L->L;
    While(q)

    {
    While(!Q->Empty())
    { if(q->getX()==Q->getx())return 1;
    Q->pop();
    } q=q->next;
    }return 0;
    }
    2)
    При реализации перегрузки операций.
    Если функция-член одного класса должна использоваться в другом классе, т.е. функция член одного класса должна использоваться в другом классе. class List
    {
    Tnode *L; public: void output();}; void List::output()
    {
    Tnode *q=L; while(q)
    { cout<x; q=q->next;
    }
    } class Quele
    {
    ………………….
    Tnode *L; friend void List::output();
    }
    Пример реализации классов: include
    "iostream"
    #include

    using namespace std; class student
    { private: char fam[20]; char group[10]; unsigned short year_zach; char shifr_napravlenia[6]; char shifr_profiliy[6]; char vp_kafedra[40]; public:
    //конструктор без параметров student()
    { strcpy(fam,
    ""
    );strcpy(group,
    ""
    );strcpy(vp_kafedra,
    ""
    ); year_zach=0;strcpy(shifr_napravlenia,
    ""
    );strcpy(shifr_profiliy,
    ""
    );
    }
    //конструктор параметрами student(
    char
    *f, char
    *g, unsigned short y, char
    * sh_n, char
    * sh_p, char
    *vk)
    { strcpy(fam,f);strcpy(group,g);strcpy(vp_kafedra,vk); year_zach=y;strcpy(shifr_napravlenia,sh_n); strcpy(shifr_profiliy,sh_p);
    }
    //деструктор

    student(){cout<<
    "delete object"
    <//методы модификации void set_fam(
    const char
    *f){ strcpy(fam,f);} void set_group(
    const char
    *g){ strcpy(group,g);} void set_year_zach(
    unsigned short y){ year_zach=y;} void set_shifr_napravlenia(
    char
    *sh_n){ strcpy(shifr_napravlenia,sh_n);} void set_shifr_profiliy(
    char
    * sh_p){ strcpy(shifr_profiliy,sh_p);} void set_vp_kafedra(
    const char
    *vk){ strcpy(vp_kafedra,vk);} const char
    * get_fam(){ return fam;} const char
    *get_group(){ return group;} unsigned short get_year_zach(){ return year_zach;} char
    * get_shifr_napravlenia(){ return shifr_napravlenia;}
    char
    * get_shifr_profiliy(){ return shifr_profiliy;} const char
    * get_vp_kafedra(){ return vp_kafedra;}
    //операции с данными объекта
    //вернуть год поступления, шифр направления, шифр профиля, название выпускающей кафедры по фамилии void fined1(
    const char
    *f, char
    * sh_n,
    char
    * sh_p, char
    *vk);
    //на каком курсе учится студент int kurs(); char
    * info()
    {
    }
    };
    #include
    "stdafx.h"
    #include
    "student.h"
    //реализация методов void student::fined1(
    const char
    *f, char
    * sh_n,
    char
    * sh_p, char
    *vk)
    { if
    (strcmp(fam,f)==0)
    { strcpy(sh_n,shifr_napravlenia); strcpy(sh_p,shifr_profiliy); strcpy(vk,vp_kafedra); return;
    } throw
    "Это не тот объект"
    ;
    } int student::kurs()
    { time_t t=time(NULL); tm *c=localtime(&t); int y=(c->tm_year+1900)-year_zach; return
    (y==0)?1:y;
    }
    5.8.5 Методы класса
    Это статические методы.

    5.8.5.1 Статические методы
    Методы тоже могут быть статическими.
    Объявление статического метода
    static загловок метода(){ ……}
    Правила применения статического метода
    1)
    В определении метода слово static не указывается.
    2)
    Метод, который обращается к статическому полю можно сделать статическим.
    3)
    Если метод статический, то к нему можно обращаться до того, как был создан хотя бы один экземпляр переменной.
    4)
    Статический метод не может обращаться к нестатическим полям класса.
    5)
    Статический метод просто не будет знать, к какому экземпляру обратиться – внутри него нет доступа до указателя this. Оператор this можно использовать только внутри нестатической функции-члена.
    6)
    Для использования статического метода, таким образом, не нужно создавать отдельного экземпляра класса, а обращение ведётся через имя класса и оператор ::.
    7)
    Статические поля и методы, также как и нестатические, могут иметь модификаторы доступа private, protected и public.
    8)
    Для доступа к статической переменной в методе, реализованном вне класса, используется имя: имя класса::имя поля.
    9)
    При использовании статических методов запрещён модификатор const метода, так как метод по определению не может обращаться к нестатическим полям и изменять их.
    Пример. Применение статического метода к статическому полю class
    Bank
    {
    //переменная для выделения каждому объекту своего номера счета
    //номер счета данного объекта int nAccountNumber;
    //текущий баланс double dBalance; protected: static int nNextAccountNumber; public:
    Bank()
    {
    //следующий номер счета nAccountNumber=++Bank1::nNextAccountNumber;

    Cleare();
    //вызывает другой метод
    } void
    Cleare()
    { dBalance=0.0;
    } static int get_nNextAccountNumber(); int get_nAccountNumber()
    { return nAccountNumber;
    }
    static
    int
    get_ nNextAccountNumber();
    };
    Файл сpp
    #include
    "StdAfx.h"
    #include
    "Bank1.h" int
    Bank1::nNextAccountNumber=0; int get_nNextAccountNumber()
    { return
    Bank::nNextAccountNumber;
    }
    5.9
    Конструкторы класса
    Это методы, обеспечивающие создание (инициализацию полей) экземпляров класса (объектов). Объект это переменная класса.
    В классе С++ может быть несколько конструкторов, т.к. для них допускается перегрузка.
    5.9.1 Виды конструкторов
    1.
    Конструктор по умолчанию.
    Если программист не включил в класс ни одного конструктора, то компилятор создаст его автоматически, и он будет вызывается автоматически при определении объекта. Этот метод инициализирует поля данных нулевыми значениями.

    Примечание. Если класс содержит константные и ссылочные поля, то при использовании конструктора по умолчанию возникнет ошибка, так как этот конструктор не умеет инициализировать такие поля.
    2.
    Явно определенный конструктор
    Это метод, который явно определен в классе и вызывается автоматически при объявлении экземпляра класса.
    Такой конструктор реализуется по формату функции, его имя – это имя
    класса, эта функция не имеет типа, даже void.
    Имя класса ([список параметров]){ тело конструктора
    }
    Виды явно определенных конструкторов:
    Без параметров – его называют конструктором по умолчанию.
    Формат объявления
    Имя класса() {тело конструктора}
    Пример объявления в классе явного конструктора, определенного вне класса сlass Droby
    { private: int a,b; public:
    Droby() ;
    //конструктор без параметров
    };
    Droby :: Droby() {a=0;b=1;} //реализация конструктора
    Пример определения конструктора в классе сlass Droby
    { private: int a,b; public:
    Droby() {a=0;b=1;} //реализация конструктора Droby() ;
    };

    С параметрами – создает объект и инициализирует члены данных значениями параметров. В классе может быть несколько перегруженных конструкторов с различным количеством параметров. Параметры могут быть любого типа, кроме типа этого класса.
    Формат объявления конструктора с параметрами
    Имя класса(список параметров);

    Пример объявления конструктора с параметрами сlass Droby
    { private: int a,b; public:
    Droby(int a1, int b1) ;
    //конструктор с параметрами
    };
    Droby :: Droby(int a1, int b1) {a=a1;b=b1;} //реализация конструктора
    Формат определения конструктора с параметрами внутри класса
    Имя класса(список параметров){ операторы инициализирующие поля класса значениями параметров}
    Пример определения конструктора с параметрами в классе сlass Droby
    { private: int a,b; public:
    Droby :: Droby(int a1, int b1) {a=a1;b=b1;}
    };
    3.
    Конструктор копирования
    Стандартный конструктор копирования, который осуществляет поэлементное копирование однотипных объектов. Вызывается при присваивании объектов одного типа.
    Не стандартный конструктор копирования (создается программистом) включается в класс, в котором есть динамически создаваемые члены данных.
    Такой конструктор имеет один параметр – ссылку на объект своего класса.
    Пример применения копирующего конструктора using namespace std; class massiv
    { private: int n; int
    *x; public: massiv(
    int n1){x=
    new int
    [n1]; n=n1;} massiv(){x=0; n=0;} massiv(
    const massiv &O);//копируюий конструктор int getN();
    void input(); void output(); void chenge();
    //применение копируюего конструктора void operator
    +(massiv &O1)
    { for
    (
    int i=0; i} void operator -(int a); void operator *(int a); friend massiv operator
    *(
    int a,massiv &O);
    //friend massiv operator +(massiv &O1,massiv &O2); friend ostream& operator
    <<(ostream &os,massiv &O);
    };
    5.9.2 Правила по применению конструктора
    Параметры конструкторов подчиняются тем же правилам о типах параметров, что и все остальные функции. Так как конструкторы различаются по типам своих параметров, транслятор способен правильно выбрать конструктор.
    Конструкторы нельзя определять с спецификатором: virtual, const, static.
    Конструктор глобального объекта вызывается до функции main.
    Локальные объекты создаются конструктором, как только становится активной область их действия.
    Конструктор вызывается автоматически при передаче объекта из функции (результат какой-то функции – тип класса).
    Конструкторы не наследуются.
    Пример конструкторы в классе Рациональное число
    #include "iostream" using namespace std; class Droby
    { private: int a,b; int Nod();
    //реализация вне класса
    public:
    Droby(int a1, int b1);
    //объявление конструктора с параметрами
    Droby(){a=0;b=1;}
    // с реализацией в классе void Add(Droby &d); void set_a(int a1){a=a1;} void set_b(int b1){b=b1;} int get_a(){return a;} int get_b(){return b;}
    Droby& Sub(Droby &d);
    };
    //реализация объявленных методов
    Droby::Droby(int a, int b)
    { this->a=a; this->b=b;int N=Nod();this->a= this->a/N; this->b= this->b/N;
    }
    5.10
    Создание и инициализация объектов (экземпляров класса)
    Экземпляр (или объект) - это переменная типа класс, созданная конструктором класса.
    Конструктор класса будет вызван (создаст объект) в следующих случаях: int main()
    {
    Droby R1;
    // вызов конструктора без параметров
    Droby R2(1,2),R3(2,3); вызов конструктора с параметрами
    }
    Экземпляр класса без конструктора может инициализироваться присваиванием ему другого объекта этого же класса. Это не запрещено и в том случае, когда конструкторы в классе определены. int main()
    {
    Droby R2(1,2),R3(2,3);
    Droby R4=R2;
    //инициализация присваиванием
    Droby *R5=new Droby(R4);
    }

    Алгоритм выполнения присваивания выглядит так, конструктор создает объект R4, а затем в него переписываются значения R2 (просто присваивание).
    Экземпляр (объект) это переменная данного класса. А класс – тип.
    Следовательно, переменной будет выделена память в объеме равном количеству байтов под все не статические переменные объекта – члены – данных.
    Пример для экземпляра D класса Droby будет выделено 8 байт – все переменные не статические int main(
    int argc, _TCHAR* argv[])
    {
    Droby D(2,3); cout<(Droby); return 0;
    }
    Пример для экземпляра класса Droby будет выделено 8 байт, для статической переменной z память в экземпляре не выделяется class A{
    static int z; private: int x,y;
    }; int _tmain(int argc, _TCHAR* argv[])
    {
    A O(); int a; std::cout<}
    5.11
    Деструктор класса
    Метод, обеспечивающий правильное удаление объектов.
    Деструктор по умолчанию. Присутствует неявно в каждом классе.
    Вызывается автоматически, когда объект выходит из области видимости.
    Видимость объектов определяется по правилам видимости локальных, глобальных, статических переменных.

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

    Имя класса ([список параметров]){тело деструктора}
    Может быть реализован в классе или вне класса
    Пример определение и вызов явно определенного деструктора для линейного динамического списка
    #include
    "iostream" using namespace std; class
    CNode
    { int data;
    CNode *next; public:
    CNode (
    int d){ data=d; next=0;}
    CNode(); void insert_after(CNode *q); int get_data()
    const
    ;
    CNode *get_next();
    };
    CNode::CNode()
    //деструктор класса CNode
    { cout<<
    "next"
    ; delete next;
    } int main(
    int argc, _TCHAR* argv[])
    {
    CNode list(0),*l(0);
    {
    CNode a(2),b(3),c(4);
    //область действия объектов
    }
    //завершение действия имен a b c и удаление этих объектов
    //вызов деструктора три раза return 0;
    }

    Результат программы
    Пример применения деструктора по умолчанию при выходе объекта из области видимости. Потеря объекта.
    Droby Droby::Sub(Droby &d)
    {
    Droby R;
    R.a= a*d.b-b*d.a;
    R.b=b*d.b; int N=R.Nod();
    R.a/=N;
    R.b/=N; return R;
    }
    Объект R представляет локальную переменную, которая по завершении метода будет удалена из памяти.
    5.12
    Применение методов к объектам
    Формат применения метода к объекту
    Имя объекта
    .
    Имя метода ([список параметров])
    Метод применяется к объекту, стоящему в вызове слева.
    Пример выполнения операций с рациональными дробями int main()
    {
    Droby R1;
    R1.set_a(5);
    //установить значение числителя объекта R1
    R1.set_b(6);
    //установить значение знаменателя объекта R1
    Droby R2(1,2),R3(2,3);
    R1.Add(R2);
    //к дроби R1 прибавить дробь R2 результат в R1
    Droby R=R1; cout<Droby R4=R.Sub(R3);
    //вычесть из R дробь R3
    //результат в R, а затем в R4
    }

    Пример реализации взаимодействия объектов
    Диаграмма классов
    Реализация
    #pragma once
    #include
    "Circle.h" class
    Menu
    { private:
    Circle C; public
    : static void outparametrs(
    int r);
    };
    #include
    "Menu.h"
    #include
    void
    Menu::outparametrs(
    int r){
    C.set_r(r); std::cout<<
    "Perimetr="
    <" Area Circle="
    <} class
    Circle
    {
    private
    : double r; static const double pi; public
    :
    Circle():r(0){};
    Circle(
    double r1); double
    S(); double
    P();
    };
    #include
    "Circle.h" const double
    Circle::pi=3.14;
    Circle::Circle(
    double r1)
    {
    r=r1;
    } double
    Circle::S()
    { return pi*r*r;
    } double
    Circle::P()
    { return
    2*pi*r;
    }
    #include
    "Menu.h" int
    _tmain(
    int argc, _TCHAR* argv[])
    {
    Menu::outparametrs(2); return
    0;
    }
    1   2   3   4   5   6   7   8   9   ...   15


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