Пятница, 2025-06-20, 7:07 PM
Приветствую Вас Гость | RSS
Главная | Статические переменные | Регистрация | Вход
Меню сайта
Вход на сайт
Поиск
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Программирование

    Статические переменные. Шаблоны функций и классов. Связные списки C++

     

    Статические переменные-члены и статические функции-члены.

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

     

    #include<iostream.h>
    class Cat
    {
    public:
    Cat(int age):itsAge(age){HayMenyCats++;}
    virtual ~Cat(){HayMenyCats--;}
    virtual int GetAge() {return itsAge;}
    virtual void SetAge(int age){itsAge=age;}
    static int HayMenyCats;
    private:
    int itsAge;
    };
    int Cat::HayMenyCats =0;

    int main(void)
    {
              const int MaxCat=5;
              int i;
              Cat *CatHouse[MaxCat];
              for(i=0;i<MaxCat;i++)
              CatHouse[i]=new Cat(Maxcat-i);
              for(i=0;i<MaxCat;i++)
                         {
                         cout<<"сейчас у нас ";
                         cout<<Cat::HayMenyCats;
                         cout<<" кота.\n";
    cout<<"удалим кота, возраст которого ";
    cout<<CatHouse[i]->GetAge()<<" года \n";
                         delete CatHouse[i];
                         CatHouse[i]=0;
                         }
    return 0;
    }

     

    у нас  живёт 4 кота .
    удалим кота, возраст которого 4 года
    у нас  живёт 3 кота .
    удалим кота, возраст которого 3 года
    у нас  живёт 2 кота .
    удалим кота, возраст которого 2 года
    у нас  живёт 1 кота .
    удалим кота, возраст которого 1 года

    Рекомендуется:

    • Применять статические переменные для совместного использования данных несколькими объектами класса.
    • Необходимо ограничить доступ к статическим ,объявив их private или protected.
    • Не используйте статические данные для хранения данных одного объекта. Эти переменные предназначены для обмены данными между объектами класса.

    Статические функции-члены подобны статическим переменныи-членам.  Их можно вызвать, в отличии от других функций-членов, тогда. Когда нет ни одного объекта данного класса.

    #include<iostream.h>
    class Cat
    {
    public:
    Cat(int age) :itsAge(age) {HayMenyCats++;}
    virtual ~Cat(){HayMenyCats--;}
    virtual int GetAge() {return itsAge;}
    virtual void SetAge(int age) {itsAge=age;}
    static int GetHayMeny() 
    { return HayMenyCats;}
    private:
    int itsAge;
    static int HayMenyCats;
    };
    void Info();

    int Cat::HayMenyCats =0;

    int main(void)
    {
              const int MaxCat=4;
              int i;
              Cat *CatHouse[MaxCat];
              for(i=0;i<MaxCat;i++)
              {
              CatHouse[i]=new Cat(MaxCat-i);
              Info();
    cout<<CatHouse[i]->GetAge()<<" года\n";
              }
              for(i=0;i<MaxCat;i++)
    {          cout<<"удаляем старшего кота \n"<<endl;
              delete CatHouse[i];
              CatHouse[i]=0;
              Info();
              }
    return 0;
    }
    void Info()
    {
              cout<< "у нас  живёт "<< Cat::GetHayMeny()<<" кота .\n";

    }

    Вызов статических функций может быть двух видов:

    • Cat::GetHayMeny() — без определения объекта, но с указанием класса.
    • TheCat. GetHayMeny() —с определением объекта, и без указания класса.

    Статические функции-члены не содержат указателя this. Поэтому они не могут использовать обычные нестатические переменные-члены, так как доступ к ним осуществляется через указатель this.

     

    Шаблоны функций и классов

    Шаблоны представляют ещё одну реализацию полиморфизма в программах С++. Они позволяют создать универсальный фрагмент кода, а затем использовать его многократно с различными типами данных или различными объектами. С помощью шаблонов можно уменьшить объём и сложность программы.

    Шаблоны функций позволяют передавать в качестве аргумента тип переменной. Шаблоны создают семейства функций, определяющее неограниченное множество родственных функций. Экземпляризация— операция создания определённого типа из шаблона. Отдельные классы называются экземплярами шаблона. Параметризованные шаблоны — представляют возможность создания общего класса  и для построения конкретных экземпляров передают этому классу в качестве параметров типы данных.

    На пример список. Список может быть для чего угодно.

    Построение шаблонов рассмотрим на примере. Необходимо написать функцию расчёта куба для аргумента. (Cub()).

    #include<iostream.h>
    #include<math.h>

    template <class T>
       T cub(T x)
       {          return x*x*x;}
    template <class SwapType>
    void Swap(SwapType &x,SwapType &y)
    { SwapType tmp;
       tmp=x;
       x=y;
       y=tmp;
    }
    template <class T1,class T2>
    T1 max(T1 x,T2 y)
    {
    if(x>y)return x;
    else return y;
    }
    void main(void)
    {
       int i=3;
       float f=3.12;
       double x=3.1e2;
       cout<<"//целое "<<cub(i)<<endl;
       cout<<"//вещественное "<<cub(f)<<endl;
       cout<<"//двойной точности "<<cub(x)<<endl;
       char ch1='a',ch2='z';
       cout<<"//1-- "<<ch1<<"  2-- "<<ch2<<endl;
       Swap(ch1,ch2); cout<<"//переставили "<<endl;
       cout<<"//1-- "<<ch1<<"  2-- "<<ch2<<endl;
       int c1=0,c2=9;
       cout<<"//1-- "<<c1<<"  2-- "<<c2<<endl;
       Swap(c1,c2); cout<<"//переставили "<<endl;
       cout<<"//1-- "<<c1<<"  2-- "<<c2<<endl;

       cout<<"//max из  int "<<c1<<" и int "<<c2<<" = "<<max(c1,c2)<<endl;
       cout<<"//max из  char "<<ch1<<" и char "<<ch2<<" = "<<max(ch1,ch2)<<endl;
       cout<<"//max из  int "<<i<<" и float "<<f<<" = "<<max(f,i)<<endl;
    }


    //целое 27
    //вещественное 30.3713
    //двойной точности 2.9791e+07
    //1-- a  2-- z
    //переставили
    //1-- z  2-- a
    //1-- 0  2-- 9
    //переставили
    //1-- 9  2-- 0
    //max из  int 9 и int 0 = 9
    //max из  char z и char a = z
    //max из  int 3 и float 3.12 = 3.12

     

    Шаблоны классов

    Шаблон класса представляет собой  скелет обобщённого класса. Ситаксис такой:

    Template< список_аргументов_шаблона>

                //тело класса
    };

    Каждый аргумент в списке является либо объявлением типа float a; либо идентификатором класса class T. Из-за этого определение функции-метода шаблонного класса имеет вид:
    Template< список_аргументов_шаблона>
    Тип_результата имя_класса < список_аргументов_шаблона>::
    Имя_функции( список_аргументов_функции)
    {
    //тело функции.
    }

    объявление объекта шаблонногокласса:
    имя_класса_шаблона < список_аргументов_шаблона> имя_объекта;
    Пример использования шаблонов будем рассматривать на создании очереди.

     

    Связные списки и другие структуры

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

    Существуют три основных вида списков:

    • Однонаправленные списки  (очередь, стек);
    • Двунаправленные списки (дек и т.д.);
    • Деревья.

    Названия образуются от количества связующих список указателей в каждом объекте списка.

    Список состоит из узлов, узлы представляют собой абстрактные классы. Начало — это начало обработки промежуточных узлов списка, которые отвечают за хранение данных, указатель узла - “хвост” обязательно имеет значение null (0).

    // программа работы с динамическими списками при помощи классов.
    // однонаправленные списки, двунаправленные списки и деревья.

    #include <iostream.h>
    #include <iomanip.h>
    #include <fstream.h>
    ofstream fout("rez.txt");
    ifstream fin("rez.txt");

    class Data
    {
    public:
                Data ();
                ~Data(){delete fam;}
                int Compare(const Data &);
                void Show();
    private:
                char fam[25];
                float ball;
    };
    Data::Data()
    {
    cout<<"\n Введите фамилию и средний балл :";
                cin>>fam>>ball;
    }
    void Data::Show()
    {          cout.width(25);
                cout.fill(' ');
                cout<<fam;
                cout.width(10);
                cout.fill('-');
                cout.precision(3);
                cout<<ball<<"\n";
                fout.width(25);
                fout.fill(' ');
                fout<<fam;
                fout.width(10);
                fout.fill('-');
                fout.precision(3);
                fout<<ball<<"\n";
                //fout<<fam<<"--"<<ball<<endl;
    }
    int Data::Compare(const Data &theO)
    {
    if(strcmp(fam,theO.fam)<0)return -1;
    if(strcmp(fam,theO.fam)==0)return 0;
    if(strcmp(fam,theO.fam)>0)return 1;
    }
    class Node;
    class HeadNode;
    class TailNode;
    class InternalNode;

    class Node
    {public:

                Node(){}
                virtual ~Node(){}
    virtual Node* Insert(Data* theData)=0;
                virtual void Show()=0;
    private:
    };
    class InternalNode:public Node
    {public:
    InternalNode(Data *theData, Node *next) ;
    ~InternalNode(){delete myNext,delete myData;}
    virtual Node* Insert(Data *theData);
    virtual void Show() {myData->Show();myNext->Show();}
    private:
                Data* myData;
                Node* myNext;
    };
    InternalNode::InternalNode(Data *theData,Node*next):
    myData(theData),myNext(next)
    {}
    Node* InternalNode ::Insert(Data *theData)
    {
    int result=myData->Compare(*theData);
    switch(result)
    {
    case  0:
    case1:{InternalNode *dataN=new InternalNode (theData,this);
                return dataN;}
    case-1:{myNext=myNext>Insert(theData);
                return this;}
                            }
                return this;
    }
    class TailNode:public Node
    {
    public:
                TailNode(){}
                ~TailNode() {}
                virtual Node* Insert(Data *theData);
                virtual void Show(){ }
    private:
    };
    Node* TailNode::Insert(Data *theData)
    {
    InternalNode *dataN=new InternalNode (theData,this);
                return dataN;
    }
    class HeadNode:public Node
    {public:
    HeadNode(){myNext=new TailNode;};
    ~HeadNode(){delete myNext;}
    virtual Node* Insert(Data *theData);
    virtual void HeadNode::Show();
    private:
                Node* myNext;
    };
    void HeadNode::Show()
    {
    cout<<"        Фамилия         "<<"   балл  "<<endl;
    fout<<"        Фамилия         "<<"   балл  "<<endl;
                myNext->Show();
                }
    Node* HeadNode::Insert(Data *theData)
    {
                myNext=myNext>Insert(theData);
                return this;
    }

    class Admin
    {public:
                Admin();
                ~Admin(){delete myHead;}
                void Insert(Data* pData);
    void ShowAll(){myHead->Show();}
    private:
                HeadNode* myHead;
    };
    Admin::Admin()
    {
                myHead=new HeadNode;
    }
    void Admin:: Insert(Data*pData)
    {
                myHead->Insert(pData);
    }
    int main()
    {
                Data* pData;
                int val=1;
                Admin ll;
                while(val!=0)
                {
                            pData=new Data();
                            
                            ll.Insert(pData);
    cout<<"хотите закончить ввод? Если да, то введите 0";
                            cin >>val;
                }
                ll.ShowAll();
    cout<<"********************************\n";
                fout.close();
                return 0;
    }

    uCozCopyright MyCorp © 2025