ООП Классы Данные отдельно, методы отдельно struct Node { Node* next; void* data; }; struct List { Node* first; int size; }; void* allocate() { … } void.

Презентация:



Advertisements
Похожие презентации
Инструкции C++ Условная инструкция Формат: if (условие) оператор; else оператор; Пример: if (i!=0) { if (j) j++; if(k) k++; else if(p) k--; } else i--;
Advertisements

ООП Классы – 2.
Инструкции C++ Условная инструкция Формат: if (условие) оператор; else оператор; Пример: if (i!=0) { if (j) j++; if(k) k++; else if(p) k--; } else i--;
1 Переопределение операций Макаревич Л. Г.. 2 Зачем нужна перегрузка операций? class Complex { double re; double im; public: Complex(double r=0, double.
Потоки Язык C++ не обеспечивает средств для ввода/вывода Ему это и не нужно; такие средства легко и элегантно можно создать с помощью самого языка Традиционно.
Объектно-ориентированное программирование С++. Лекция 6 Карпов В.Э.
Лекция 10 ОбъектыЛекция 10 ОбъектыООП Инкапсуляция Возможность совместного хранения данных и кода для их обработки Наследование Возможность расширять существующие.
1. Классы ООП 1.Наследование 2.Инкапсуляция 3.Полиморфизм.
Лекция 8. Введение в ООП. Часть 1 Красс Александр СПбГУ ИТМО, 2008.
Абстрактный тип данных список. Операции над абстрактным списком Создать пустой список Уничтожить список Определить, пуст ли список Определить количество.
С++, начала ООП Семинар 1 Рябова Анна Сергеевна
Д.з Язык С++ - занятие 31. Задача 1: 1/1 + 1/3 + 1/5 … #include using namespace std; int main() { int n; cin >> n; double sum = 0;// Сумма for.
Дружественные функции Дружественные функции – это функции, объявленные вне класса, но имеющие доступ к закрытым и защищенным полям данного класса Дружественная.
Объектно-ориентированное программирование С++. Лекция 8 Карпов В.Э.
Сложные структуры данных Связные списки. Структуры, ссылающиеся на себя struct node { int x; struct node *next; };
Д.з. 1. Задача 3: список struct list { int val; list* next; list(int val_, list* next_) : val(val_), next(next_) {} }; void print(const list* p) { while.
Лекция 4. Введение в С++ Наследование, множественное наследование. Конструкторы, деструкторы. Виртуальные функции.
Универсальность. Классы с родовыми параметрами. Под универсальностью (genericity) понимается способность класса объявлять используемые им типы как параметры.
Д.з. на 3 марта Язык С++ - занятие 51. Задача 4: top class stack { … int & top() { return stk[size -1 ]; } … }; // Пример вызова: stack s; … s.top() =
Язык C++ Лекция 2. Недостатки enumов Засорение namespaceа, в котором находится enum Соответственно, члены enumа должны иметь уникальный префикс.
Транксрипт:

ООП Классы

Данные отдельно, методы отдельно struct Node { Node* next; void* data; }; struct List { Node* first; int size; }; void* allocate() { … } void add (void* cont, void* data) { … } int size (void* cont) { … } void* remove (void* cont, int pos) { … } void release(void* cont) { … } void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; List* list = (List*)allocate(); add(list, a+1); add(list, a+5); remove(list,1); printf(Size: %d, size(list)); release(list); }

Проблема 1: подаем некорректные данные void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; void* bbb = NULL; List* list = (List*)allocate(); add(bbb, a+1); add(a, a+5); remove(a,1); printf(Size: %d, size(bbb)); release(list); }

Данные и методы вместе (объект) struct Node { Node* next; void* data; }; void* allocate() { … } void release(void* cont) { … } struct List { Node* first; int size; void add (void* data) { … } int size () { … } void* remove (int pos) { … } void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; List* list = (List*)allocate(); list->add(a+1); list->add(a+5); list->remove(1); printf(Size: %d, list->size()); release(list); }

Проблема 2: не защищено создание и удаление void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; void* bbb = NULL; List* list = (int*)allocate(); list->add(a+1); list->add(a+5); list->remove(1); printf(Size: %d, list->size()); release(bbb); } void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; void* bbb = NULL; List list = ??? // мы знаем только как создавать указатель на структуру List }

Не получается void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; void* bbb = NULL; List* list = ???->allocate(); list->add(a+1); list->add(a+5); list->remove(1); printf(Size: %d, list->size()); list->release(); free(list); // две операции } struct List { Node* first; int size; void add (void* data) { … } List* allocate() { … } List allocate2() { … } void release() { … }

