Капсулиране и разпределяне на обекти в купчината
1. Капсулиране и заместване
В предишни лекции разгледахме обекти като Array, Complex, които бяха създадени, за да не се мисли за тяхната подробна вътрешна структура, а само да се използват.
Следвайки този подход, можем да кажем, че типовете обекти в C ++ се разбиват на нива (стъпки):
по-високи нива
указател, int, char и т.н. (основни типове)
По този начин се появява положителна характеристика: всяко ново ниво ви позволява да скриете по-ниско, например в класа Complex ние не се интересуваме от неговото изпълнение, а само от набор от неговите възможности.
Извиква се скриването на изпълнението на структурата от потребителя и предоставянето му само на определен набор от възможности Капсулиране и е една от трите основи на ООП.
Помислете за следния код, като използвате класа на комплексния номер:
Комплекс a, b;
a.add (b);
Вторият ред извиква метода на класа. Отнема известно време да извикате метод (функция), за да поставите аргументи в стека и да отидете на кода на тази функция. Методът за добавяне ще добави четири числа.
Да кажем, че не използваме класа на комплексните числа, а просто използваме четири числа, които характеризират две комплексни числа. Тогава ще отнеме по-малко време, за да ги добавите, тъй като няма да е необходимо да извиквате функцията за добавяне на сложни числа.
По този начин може да се види, че по време на капсулирането времето на изпълнение на програмата ще се увеличи и това е недостатък.
Нека се опитаме да го премахнем.
Можем да поставим функцията във файла, в който е извикана.
Това означава, че по време на компилацията функцията ще бъде открита от компилатора в този файл и най-вероятно нейният код ще бъде заменен на мястото на повикването. Нарича се Заместване (В редица). Това означава, че ако поставим изпълнението на функцията във файл с нейното извикване, тогава увеличаването на времето за работа няма да настъпи (всъщност функцията няма да бъде извикана).
Ако имаме няколко файла, в които трябва да вмъкнем изпълнението на функцията, ще направим това за всеки файл.
Но сега, когато се опитаме да свържем всички обектни файлове, колекторът ще изведе грешка, свързана с факта, че е намерил множество реализации на една и съща функция.
За да избегнем грешката, описана в края на първия абзац, ще използваме ключовата дума в редица. Той е посочен преди типа на данните, върнат от функцията, например inline void add (Complex & b);
По този начин ние не само информираме компилатора, че е желателно да заменим изпълнението на мястото на повикването, но също така информираме колектора, че не е необходимо да се показва грешка, когато са намерени няколко реализации на една функция, но е достатъчно за да изберете някоя от тези реализации.
Сега нека разгледаме следния проблем: ако трябва да сменим функция, чиято реализация е в няколко файла, тогава трябва да я сменим във всеки файл, а това е неудобно и може да се появят грешки.
Нека преместим изпълнението на функцията в заглавния файл.
По този начин, като включим този заглавен файл във всички файлове, в които се извиква нашата функция, ние ще премахнем проблема с многобройните внедрения. Нека дадем пример за такъв заглавен файл (файл "complex.h"):
По този начин този проблем със заместването също е частично решен, тъй като заместването не се случва във всички случаи (това е по преценка на компилатора).
Сега трябва да разберете кога можете и трябва да използвате заместване и кога не.
Ако имаме функция с малък обем и може би често се извиква, тогава трябва да използваме метода на заместване за нея (поставяне в заглавен файл и посочване на ключовата дума в редица), тъй като ще отделим по-малко време за извикване на функцията.
Нежелателно е да се използва заместване на функции, които са дълги във времето за изпълнение или в количеството код, тъй като компилацията води до много по-голям файл (в края на краищата заместванията се използват навсякъде).
Когато се използва заместване, времето за компилиране на програмата се увеличава (компилаторът се нуждае от време, за да вмъкне и трансформира изпълнението на функцията на мястото на повикването). Понякога това увеличение е малко (особено за малки проекти), но понякога времето за компилация се увеличава значително в сравнение със случая, когато не се използва заместване.
С голям брой функции, маркирани за заместване, компилаторът може да избере не тази, която програмистът първоначално е възнамерявал да замести, а съвсем различна. В резултат на това е възможна значителна промяна в скоростта на програмата.
Коментар:
Компилаторите са достатъчно умни програми, които вместо заместване на функциите
където се наричаше int a = факториал (5); компилирайте даденото място за повикване като int a = 120;
След като разгледахме заместването като възможно решение на проблема с увеличаването на времето за изпълнение на програмата с капсулиране, ето няколко идеи за и против използването на капсулиране: