Навіщо потрібно об'єктно-орієнтованого програмування (ООП)

float F11 (int Z1)

int * x;
int * y;
int * z;
x = new int;
y = new int;
z = new int;
...

де x, y, z - покажчики на ділянки пам'яті, кожен раз виділяються в функції для зберігання там цілих чисел. Ці числа потрібні лише в процесі роботи функції, а значить є проміжними даними. В кінці роботи цієї функції нам треба буде очистити виділену пам'ять за допомогою команд виду:

delete x;
delete y;
delete z;

Даний код має недоліки, описані вище - повторне створення і знищення всередині функції проміжних даних при кожному новому виклику цієї функції. Рішенням проблеми могло б бути наступне: ми проміжні змінні могли б передавати в функцію, як її аргументи. Тобто переробимо код наступним чином:

float F11 (int Z1, int * x, int * y, int * z) <
...

Усе! Так як * x * y, * z - це тепер аргументи функції, то їх необхідно створити один раз до запуску функції, як і будь-які інші аргументи, що подаються на вхід функції. Таким чином, усередині функції F11 () тепер не будуть кожного разу створюватися і віддалятися ці самі змінні. Таким чином, резервувати пам'ять для даної функції ми будемо до її запуску одного разу створивши відповідні змінні. Більш того, доцільно даний підхід розвинути. У нашому прикладі наша функція повертає деяке число типу float. Це означає, що кожен раз всередині функції створюється змінна типу float, куди записується результат роботи цієї функції, а потім по завершенні роботи функції ця змінна знищується. Тобто насправді в тілі функції має місце наступне:

float F11 (int Z1, int * x, int * y, int * z)

Знову маємо зайві дії створення і знищення. Тут у нас створюється всередині функції змінна vix виду float, значення якої функція повертає, а саму змінну vix знищує - чистить ділянку пам'яті, що був під неї всередині функції виділено. Таким чином якщо функцію запускаємо кілька разів, то кілька разів по суті в порожню створюємо і знищуємо змінну vix. Таким чином, з урахуванням вищевикладеного доцільно зробити так:

void F11 (int Z1, int * x, int * y, int * z, float * vix) <
...
>