Конструктор и деструктор struct Node { Node* next; void* data; }; struct List { Node* first; int size; List() { … } // конструктор void add (void* data) { … } int size () { … } void* remove (int pos) { … } ~List() { …} // деструктор } void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; List* list = new List(); list->add(a+1); list->add(a+5); list->remove(1); printf(Size: %d, list->size()); delete list; // ~List() } void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; List list(); list.add(a+1); list.add(a+5); list.remove(1); printf(Size: %d, list.size()); } // после завершения функции выполнится деструктор ~List()

Бонус: несколько конструкторов struct Node { Node* next; void* data; }; struct List { Node* first; int size; List() { … } //создать пустой список List(int* array, int array_size) { … } // создать список и заполнить его данными из массива } void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; List* list = new List (a, 10); printf(Size: %d, list->size()); // 10 delete list; // ~List() } void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; List list(a, 10); printf(Size: %d, list.size()); // 10 } // после завершения функции выполнится деструктор ~List()

Проблема 3: портим состояние объекта void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; List* list = new List(); list->add(a+1); list->add(a+5); list->remove(1); list->first = NULL; // не освободили память предварительно list->size = 1000; // некорректный размер printf(Size: %d, list->size()); // покажет: 1000 delete list; // ~List() }

Защищаем доступ. Инкапсуляция. struct Node { Node* next; void* data; }; class List { private: Node* first; int size; public: List() { … } // конструктор void add (void* data) { touch(); // no problem … } int size () { return size; // no problem } void* remove (int pos) { touch(); … } ~List() { …} // деструктор private: void touch() { // запоминаем время } void main() { int a[] = {0,1,2,3,4,5,6,7,8,9}; List* list = new List(); list->add(a+1); list->add(a+5); list->remove(1); list->first = NULL; // ошибка компиляции list->size = 1000; // ошибка компиляции printf(Size: %d, list->size()); list->touch(); // ошибка компиляции delete list; // ~List() }

Проблема 4: защита вспомогательной структуры class Node { private: Node* next; void* data; }; class List { private: Node* first; int size; public: List() { … } // конструктор void add (void* data) { touch(); // no problem Node newNode = new Node(); newNode->next = NULL; // ошибка компиляции newNode->data = data; // ошибка компиляции … } int size () { return size; // no problem } … } Кто-то может воспользоваться нашей структурой случайно (в своем коде): void main() { Node n* = new Node(); // no problem }

Друзья класса class List; // нужно указать, что класс такой есть class Node { friend List; private: Node* next; void* data; Node() { … }; }; class List { private: Node* first; int size; public: List() { … } // конструктор void add (void* data) { touch(); // no problem Node newNode = new Node(); newNode->next = NULL; // no problem newNode->data = data; // no problem … } … } Кто-то может воспользоваться нашей структурой случайно (в своем коде): void main() { Node n* = new Node(); // ошибка компиляции, конструктор приватный ! }

Соглашение: разделение интерфейса и реализации Файл List.hpp class List; class Node { friend List; private: Node* next; void* data; Node(); }; class List { private: Node* first; int size; public: List(); // конструктор void add (void* data); int size () { return size;// можно оставить } void* remove (int pos) ; ~List(); // деструктор private: void touch() ; } Файл List.cpp #include List.hpp Node::Node() { … } List::List() { // конструктор … } void List::add (void* data) { … } void* List::remove (int pos) { … } List::~List() { … } List::touch(){ … }

Бонус: переопределение операций class Complex { private: float myReal; float myImag; public: Complex(float re, float im) { myReal = re; myImag = im; } Complex operator+(Complex c) { Complex sum(myReal+c.myReal, myImag+c.myImag); return sum; } Complex operator+(double re) { Complex sum(myReal+re, myImag); return sum; } Complex operator+(int re) { Complex sum(myReal+re, myImag); return sum; } void print() { printf("Complex: %f %f\n", myReal, myImag); } float& operator[] (int pos) { if (pos ==0) return myReal; else return myImag; } }; // end of class definition // внещний оператор Complex operator+(double d, Complex c2) { Complex sum(d+c2.Real(), c2.Imag()); return sum; }

Бонус: переопределение операций void main() { Complex c1 (1.1, 0); Complex c2 (9,9.9); int i = 0; double d = 0.0; Complex c = c1 + c2; // Вызов: Complex operator+(Complex c) {…} c = c1 + i; // Вызов: Complex operator+(int re) {…} c = c1 + d; // Вызов: Complex operator+(double re) {…} c = d + с1; // Вызов: Complex operator+(double d, Complex c2) {…} c[0] = 1; // Вызов: float& operator[] (int pos) {…} c[1] = 8; // Вызов: float& operator[] (int pos) {…} c.print(); }