C++. Посилання об'єкт класу. Доступ до об'єкта класу за посиланням. Посилання як члени класу даних. Приклади
Посилання об'єкт класу. Доступ до об'єкта класу за посиланням. Посилання як члени класу даних. Приклади
Пошук на інших ресурсах:
1. Як оголошується змінна, яка є посиланням на клас? Як оголосити посилання на об'єкт класу?
Посилання на клас оголошується за допомогою символу & . При оголошенні змінної, яка є посиланням, необхідно одразу її ініціалізувати значенням об'єкта, для якого вже виділено пам'ять.
Загальний вид оголошення посилання на об'єкт класу має вигляд:
- CMyClass – ім'я класу;
- ref - ім'я змінної, яка є посиланням на об'єкт obj;
- obj – ім'я об'єкта, для якого виділено пам'ять.
2. Приклад оголошення посилання на об'єкт класу та його використання
Нехай заданий клас CYear, що реалізує рік. Оголошення класу має такий вигляд:
// клас, що реалізує категорію "Рік" class CYear < int year; // Внутрішня змінна public: CYear(void); // конструктор за замовчуванням // конструктор з 1 параметром CYear(int year) < this-> year = year; > // методи доступу int Get(void) < return year; > void Set(int year) < this-> year = year; > // метод, що визначає високосний рік чи ні bool IsLeapYear(void); >; // конструктор за замовчуванням CYear::CYear(void) <year = 2000; // Початкова ініціалізація > // метод, що визначає високосний рік чи ні bool CYear::IsLeapYear(void) < if (рок % 400 == 0) return true; else if (рок % 100 == 0) return false; else if (Year % 4 == 0) return true; else return false; >
Використання класу в іншому методі
CYear c1; // c1 - об'єкт CYear & c2 = c1; // c1 і c2 вказують на ту саму ділянку пам'яті int d; // Доступ до об'єкта c1 c1.Set(2010); d = c1. Get (); // d = 2010 // Доступ за посиланням c2 d = c2. Get (); // d = 2010 c2.Set(3333); d = c1. Get (); // d = 3333; c1 і c2 вказують на ту саму ділянку пам'яті
У наведеному вище коді за допомогою символу & оголошується змінна-посилання c2 на об'єкт класу c1 за допомогою наступного рядка
Для змінної c1 пам'ять вже виділено. Змінні c1 і c2 посилаються на ту саму ділянку пам'яті (на той самий об'єкт).
3. Оголошення та використання посилання на об'єкт класу, доступ до якого здійснюється за допомогою некерованого (unmanaged) покажчика. приклад
Якщо оголосити покажчик клас ( * ) і виділити йому пам'ять, то цей ділянку пам'яті (об'єкт) можна оголосити посилання.
Нижченаведений приклад демонструє використання покажчика та посилання на клас CYear, що описується в п. 2.
CYear * pc = new CYear(); // Некерований покажчик, виділяється пам'ять CYear & rc = (*pc); // Посилання на пам'ять, виділену для покажчика int d; // доступ до об'єкта за вказівником pc->Set(2040); d = pc->Get(); // d = 2040 d = rc. Get (); // d = 2040 rc.Set(2100); d = pc->Get(); // d = 2100
4. Приклад використання посилання на об'єкт класу, який є членом даних іншого класу. Що станеться, якщо у класі не ініціалізувати посилання на об'єкт?
Посилання (змінне посилання) на об'єкт класу може бути членом даних іншого класу. При оголошенні змінної-посилання в класі, ця змінна може бути відразу ініціалізована в спеціально розробленому конструкторі. У цьому випадку для змінної посилання класу пам'ять виділяється динамічно (див. приклад нижче).
У прикладі нижче демонструється застосування класу CLine (відрізок), в якому оголошуються два посилання класу CPoint , який описує точку на координатній площині.
У класі CPoint реалізовані такі члени даних та методи:
- внутрішні змінні x, y – координати точки;
- конструктор за замовчуванням;
- методи доступу GetXY(), SetXY().
У класі CLine оголошуються такі члени даних та методи:
- внутрішні змінні-посилання типу CPoint& (посилання на об'єкт класу CPoint) з іменами p1, p2;
- конструктор з двома параметрами, який динамічно ініціалізує посилання p1 p2 при оголошенні об'єкта класу;
- методи доступу GetPoints(), SetPoints().
Оголошення класів CPoint і CLine має такий вигляд:
// клас, що реалізує точку class CPoint < int x,y; public: // конструктор за замовчуванням CPoint() < x = y = 0; >// методи доступу void GetXY(int* nx, int* ny) < * nx = x; *ny = y; >void SetXY(int nx, int ny) < x = nx; y = ny; >>; // клас, що реалізує відрізок class CLine < // Посилання на об'єкти типу CPoint CPoint & p1; CPoint & p2; public: // конструктор за замовчуванням // динамічно ініціалізуються значення посилань p1 та p2 CLine():p1(* new CPoint), p2(* new CPoint) < p1.SetXY(0, 0); p2.SetXY(1, 1); >// методи доступу // Повернути координати точок void GetPoints(CPoint* pt1, CPoint* pt2) < int x, y; p1.GetXY(&x, &y); // взяти значення x, y для точки p1 pt1->SetXY(x, y); // встановити x,y у нову точку pt1 p2.GetXY(&x, &y); // взяти x,y pt2->SetXY(x, y); // записати x,y у pt2 > // встановити нові значення точок void SetPoints(CPoint* pt1, CPoint* pt2) < int x, y; // p1 => pt1 p1.GetXY(&x, &y); pt1->SetXY(x, y); // p2 => pt2 p2.GetXY(&x, &y); pt2->SetXY(x, y); > >;
Важливо: при оголошенні посилання на об'єкт деякого класу, обов'язково потрібно ініціалізувати ці посилання деяким значенням, наприклад, спеціально розробленому конструкторі за умовчанням. Якщо не вказати код ініціалізації посилання в конструкторі, компілятор видасть помилку:
p1' : мусить бути ініціалізований в конструкторі base/member initializer list .
У класі CLine здійснюється динамічна ініціалізація посилань p1 та p2 за допомогою конструктора:
// динамічна ініціалізація змінних-посилань p1, p2 класу CLine CLine():p1(* new CPoint), p2(* new CPoint) < // . >
Використання класу CLine в іншому методі:
// Посилання на об'єкти як члени-даних класу CLine cl1; // викликається конструктор, який ініціалізує змінні посилання p1, p2 // Додаткові змінні CPoint point1, point2; int x, y; // Перевірка, як конструктор заповнив координати точок відрізка cl1.GetPoints(&point1, &point2); point1.GetXY(&x, &y); // x = 0; y = 0 point2.GetXY(&x, &y); // x = 1; y = 1 // встановити нові значення point1.SetXY(3, 8); // Записати крапку (3; 8) point2.SetXY(5, 9); // Записати крапку (5; 9) cl1.SetPoints(&point1, &point2); // Перевірка CPoint pp1, pp2; cl1.GetPoints(&pp1, &pp2); pp1.GetXY(&x, &y); // x = 3; y = 8 pp2.GetXY(&x, &y); // x = 5; y = 9
Пов'язані теми
C++. Класи. Частина 1. Поняття класу. Оголошення типу даних "клас". Об'єкт класу. Класи серед CLR. Інкапсуляція даних у класі
C++. Класи. Частина 1. Поняття класу. Оголошення класу. Об'єкт класу. Класи в середовищі CLR. Інкапсуляція даних у класі
Пошук на інших ресурсах:
1. Основні поняття об'єктно-орієнтованого програмування. Класи та об'єкти
У мові програмування C++ поняття «клас» є основою об'єктно-орієнтованого програмування (ООП). Об'єктно-орієнтоване програмування виникло як удосконалення процедурно-орієнтованого програмування.
Свого часу процедурно-орієнтоване програмування вже не забезпечувало необхідної якості написання великих програмних систем.Програми розбивалися (структурувалися) на модулі, виникала повторюваність програмного коду різних модулях (частинах) програми, ускладнювалося тестування (пошук помилок), знижувалася надійність програми.
В основі ООП лежать поняття «об'єкт» і «клас». У мові програмування об'єкт – це змінна типу «клас». Клас описує дані та методи (функції), які використовуватимуться об'єктом цього класу. Кожен клас визначає логічно-завершену одиницю програми. Інкапсуляція даних та методів їх обробки в межах класу дозволяє покращити структурованість програмних систем. Це своє чергу зменшує ризик виникнення «невидимих» логічних помилок. Використання спадковості та поліморфізму в класах дозволяє уникнути повторюваності програмного коду та зручно впорядкувати складні виклики методів, об'єднаних між собою у список.
Клас визначає формат (опис) деяких даних та роботу (поведінка) над цими даними. З оголошення класу можна отримати різну кількість об'єктів класу (змінних типу клас). Кожен об'єкт класу визначається конкретним (зараз) значенням внутрішніх даних (змінних), яке називається станом об'єкта.
У класі оголошуються дані (внутрішні змінні, властивості) та методи (функції), які оперують цими даними (виконують роботу над даними).
Клас може бути успадкований з інших класів верхніх рівнів. Це означає, що клас може використовувати частину коду інших класів верхніх рівнів.
Також клас може бути батьківським для інших класів, які успадковують його програмний код.
2. Які види класів мови C++ можна реалізувати серед CLR ?
У середовищі CLR (Common Language Runtime) підтримуються два види класів:
- некеровані (unmanaged) класи.Для виділення пам'яті під об'єкти таких класів можуть використовуватися некеровані покажчики (*) та операція new;
- керовані (managed) класи. Для виділення пам'яті в таких класах можуть бути використані керовані покажчики (^) та операція gcnew.
Ця тема висвітлює особливості використання unmanaged ( * ) класів.
Приклади, які демонструють особливості використання та відмінність між керованими ( ^ ) і некерованими ( * ) класами, докладніше описуються в темі:
3. Загальна форма оголошення unmanaged-класу. Ключове слово "class"
У найпростішому випадку (без наслідування) загальна форма оголошення unmanaged-класу має такий вигляд
class ім'я_класу < private: // приховані (закриті) дані та методи (функції) // . public: // Відкриті дані та методи // . protected: // захищені дані та методи // . >;
- ім'я_класу - безпосередньо ім'я нового типу даних "клас". Це ім'я використовується для створення об'єктів класу.
Ключове слово class повідомляє, що оголошується новий клас (тип даних). Усередині класу оголошуються члени класу: дані та методи. Ключове слово private визначає члени класу, які мають бути закриті від зовнішніх методів, оголошених поза класу, і навіть об'єктів класу. Члени даних, оголошені з ключовим словом private, доступні лише іншим членам цього класу.
Ключове слово public визначає загальнодоступні дані (змінні) та методи (функції) класу.
Ключове слово protected визначає захищені дані та методи класу, які є:
- доступними для методів успадкованих від цього класу;
- недоступними для методів, реалізованих в інших частинах програми;
- недоступними для об'єктів (примірників) класу.
У межах опису класу секції (розділи) private , protected , public можуть йти у порядку й у будь-якій кількості. Наприклад:
class MyClass < // секція (розділ) private за умовчанням // . public: // секція public // . protected: // секція protected // . private: // Знову секція private // . public: // Знову секція public // . >;
4. Що означає термін «інкапсуляція даних» у класі?
Термін "інкапсуляція даних" означає те, що для членів класу (даних та методів) можна встановлювати ступінь доступності з інших частин програмного коду (інших методів, об'єктів класу). Таким чином, виникає поняття приховування даних (методів) у класі.
Інкапсуляція забезпечує покращення надійності збереження даних у класі шляхом введення додаткових методів перевірки цих даних на допустимі значення. Як правило, доступ до прихованих даних у класі відбувається не безпосередньо, а через виклики спеціальних методів доступу чи властивостей класу. Безпосередньо дані розміщуються у прихованій секції (розділі) класу, а методи доступу до цих даних розміщуються у загальнодоступному розділі класу.
Класична мова C++ дозволяє встановлювати доступ до членів класу за допомогою трьох специфікаторів: private, protected, public.
5. Які типи доступу можуть мати члени класу? Які відмінності між членами класу, оголошеними з ключовими словами private, protected, public?
Члени класу можуть мати три основні типи доступу, які визначаються відповідними ключовими словами:
- private – члени класу є прихованими. Це означає, що доступ до них мають лише методи, які оголошені у класі. private-члени класу є недоступними із успадкованих класів та об'єктів цього класу;
- protected – члени класу є захищеними. Це означає, що доступ до protected-членів мають методи даного класу та методи успадкованих класів. protected-членів класу є недоступними для об'єктів цього класу;
- public - члени класу є відкритими (доступними) для всіх методів та об'єктів з усіх інших частин програмного коду.
6.Чи може клас, за його оголошенні, містити лише дані та не містити методів?
Клас може бути оголошено без методів. Такі класи містять лише дані. Щоб отримати доступ до даних у класі, які не містять методів, потрібно ці дані оголосити у розділі public . Класи без методів майже застосовуються. Якщо оголосити дані в розділі private, то отримати доступ до членів-даних класу буде неможливо.
приклад. У цьому прикладі оголошується клас без методів, що реалізує операції з датою. Клас містить внутрішні змінні (дані), що є:
class CMyDate < public: int day; // Число int month; // Місяць int year; // рік >;
Фрагмент коду демонструє роботу з класом CMyDate
// оголосити об'єкт класу MyDate CMyDate D; // Заповнити значеннями поля класу D.day = 20; D.month = 02; D.year = 2002; int t = D.year; // t = 2002 t = D.month; // t = 2
7. Приклад оголошення порожнього класу
Так, клас може бути оголошений без даних та без методів. Наприклад, нижче оголошено клас, який містить ні даних ні методів.
// клас не містить ні даних, ні методів class NoData < >;
Об'єкт такого класу також створюється.
NoData nd; // Об'єкт класу NoData
Зрозуміло, що такий клас має дуже обмежене використання. Порожній клас доцільно створювати у випадках, якщо під час створення великого проекту потрібно протестувати його більш ранню (початкову) версію, до якої деякі класи ще не розроблені та не реалізовані. Замість реального класу вказується порожній клас – заглушка. Цей порожній клас розробляється під потреби майбутнього проекту таким чином, щоб компілятор не видавав повідомлення про помилку і можна було протестувати частину коду, яка на даний момент вже написана. У цьому випадку ім'я порожнього класу вибирається таким, яким воно має бути у майбутньому проекті.
8.Приклад класу, який містить методи (функції)
Основні переваги класів виявляються за наявності методів – членів класу. За допомогою методів доступу до даних у класах можна зручно:
- ініціалізувати дані початковими значеннями;
- здійснювати перевірку на коректність внутрішніх даних за їх завдання;
- реалізовувати різні варіанти перетворення (конвертування) даних;
- реалізовувати організацію виділення пам'яті для складних типів даних, реалізованих у класах;
- виконувати різноманітні види обчислень над даними.
приклад. Модифікація класу CMyDate. Клас, який описує дату та операції над нею. Операції доступу до членів класу реалізовано за допомогою відповідних методів. Самі дані реалізовані розділ private .
Програмний код класу
class CMyDate < int day; int month; int year; public: void SetDate(int d, int m, int y); // int GetDay(void); // Повертає номер дня int GetMonth(void); // Повертає номер місяця int GetYear(void); // Повертає рік >;
Реалізація методів класу SetDate(), GetDay(), GetMonth(), GetYear()
// Встановити нову дату void CMyDate::SetDate(int d, int m, int y) < day = d; month = m; year = y; >// рахувати номер дня int CMyDate::GetDay(void) < return day; > // рахувати номер місяця int CMyDate::GetMonth(void) < return month; > // рахувати рік int CMyDate::GetYear(void) < return year; >
Використання методів класу з іншого програмного коду (наприклад, обробника події у програмах типу Windows Forms)
// Об'єкт класу CMyDate MD; // встановити значення дати 20.02.2002 MD.SetDate(20, 2, 2002); // рахувати дату int t; t = MD.GetDay(); // t = 20 t = MD.GetMonth(); // t = 2 t = MD.GetYear(); // t = 2002
9. У яких частинах класу та програми можна оголошувати реалізацію методів класу? приклад
Реалізацію методів класу можна оголошувати у класі та за межами класу.
Наприклад. У наведеному нижче програмному коді оголошується клас СMyTіме. Клас містить два методи SetTime1() і SetTime2(), які виконують однакову роботу: встановлюють новий час. Тіло (реалізація) методу SetTime1() описується у класі CMyTime. Реалізація методу SetTime2() описується поза класу. У класі описується лише прототип (декларація) методу SetTime2().
class CMyTime < private: int sec; // секунда int min; // хвилина int hour; // година public: // декларація та реалізація методу всередині класу void SetTime1(int h, int m, int s) < // Реалізація hour = h; min = m; sec = s; > // Тільки декларація (прототип) методу (метод SetTime2 є членом класу) void SetTime2(int h, int m, int s); // Реалізація методу - за межами класу >; // Реалізація методу SetTime2() поза класу void CMyTime::SetTime2(int h, int m, int s)Тіло методу, що описується за межами класу, може бути описано в іншому модулі. Як правило, у системі Microsoft Visual Studio цей модуль має розширення *.cpp. Сам клас описується в модулі з розширенням *.h .
10. Яке призначення має оператор розширення області видимості (доступу) '::'?
Програмний код методів-членів класу можна описувати в самому класі та за його межами. Якщо потрібно описати код методу, який є членом класу, то для цього використовується оператор розширення області видимості.::» . Оператор "::" визначає ім'я члена класу разом з ім'ям класу, в якому він реалізований.
11. Що таке об'єкт класу? Які відмінності між об'єктом класу та оголошенням класу? Оголошення об'єкту класу
Оголошення класу – опис формату типу даних. Цей тип даних "клас" описує дані та методи, які оперують цими даними.Опис класу – це лише опис (оголошення). І тут пам'ять для класу не виділяється.
Пам'ять виділяється лише тоді, коли клас використовується для створення об'єкта. Цей процес ще називають створенням екземпляра класу, який є фізичною сутністю класу.
Оголошення об'єкта класу (примірника) нічим не відрізняється від оголошення змінної:
Ім'я_класу ім'я_об'єкта;
За допомогою імені ім'я_об'єкта можна здійснити доступ до загальнодоступних (public) членів класу. Це здійснюється за допомогою символу ‘ . ‘ (Точка).
Можливий варіант оголошення вказівника на клас. Якщо це unmanaged-клас, то оголошення має вигляд:
Ім'я_класу * ім'я_об'єкта;
Після такого оголошення потрібно виділяти пам'ять для об'єкта класу за допомогою оператора new . Доступ до даних за вказівником здійснюється за допомогою комбінації символів '->' так само як і у випадку зі структурами.
Наприклад. Оголошення класу Worker, що описує методи та дані про працівника підприємства.
class Worker < private: // private-члени класу Worker // . public: // Public-члени класу Worker // . >;
Об'єкт класу - Це змінна типу "клас". При оголошенні об'єкта класу виділяється пам'ять цього об'єкта (змінної). Наприклад, для класу Worker можна написати наступний код
Worker w1; // об'єкт класу Worker, виділяється пам'ять даних об'єкта
З об'єкта можна мати доступ тільки до public-членів класу. Це можна здійснювати за допомогою символу ‘ . ‘ (точка) або доступу за вказівником '->' :
w1.SetName("Johnson J."); // виклик public-методу Worker * w2; // покажчик на клас Worker w2 = new Worker(); // динамічне виділення пам'яті класу w2->SetName("Jackson M."); // Виклик public-методу з класу за вказівником
12. Який тип доступу за замовчуванням мають члени класу C++?
За умовчанням, члени класу мають доступ до private . Тому, при оголошенні класу, якщо потрібно вказати private члени класу, це слово можна опустити.
Наприклад, нехай задано оголошення класу, який описує піксель на екрані монітора.
class CMyPixel < int color; // розділ private int x; int y; public: // загальнодоступні методи (розділ public) void SetXYColor(int nx, int ny, int ncolor) < x = nx; y = ny; color = ncolor; >int GetX(void) < return x; > int GetY(void) < return y; > int GetColor(void) < return color; > >;
Очевидно, на початку оголошення класу, розділ private відсутній. Це означає, що члени-дані класу color, x, y є прихованими. При створенні об'єкта класу та прямому доступі до них компілятор видасть помилку
CMyPixel MP; // оголосити об'єкт класу // MP.x = 25; - помилка - "CMyPixel::x - cannot access private member declared in CMyPixel MP.SetXYColor(25, 15, 2); // так правильно
13. Як можна реалізувати доступ до private-членів класу?
Як правило, private-члени класу є закритими. Це основна перевага інкапсуляції. Щоб змінювати значення private-членів класу, використовують методи класу, які оголошені в public-секції. У цих методах можна змінювати значення private-членів. Такий підхід використовується для забезпечення надійності збереження даних у приватних членах. У public-методах, які мають доступ до private-членів, можна реалізувати додаткові перевірки на допустимість значень.
Наприклад.
Нехай дано клас, який визначає масив із n дійсних чисел. Клас містить два приховані (private) члени даних:
Програмний код класу, який демонструє доступ до private-членів класу, наведено нижче.
class CMyArray < int n; float *A; // масив типу float, пам'ять для масиву виділяється динамічно public: CMyArray(); / / Конструктор класу, без нього ніяк void SetN(int nn); // встановити нове n, обнулити масив A int GetN(void); // рахувати n void SetAi(int index, float value); // встановити нове значення A[index] float GetAi(int index); // рахувати значення з A[index] >; / / Конструктор класу, без нього ніяк CMyArray::CMyArray() < n = 0; >// встановити нове значення n, і встановити 0 значення елементів масиву void CMyArray::SetN(int nn) < if (n>0) delete A; // звільнити пам'ять, виділену попередньо для масиву A n = nn; A = new float[n]; // Виділити пам'ять для n елементів масиву // Заповнити значеннями 0 елементи масиву for (int i=0; i // рахувати n int CMyArray::GetN(void) < return n; > // встановити нове значення A[index] void CMyArray::SetAi(int index, float value) < if (n<=0) return; if (index > n-1) return; A[index] = value; > // Вважати значення A[index] float CMyArray::GetAi(int index) < return (float) A [index]; >
Як видно з програмного коду, у класі оголошується новий елемент – конструктор класу. Це спеціальний метод, який використовується для початкової ініціалізації членів класу даних. Докладніше про конструкторів та деструкторів класу описується в темах:
Фрагмент використання класу CMyArray з іншого програмного коду:
CMyArray MA; // Створити об'єкт класу CMyArray int d; double x; MA.SetN(15); d = MA.GetN(); // d = 15 MA.SetAi(3, 2.88); x = MA.GetAi(3); // x = 2.88 x = MA.GetAi(10); // x = 0 MA.Set(20); // Перевизначення масиву d = MA.GetN(); // d = 20 x = MA.GetAi(3); // x = 0
Пов'язані теми
#19 – Створення класів та об'єктів
За уроки на практиці вивчіть використання класів та об'єктів. Ви познайомитеся з C++ ООП, навчитеся будувати класи та об'єкти на їх основі.
Відеоурок
Підписуйтесь на нашу групу в Телеграмі 🇺🇦
Створення класів
Для створення класу необхідно прописати ключове слово class і далі назву для класу. Загальноприйнято починати назви класів з літери у верхньому реєстрі, але якщо цього не зробити, то помилки не буде.
У будь-якому класі можна створювати поля (змінні), методи (функції), а також конструктори.
Створивши новий клас і помістивши туди якусь інформацію, ми можемо створювати на його основі нові об'єкти. Об'єкти мають доступ до всіх характеристик класу, які позначені модифікатором public .
Існує три модифікатори доступу:
- public - дані будуть видимі всюди, як у класі, так і поза ним;
- protected - дані будуть видимі тільки у класі, де вони були створені, а також у класах-нащадках;
- private - дані будуть видимі лише у класі, де вони були створені.
Приклад простого класу наведено нижче:
На основі такого класу ми можемо створити безліч об'єктів. Кожний об'єкт у цьому випадку буде конкретною книжкою. Для кожного об'єкта ми можемо вказати унікальні дані: кількість сторінок, назву книги та її вагу.
Щоб створити об'єкт, нам знадобиться наступний код:
Book sherlock_holms; // Створення об'єкта sherlock_holms.getInfoBook(); // Виклик методу класу
Такий код можна прописати і в одному рядку коду. Ми для наочності розбили код на дві стрічки.
Щоб брати дані з класу через об'єкт, необхідно ставити крапку та вказувати ім'я змінної або функції, яку ми хочемо використати.
Весь код буде доступний після підписки на проект!