У підсумку всередині нашої функції не створюються ніякі проміжні змінні, а сама функція нічого не повертає. Все необхідне для її роботи тут передається функції в якості її аргументів. В результаті при кожному запуску функції немає потреби кожного разу виділяти і чистити пам'ять. Вся ця пам'ять, по суті, виділяється один раз перед першим запуском функції. Функція лише модифікує дані в цій пам'яті - в аргументах, що подаються на її вхід. Сама функція пам'ять не виділяє і не очищає. Таким чином, ми відокремили процес виділення пам'яті і процес роботи з даними (пам'яттю). Функція тепер тільки працює з даними в пам'яті, а за її виділення і очищення не відповідає. Все це прекрасно, але, по-перше, тут змінні, з якими працює функція - це її аргументи, а це значить, що вони не створюються всередині функції - вони зовнішні по відношенню до функції. А раз так, то їх може поміняти не тільки сама функція, але і будь-хто ще крім даної функції. У той час, як змінні створювані всередині функції доступні лише самої функції і більше нікому. І по-друге, якщо нам необхідна величезна кількість найрізноманітніших проміжних змінних, масивів і т.п. для роботи функції? Адже часто функція - це досить велика підпрограма. Тоді писати все проміжні змінні у вигляді аргументів функції не зручно. Як мінімум добре б об'єднати всі ці змінні в єдину структуру і подавати на вхід функції посилання на цю саму структуру. В результаті розробники мов і зробили щось подібне, але при цьому пішли ще далі - вони створили особливу структуру, яку назвали класом. Клас - це така форма організації коду, де під одним ім'ям (ідентифікатором) знаходяться і функція і дані, які їй обробляються. Тобто функцію помістили в одну структуру разом з даними, які має обробляти ця функція і які тепер немає потреби створювати всередині цієї самої функції при кожному її запуску. Ми в класі заздалегідь описуємо всі змінні, масиви і т.п. - всю ту пам'ять, що нам знадобиться, а також в класі ми описуємо функції, які і будуть працювати з цими змінними (з цією пам'яттю). І навіть якщо у функцій немає вхідних аргументів, то той факт, що змінні, масиви і т.п. і функції належать одній структурі (одного класу) - це повідомляє комп'ютера, що функції цього класу можуть працювати зі змінними, масивами і т.п. цього класу, як зі своїми власними аргументами. Більш того, дані поділяються в класі на private і public. Якщо ви описуєте, наприклад, змінну, як private, то з нею можуть працювати тільки функції даного класу - і ніщо інше поза даного класу поміняти цю змінну не може. Тобто дані типу private - це, по суті, як внутрішні змінні функцій - до них може звертатися лише сама функція і ніщо інше! Ну а дані типу public доступні і тим, хто не є членом даного класу - тобто в ці дані ми по суті пишемо результат роботи функції які цікаві вже поза даного класу - тобто це те, що повертала б наша функція якби ми не використали концепцію класу, а працювали б тільки з функціями. Так ось, таке об'єднання даних і функцій для їх обробки в одній структурі (що отримала назву класу) - це і є суть такого поняття, як інкапсуляція. Як ми вже з'ясували - саме практика підказала цей "хід" розробникам мов програмування. Виявилося, що це оптимально, коли функції лише виконують набори операцій над даними. а опису даних і самі дані (пам'ять) для цих функцій знаходяться в окремому від функцій місці. І разом з тим функції і пам'ять-дані для них утворюють єдину конструкцію - клас. Об'єкт, до слова, - це конкретна реалізація класу. Так само, як в команді виду:

int - це загальне позначення цілого типу, а i - це вже конкретна змінна цілого типу, яка і є такою завдяки тому що у зазначеній вище команді варто ідентифікатор цілого типу int. Так і з класами. Клас - загальне позначення конструкції якогось типу, об'єкт - конкретний прояв цієї конструкції. Про типи см. Також тут. До речі, тут також важливий наступний момент якраз пов'язаний з класами і типами. Часто при описі типів змінних в програмі має місце наприклад наступне:

Це виділяє в пам'яті соотвествующее місце для змінних i, j, k, куди ми можемо записати дані цілого типу. Однак, якщо у нас є, наприклад клас K1, в якому є, наприклад, змінні a1, b1, c1 типу int і функція обробки цих змінних funk1 ():

class K1 <
public:
int a1, b1, c1;
void funk1 ();

то опис зразок такого:

приведе до того, що будуть створені об'єкти X, Y, Z в яких буде виділена пам'ять під їх змінні a1, b1, c1, куди ми можемо записати відповідні дані. Таким чином тепер ми можемо записати якісь цілі числа в ділянки пам'яті з іменами X.a1, X.b1, X.c1, Y.a1, Y.b1 і так далі тобто виявилося, що виділено місце в пам'яті під відповідні 9 чисел: 3 числа (a1, b1, c1) для об'єкта X, 3 числа для об'єкта Y, 3 числа для об'єкта Z - тут все як в ситуації з оголошеня типу int, де пам'ять виділяється під відповідні змінні. А ось чи буде виділено місце в пам'яті для кожної з функцій funk1 () кожного об'єкта? Чи буде виділена пам'ять під X.funk1 (), Y.funk1 (), Z.funk1 ()? Виявляється, що немає і це логічно, адже інакше ми б три рази виділили пам'ять під по суті одну і ту ж функцію (під функції що працюють однаково)! А це безглузді витрати ресурсів комп'ютера. Таким чином в c ++ пам'ять під функції для кожного з об'єктів одного і того ж класу не виділяється - функції не тиражуються при створенні об'єктів класу. Тобто при введенні поняття класу ми не просто об'єднуємо в одну структуру (клас) дані і функції для їх обробки, але також ця концепція має на увазі відмову від дублювання однієї і тієї ж функції в конкретних об'єктах одного і того ж класу.
Наступне поняття ООП - успадкування. Знову приклад з обробки зображень. Нехай до нас хтось створив клас для роботи з зображеннями. Нас цей клас повністю влаштовує, однак нам би хотілося, щоб крім тих можливостей по обробці зображень, що надає даний клас, в ньому з'явилися б додаткові функції. Процедура спадкування і дозволяє створити наш власний клас для роботи з зображеннями на основі існуючого класу - наш клас успадкує всі функції попереднього, плюс ми туди додамо потрібні нам функції. От і все. Це дуже зручно, так як нам немає необхідності повторювати роботу по розробці функцій, які вже існують в уже створеному до нас класі. Ми ці функції просто успадковуємо створюючи клас-спадкоємець вже існуючого класу. Причому в нашій програмі ми можемо використовувати одночасно і клас-предок і клас-спадкоємець і не дивлячись на те, що у нас є два дуже схожих один на одного класу в класі-спадкоємця ми не створюємо повторно функції, що вже є в класі предка. Таким чином нам не доводиться ці самі функції заново переписувати в клас-спадкоємець - ми просто користуємося функціями класу-предка і в результаті не займаємо повторно пам'ять під одні і ті ж функції в різних класах.
Ну і, нарешті, поліморфізм. Тут все досить просто і це поняття є, по суті, розвиток такого явища, як перевантаження функцій (раніше прегрузка називалася перевизначенням). Це коли одна і та ж функція може працювати по-різному в залежності від того, якого типу дані ви подали на її вхід. Наприклад, у вас є якась функція множення, і коли ви в якості аргументів передаєте їй цілі числа, то вона їх просто перемножує, а коли в якості аргументів даєте їй матриці, то тоді ця функція перемножує матриці за правилом множення матриць. Тобто тут одна і та ж функція, один і той же інтерфейс (спосіб взаємодії, відображення) призначений для перемноження даних різного типу. Для того, щоб організувати код таким чином, щоб один і той же інтерфейс використовувався для роботи з даними різного типу існують спеціальні команди мови. Ще один приклад - з обробки зображень. Це коли одна і та ж програма може однаково обробляти зображення різних форматів - bmp, jpeg, gif і т.д. при цьому вас не турбує формат цього зображення - вам для його обробки необхідно в програмі здійснювати одні й ті ж операції, не залежно від того, який зараз формат даного зображення. В результаті поліморфізм дозволяє створювати досить зручні інтерфейси програм.
Таким чином, конструкції ООП - це не щось кимось надумане довільним чином. Прийоми ООП виникли з самої практики - це прийоми більш оптимальної роботи з інформацією тільки і всього.

p.s. Для того, хто цікавиться пристроєм комп'ютера можна порадити ось цю книгу і зокрема главу з неї - "Що таке комп'ютер" (саму книгу або окремі розділи з неї ви можете придбати тут).