1 / 134

Программирование

Программирование. Часть 6 . Основы ООП Динамические структуры данных. 5. Объектно-ориентированное программирование 5. 1 . Декомпозиция: divide et impera. Современные программные системы – сложные системы: они отражают сложность реального мира;

quinta
Download Presentation

Программирование

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Программирование Часть 6. Основы ООП Динамические структуры данных

  2. 5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera • Современные программные системы – сложные системы: • они отражают сложность реального мира; • процесс их разработки сложен (и слабо стандартизирован); • программа - дискретная система, а дискретные системы неустойчивы: маленькая ошибка приводит к значительным последствиям. • Общие свойства сложных систем: • Имеют внутреннюю структуру, то есть состоят изкомпонент - подсистем, которые, в свою очередь, тоже могут быть разбиты на подсистемы. • Внутренние связи подсистем сильнее связей между этими подсистемами. Это дает возможность по отдельности изучать каждую часть. • Состоят из ограниченного числа типов подсистем, скомбинированных и организованных различным образом. • Являются результатом эволюции более простых систем.

  3. 5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera • Рост сложности и объема ПО на примере ОС Windows (неофициальные данные): • Последствия ошибок: • Состоят из ограниченного числа типов подсистем, скомбинированных и организованных различным образом. • Являются результатом эволюции более простых систем.

  4. 5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera • Сложности разработки: • Служба Microsoft Consulting Services провела анализ результатов выполнения большого количества своих программных проектов. • Оказалось, что вероятность провала программных проектов довольно велика. • Только 24% проектов можно признать в той или иной степени успешными, • 26% не были завершены, • 50% столкнулись с большими проблемами, например, бюджет был превышен вдвое или затрачено в 1,5 раза больше времени.

  5. 5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera • Последствия маленьких ошибок – крах программной системы: • 1996 год. • Ошибка взятия целой части дробного числапри выходе числа с плавающей точкой за диапазон допустимых 16-битовых целых: • double x; • … • short i = x; • …Вместо: • double x; • … • if (abs (x) < 32 767) short i = x; • else …; • Результат:

  6. 5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera 4 июня 1996 года Взрыв ракеты-носителя Ariane 5 спустя 30 секунд после запуска.

  7. 5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera • Способ преодоления сложности – декомпозиция • При проектировании сложной программной системы необходимо разделять ее на все меньшие и меньшие подсистемы, каждую из которых можно совершенствовать независимо. • Построив модели ограниченного числа подсистем, можно, комбинируя их различным образом, строить множество гораздо более сложных систем. • Построив более простую модель, ее можно далее развивать, следуя за развитием системы. • В этом случае мы не превысим пропускную способность человеческого мозга: для понимания любого уровня системы необходимо держать в памяти информацию лишь о немногих частях системы.

  8. 5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera • Алгоритмическая декомпозиция • Основана на разделении алгоритмов по модулям системы. • Каждый модуль выполняет один из этапов общего процесса. • Реализуется средствами структурного программирования • Объектно-ориентированная декомпозиция • Мир представляется совокупностью автономно действующих объектов, моделирующих объекты реального мира. • Каждый объект обладает своим собственным поведением. • Послав объекту сообщение, можно попросить его выполнить присущее ему действие. • Объекты взаимодействуют друг с другом, моделируя поведение системы, соответствующее более высокому уровню. • Реализуется средствами объектно-ориентированного программирования.

  9. 5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera • Объектно-ориентированное программирование (ООП) – методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определенного класса, а классы могут образовывать иерархию наследования.

  10. 5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera • Иерархическое упорядочение задач или объектов – важный принцип управления сложностью проекта, лежащий в основе объектно-ориентированного подхода. •  Структурная иерархия строится по простому принципу разделения целого на составные части: Животное Голова Туловище Глаза Уши Рот Лапы Хвост … …

  11. 5. Объектно-ориентированное программирование 5.1. Декомпозиция: divide et impera • Объектная иерархия строится по принципу наследования свойств родительских (вышележащих) классов объектов дочерними (нижележащими) классами. • Родительские классы называют просто родителями (предками), дочерние – потомками • Птица, собака, волк – это типы животных, называемые классами. • Конкретная реализация того или иного класса, например, кот Матроскин, является объектом данного класса. Животное Птица Млекопитающее Собака Волк Воробей Кошка Орел … …

  12. 5. Объектно-ориентированное программирование 5.2. Три принципа ООП • Объект характеризуется: • совокупностью своих элементов (и их текущих значений • совокупностью допустимых для объекта действий • Объединение в едином объекте «материальных» составных частей (обрабатываемых данных), защищенных от внешних воздействий, и действий, манипулирующих этими частями (данными) называют инкапсуляцией. • Наследование – это такое отношение между объектами, когда дочерний объект повторяет элементы структуры и поведения родительского. •  Классы верхних уровней обычно не имеют конкретных экземпляров объектов. (Не существует конкретного живого организма, который назывался бы млекопитающее Бобик). Такие классы называют абстрактными. • Конкретные экземпляры объектов относятся, как правило, к классам самых нижних уровней объектной иерархии (собака Бобик, кот Матроскин). • Полиморфизм – это свойство различных объектов выполнять одно и то же действие (с одним и тем же названием) по-своему. • Родительские типы называют просто родителями (предками), дочерние – потомками

  13. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция • Инкапсуляция – механизм, связывающий воедино программный код и данные, которыми он манипулирует, а также обеспечивающий их защиту от внешнего вмешательства и неправильного использования. • Класс – определенный пользователем проблемно-ориентированный тип данных, описывающий внутреннюю структуру объектов, которые являются его экземплярами. • Объект (экземпляр класса) находится в таком же отношении к своему классу, в каком переменная находится по отношению к своему типу. • Данные и функции внутри класса называются членами класса. • Данные, входящие в класс, называются данными-членами или полями. • Функции, принадлежащие классу, называют функциями-членами или методами.

  14. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция • Синтаксис объявления класса, который не является наследником никакого другого класса: • class Имя_Класса • { • закрытые данные и функции • спецификатор доступа: • данные и функции • спецификатор доступа: • данные и функции • … • спецификатор доступа: • данные и функции • }; Имя_Класса Данные Функции

  15. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Пример описания простейшего класса, включающего только данные: class СBox { public: double m_length; double m_width; double m_height; }; m_height m_length m_width

  16. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Пример описания простейшего класса, включающего только данные: class СBox { public: double m_length; double m_width; double m_height; }; Спецификатор доступа

  17. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция • Спецификатор доступа определяет, где в программе будут доступны описанные за ним члены класса. • Имеются 3 спецификатора доступа: • Public – члены класса будут доступны как в классе, так и в любой точке программы внутри области видимости класса, к которому они относятся. • Private (спецификатор по умолчанию) – члены класса будут доступны только внутри класса (членам класса) • Protected – члены класса будут доступны только внутри класса и внутри потомков класса • Действие спецификатора доступа распространяется до следующего спецификатора или до конца описания класса • По умолчанию, все члены класса, объявленные после ключевого слова class до первого спецификатора доступа имеют спецификацию доступа private

  18. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Объявление экземпляров класса CBox mybox1, mybox2; Объявление указателей на класс CBox *pbox; pbox=&mybox1; Динамическое выделение памяти для экземпляра класса CBox *pmybox = new CBox; Доступ к членам – аналогично структурам mybox1.m_length = 2.5; mybox2.m_width = mybox1.m_length; pmybox->m_height = mybox1.m_length; pmybox->m_length = pmybox->m_height ;

  19. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Первый принцип инкапсуляции: объединение данных и методов. Добавим функцию вычисления объема class СBox { public: double m_length; double m_width; double m_height; double Volume( ); }; double CBox::Volume() { return m_length*m_width*m_height; }

  20. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Поработаем с классом CBox int main() // Working with class CBox { CBox mybox1; // Static allocation mybox1.m_length=2; mybox1.m_width=3; mybox1.m_height=4; cout << mybox1.Volume() << endl; // 24 CBox *pmybox2 = new CBox; // Dynamic allocation pmybox2->m_length=5; pmybox2->m_width=6; pmybox2->m_height=7; cout << pmybox2->Volume() << endl; // 210 delete pmybox2; return 0; }

  21. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Второй принцип инкапсуляции: защита от внешнего вмешательства. Доступ к данным через явный интерфейс class CBox { double m_length; double m_width; double m_height; public: void Setlength(double sl) {m_length = sl; } void Setwidth(double sw) {m_width=sw; } void Setheight(double sh) {m_height =sh; } double Getlength() {return m_length;} double Getwidth() {return m_width;} double Getheight() {return m_height;} double Volume( ); };

  22. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Работаем с измененным классом CBox: int main() // Working with modified class CBox { CBox mybox1; mybox1.Setlength(2); mybox1.Setwidth(3); mybox1.Setheight(4); cout << mybox1.Getheight() << " " << mybox1.Volume() << endl; // 4 24 CBox *pmybox2 = new CBox; pmybox2->Setlength(5); pmybox2->Setwidth(6); pmybox2->Setheight(7); cout << pmybox2->Getlength() << " " << pmybox2->Volume() << endl; delete pmybox2; return 0; }

  23. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Для чего это нужно: независимость интерфейса от реализации, разрешаются только операции, определенные через интерфейс class CBox { double m_Size[3]; //now with array !!! public: void Setlength(double sl) {m_Size[0] = sl; } void Setwidth(double sw) {m_Size[1]=sw; } void Setheight(double sh) {m_Size[2] =sh; } double Getlength() {return m_Size[0];} double Getwidth() {return m_Size[1];} double Getheight() {return m_Size[2];} double Volume( ); }; double CBox::Volume() { return Getlength()*Getwidth()*Getheight(); }

  24. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция В использующей класс программе ничего менять не надо: int main() // Working with modified class CBox { CBox mybox1; mybox1.Setlength(2); mybox1.Setwidth(3); mybox1.Setheight(4); cout << mybox1.Getheight() << " " << mybox1.Volume() << endl; CBox *pmybox2 = new CBox; pmybox2->Setlength(5); pmybox2->Setwidth(6); pmybox2->Setheight(7); cout << pmybox2->Getlength() << " " << pmybox2->Volume() << endl; delete pmybox2; return 0; }

  25. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция • Конструкторы • Конструктор класса – специальная функция класса, которая вызывается при создании нового объекта класса. Она позволяет инициализировать объекты во время их создания и захватывать ресурсы, необходимые для их функционирования. • Конструкторы всегда называются по имени класса и не имеют типа возврата. • Компилятор предоставляет два типа конструкторов: конструктор по умолчанию и конструктор копирования: • CBox mybox1; // Вызов конструктора по умолчанию • … • CBox mybox2 = mybox1 // Вызов конструктора копирования • Класс может иметь несколько конструкторов, которые можно перегружать • Если Вы определили какой-либо свой конструктор копирования, Вы обязаны явно определить конструктор по умолчанию. • Стандартный конструктор копирования нельзя использовать при работе с указателями

  26. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Класс Cboxс перегруженным конструктором и тестовым деструктором class CBox { double m_length; double m_width; double m_height; public: CBox() {m_length=0; m_width=0; m_height=0;} CBox(double l,double w) {m_length=l; m_width=w; m_height=0;} CBox(double l, double w, double h){m_length=l; m_width=w; m_height=h;} ~CBox () {std::cout << "destructor CBox done";} void Setlength(double sl) {m_length = sl;} void Setwidth(double sw) {m_width=sw;} void Setheight(double sh) {m_height =sh;} double Getlength() {return m_length;} double Getwidth() {return m_width;} double Getheight() {return m_height;} void Print (){std::cout <<"\nL="<<m_length<<" W="<<m_width<<" H="<<m_height;} double Volume( ){return m_length*m_width*m_height;} };

  27. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция В конструкторе инициализацию переменных-членов класса можно делать в теле конструктора: CBox() {m_length=0; m_width=0; m_height=0;} CBox(double l,double w) {m_length=l; m_width=w; m_height=0;} CBox(double l, double w, double h){m_length=l; m_width=w; m_height=h;} Или вне тела: CBox() : m_length(0), m_width(0), m_height(0) { } CBox(double l,double w): m_length(l), m_width(w), m_height(0) { } CBox(double l, double w, double h): m_length(l), m_width(w), m_height(h) { }

  28. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Поработаем с этим классом int main() // Working with class CBox { CBox mybox1; mybox1.Print(); // L=0 W=0 H=0 CBox mybox2(1,2,3); mybox2.Print(); // L=1 W=2 H=3 CBox mybox3(1,2); mybox3.Print(); // L=1 W=2 H=0 CBox mybox4=mybox2; mybox4.Print(); // L=1 W=2 H=3 mybox1=mybox2; mybox1.Print(); // L=1 W=2 H=3 _getch(); return 0;// Destructor done }

  29. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Стандартный конструктор копирования нельзя использовать, если Вы работаете с членами - указателями class CPoint { short m_a; short *m_k; public: CPoint() {m_a=4; m_k=new short (1);} // Consructor ~CPoint() {delete m_k; m_k=NULL;} // Destructor void Setk(short k){*m_k=k;} void Seta(short a){m_a=a;} void Print () {std::cout << "\n a="<<m_a<<" k=" << m_k<< " *k="<<*m_k;} };

  30. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Стандартный конструктор копирования нельзя использовать, если Вы работаете с членами - указателями int main() // Working with class CPoint { CPointx; x.Print(); // a= 4 k=003B6188 *k=1 CPoint y=x; y.Print();// a= 4 k=003B6188 *k=1 x.Setk(5); x.Seta(8); x.Print(); // a= 8 k=003B6188 *k=5 y.Print(); // a= 4 k=003B6188 *k=5 return 0; // program crash while try to free the same } // memory second time!

  31. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Надо определить свой конструктор копирования class CPoint { short m_a; short *m_k; public: CPoint() {m_a=4; m_k=new short (1);} CPoint (const CPoint &p) {m_a=p.m_a; m_k=new short(*p.m_k);} ~CPoint() {delete m_k; m_k=NULL;} void SetK(short k){*m_k=k;} void SetA(short a){m_a=a;} void Print () {std::cout << "\n a="<<m_a<<" k=" << m_k<< " *k="<<*m_k;} }; Если передавать p не по ссылке, а по значению, произойдет зацикливание функции, так как передача по значению предполагает создание нового объекта и копирование значения, которое тоже выполняется с помощью этой функции const, чтобы Вы по глупости не изменили значения полей источника в функции при их копировании

  32. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Та же программа, теперь дает ожидаемый результат int main() // Working with class CPoint { CPointx; x.Print(); // a= 4 k=003B6188 *k=1 CPoint y=x; y.Print();// a= 4 k=003B6260*k=1 x.SetK(5); x.SetA(8); x.Print(); // a= 8 k=003B6188 *k=5 y.Print(); // a= 4 k=003B6260*k=1 return 0; }

  33. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция • Деструкторы • Деструктор класса – специальная функция класса, которая уничтожает объект, когда необходимость в нем отпадает или время его жизни завершено. • Имя деструктора совпадает с именем класса, которому предшествует знак ~(тильда). • Деструктор не принимает параметров и не возвращает значения. Таким образом, деструктор в классе всегда один. • Компилятор предоставляет деструктор по умолчанию. • Однако, если Вы захватывали какие-либо ресурсы при создании объекта (например, динамически выделяли память), Вы обязаны переопределить деструктор для корректного освобождения ресурсов • Это было сделано в предыдущем примере: • ~CPoint() {delete m_k; m_k=NULL;}

  34. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Объекты в памяти CBox box1, box2, box3 box3 box1 box2 m_length m_length m_length m_width m_width m_width m_height m_height m_height Setlength() Getlength() Setwidth() Getwidth() Setheight() Getheight() Volume()

  35. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Указатель this double CBox::Volume() { return m_length * m_width * m_height; } box1.Volume(); box2.Volume(); box3.volume() double CBox::Volume(const CBox* this) { return this->m_length * this->m_width * this->m_height; } CBox::Volume(&box1);

  36. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Статические переменныеили константы - члены класса class CBox { double m_length; double m_width; double m_height; static int m_noboxes; public: CBox() {m_length=0; m_width=0; m_height=0;m_noboxes++} void Setlength(double sl) {m_length = sl; } void Setwidth(double sw) {m_width=sw; } void Setheight(double sh) {m_height =sh; } double Getlength() {return m_length;} double Getwidth() {return m_width;} double Getheight() {return m_height;} double Volume( ); }; Статические данные-члены класса только объявляются внутри класса. Они должны быть определены вне класса следующим образом: int CBox::m_noboxes; // или int CBox::m_noboxes=0;

  37. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Объекты в памяти CBox box1, box2, box3; box3 box1 box2 m_length m_length m_length m_width m_width m_width m_height m_height m_height Setlength() Getlength() Getwidth() Setwidth() Getheight() Setheight() m_noboxes Volume()

  38. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Статические функции - члены класса class CBox { double m_length; double m_width; double m_height; static int m_noboxes; public: CBox() {m_length=0; m_width=0; m_height=0;m_noboxes++} void Setlength(double sl) {m_length = sl; } void Setwidth(double sw) {m_width=sw; } void Setheight(double sh) {m_height =sh; } double Getlength() {return m_length;} double Getwidth() {return m_width;} double Getheight() {return m_height;} double Volume( ); static Getnoboxes() {return m_noboxes;} }; Статические функции-члены класса имеют доступ только к статическим членам класса. Для доступа к нестатическим членам они должны получить адрес объекта как параметр

  39. 5. Объектно-ориентированное программирование 5.3. Инкапсуляция Константные объекты const CBox bx1(10, 15, 6); Константные функции-члены класса class CBox { double m_length; double m_width; double m_height; static int m_noboxes; public: const double Getlength() {return m_length;} const double Getwidth() {return m_width;} const double Getheight() {return m_height;} const double Volume( ); }; Значения полей константного объекта после инициализации не могут изменяться Константная функция не может изменять значения переменных-членов класса

  40. Inf Inf Inf Inf link link link link 5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных Организация связанных структур данных. struct Node { Node *link; // Информационная часть inf // … };

  41. Inf Inf Inf Inf link link link link inf inf inf link1 link1 link1 link2 link2 link2 5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных Основные виды связанных динамических структур данных: Линейные списки – данные динамической структуры, которые представляют собой совокупность линейно связанных однородных элементов, для которых разрешается добавлять элементы между любыми двумя другими и удалять любой элемент.

  42. inf inf inf inf inf inf inf inf link link link link link link link link 5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных Основные виды связанных динамических структур данных: Кольцевые списки – имеют дополнительную связь между первым и последним элементами. Очередь – частный случай линейного списка – разрешено только 2 действия – добавление элементов в конец (хвост) и удаление из начала (головы) списка. Стек – частный случай линейного списка – разрешено только 2 действия – добавление и удаление элементов с одного конца (головы) стека.

  43. inf inf inf inf inf inf inf inf link1 link1 link1 link1 link1 link1 link1 link1 link2 link2 link2 link2 link2 link2 link2 link2 5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных Основные виды связанных динамических структур данных: Деревья – иерархические динамические структуры произвольной конфигурации.

  44. 5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных Стек как объект-контейнер class CStack { struct m_Node { m_Node *m_next; int m_item; }; m_Node *m_head; int m_size; public: CStack() {m_head=NULL; m_size=0;} //Constructor ~CStack(); // Destructor void Push(int item); int Pull(); void Print(); };

  45. 5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных Работа со стеком 1. Исходное состояние CStack() {m_head=NULL; m_size=0;} m_head m_size=0 2. Добавление элемента void CStack::Push(int item) { m_Node *cur=new m_Node; cur->m_item = item; cur->m_next = m_head; m_head = cur; m_size++; return; } m_head cur m_item m_next

  46. 5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных Работа со стеком 1. Исходное состояние CStack() {m_head=NULL; m_size=0;} m_head m_size=0 2. Добавление элемента void CStack::Push(int item) { m_Node *cur=new m_Node; cur->m_item = item; cur->m_next = m_head; m_head = cur; m_size++; return; } m_head cur m_item m_next

  47. 5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных Работа со стеком 1. Исходное состояние CStack() {m_head=NULL; m_size=0;} m_head m_size=0 2. Добавление элемента void CStack::Push(int item) { m_Node *cur=new m_Node; cur->m_item = item; cur->m_next = m_head; m_head = cur; m_size++; return; } m_head cur m_item m_next

  48. 5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных Работа со стеком 1. Исходное состояние CStack() {m_head=NULL; m_size=0;} m_head m_size=0 2. Добавление элемента void CStack::Push(int item) { m_Node *cur=new m_Node; cur->m_item = item; cur->m_next = m_head; m_head = cur; m_size++; return; } m_head cur m_item m_next

  49. 5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных Работа со стеком 1. Исходное состояние CStack() {m_head=NULL; m_size=0;} m_head m_size=1 2. Добавление элемента void CStack::Push(int item) { m_Node *cur=new m_Node; cur->m_item = item; cur->m_next = m_head; m_head = cur; m_size++; return; } m_head cur m_item m_next

  50. 5. Объектно-ориентированное программирование 5.4. Связанные динамические структуры данных Работа со стеком 1. Исходное состояние CStack() {m_head=NULL; m_size=0;} m_head m_size=1 2. Добавление элемента void CStack::Push(int item) { m_Node *cur=new m_Node; cur->m_item = item; cur->m_next = m_head; m_head = cur; m_size++; return; } m_head m_item m_next

More Related