Реферат: Знайомство з класами c++
Методична розробка
Частина 2
Класи в С++
Приватні та загальні дані
Перевантаження операторів
Успадкування. Дружні класи
Шаблони класів
Поліморфізм. Віртуальні методи
Розвиток навичок ООП:
програма «Інтерпретатор математичних функцій»
Розширення можливостей С++
Підготував: вчитель інформатики
Колківської ЗОШ-ліцею
Процик Анатолій Петрович
Колки
2006
^ §1. ЗНАЙОМСТВО З КЛАСАМИ C++
Клас являє собою головний інструментальний засіб C++ для об'єктно-орієнтованого програмування.
Клас дуже схожий на структуру, в якій згруповані елементи, що відповідають даним про деякий об'єкт, і функції, що оперують над цими даними (так звані методи).
Об'єкт представляє собою деяку сутність, наприклад телефон. Всі атрибути об'єкту дозволяє визначати саме клас C++. У разі, коли об'єктом являється телефон, клас може містити такі елементи даних, як номер і тип телефону (кнопковий або дисковий) і функції, які працюють з телефоном (набір номера, автовідповідач, тощо). Групуючи дані про об'єкт і кодуючи їх в одній змінні, ви спрощуєте процес програмування і збільшуєте можливість повторного використовування свого коду.
^ УЯВЛЕННЯ ПРО ОБ'ЄКТИ І ОБ'ЄКТНО-ОРІЄНТОВАНЕ ПРОГРАМУВАННЯ
При процедурному програмуванні програма використовує змінні для зберігання інформації про різні реально існуючі сутності, наприклад службовців, книги і навіть файли. При об'єктно-орієнтованому програмуванні потрібно фокусуватися на:
предметах, що складають деяку систему,
і операціях, які виконуються над цими предметами.
Наприклад, для об'єкту-файла ви могли б мати операції, які друкують, відображають або змінюють файл. Об’єктивно-орієнтовний підхід полягає в тому, щоб включити в клас стільки інформації про об'єкт, скільки вимагається. Виходячи з цього, можна підібрати клас, створений вами для однієї програми, і використати його в декількох різних програмах.
Клас дозволяє вашим програмам групувати дані і функції які виконують операції над цими даними. Групуванням даних і функцій для їх опрацювання називається інкапсуляцію. Функції класу називаються методами.
^ ОПИС КЛАСУ
Подібно структурі, клас C++ повинен мати унікальне ім'я, за яким слідує відкриваюча фігурна дужка, один або декілька елементів і закриваюча фігурна дужка:
class name
{
int data; // Елемент данних
void show (int); // Функция-елемент
};
Після визначення класу можна оголошувати змінні типу цього класу (так звані об'єкти), як показано нижче:
name object1, object2, …., objectN
object1, object2, …., objectN – об’єкти класу name
П
class person
{
public:
char name[64] ;
long int identif;
float oklad;
void show_person(void)
{
cout << "Имя: " << name << endl;
cout << "Идентификационный код: " << identif << endl;
cout << "Оклад: " < };
};
риклад 1: Наступне визначення створює клас person, який містить поля трьох даних і одного методу:
Метод show_person призначений для виведення значень полів name, identify та oklad на екран.
Зверніть увагу на використання специфікатора public всередині визначення класа. Елементи класа можуть бути приватними (private) і загальними (public), від чого залежить, як програми будуть звертатися до елементів класа.
В даному випадку всі елементи класу person є загальними.
void main()
{
person student[2];
for (int i=0;i<2;i++)
{
cin>>student[i].name;
cin>>student[i].identif;
cin>>student[i].oklad;
}
cout<<"-----------------"<
for (i=0;i<2;i++)
{ student[i].show_person();}
}
Результат роботи програми:
aaaa
12312345
2345.76
bbbbbbb
43212345
4187.87
----------------------
Name: aaaa
Identificat: 12312345
Oklad: 2345.76001
Name: bbbbbbb
Identificat: 43212345
Oklad: 4187.870117
Зліва подано найпростішу програму, яка використовує об’єкти класу person
Елементи масиву student[2] мають тип person.
Оскільки поля name, identif та oklad загальнодоступні (описані в розділі public), то їм можна надати значення за відомими нам правилами (в нашому випадку ввести з клавіатури)
Використовуючи метод show_person(); програма виводить значення усіх полів на екран.
Висновок
Більшість програм на C++ відображають реальні існуючі об'єкти. Об'єкти є деякими сутностями, наприклад автомобілем, собакою, годинником і т.д. Звичайно об'єкт має декілька атрибутів і операцій, які програма повинна виконувати над цими атрибутами. Наприклад, у разі годинника властивості можуть включати поточний час і час будильника. Операції такого об'єкту могли б містити установку часу, установку будильника або виключення будильника. При об'єктно-орієнтованому програмуванні ваші програми фокусуються на об'єктах і операціях над цими об'єктами.
^ §2. ОПИС МЕТОДІВ КЛАСУ ПОЗА КЛАСОМ.
В програмі минулого заняття функція-метод void show_person(void) була описана всередині опису класу person. При такому підході у випадку збільшення кількості функцій-методів їх опис всередині класу може внести безпорядок в опис самого класу. В якості альтернативи можна помістити прототип функції всередині класу, а потім описати функцію поза класом. Для програми минулого заняття клас person можна описати так:
class person
{
public:
char name[64] ;
long int identif;
float oklad;
void show_person(void);
};
Void person:: show_person(void)
{
cout << "Имя: " << name << endl;
cout << "Идентификационный код: " << identif << endl;
cout << "Оклад: " < }
Так як різні класи можуть використовувати функції з однаковими іменами (про це буде говоритися в наступних уроках), то імена функцій, що визначаються поза класом необхідно помічати іменем самого класу та оператором глобального присвоєння (::).
В даному прикладі опис функції show_person поза класом має вигляд:
Void person:: show_person(void)
А не void show_person(void)
Змінивши опис класу person (так як показано зліва), але не міняючи код головної функції main() програми минулого заняття, результат її роботи також не зміниться.
Приклад2.
Утворити клас dog,який містить поля даних про породу (breed), вагу (weight) та висоту (height) собаки та функції show_breed. Программа повинна визначати функцію класа поза описом самого класа. Потім програма створює два об’єкта типу dog і за допомогою методу show_breed виводить інформацію про кожного собаку:
Висновок
Класи C++ дозволяють вашим програмам групувати дані об'єкту і функції об'єкту (методи), які оперують з цими даними, в одній змінні. Є дві можливості визначення методів об'єкту. Перша полягає в тому, що ви можете включити весь код функції всередину визначення класу. Не дивлячись на те що включення коду методу у визначення класу може представлятися зручним, проте, коли класи стають складніше і включають декілька методів, оператори функцій можуть вносити безлад у визначення класів. Таким чином, багато програм визначають оператори функції зовні класу. У визначення класу програма повинна включати прототип функції, який указує ім'я функції, тип значення, що повертається, і типи параметрів.
Для визначення функції зовні визначення класу ваша програма повинна передувати визначенню функції ім'ям класу і оператором глобального дозволу
^ §3. ПРИВАТНІ (PRIVATE) ТА ЗАГАЛЬНІ (PUBLIC) ДАНІ ХОВАННЯ ІНФОРМАЦІЇ
Як ви вже знаєте, клас містить дані і методи (функції). Для використовування класу програми просто повинні знати інформацію, яку зберігає клас (його елементи даних) і методи, які маніпулюють даними (функції). Вашим програмам не вимагається знати, як працюють методи. Більше того, програми повинні знати тільки, яку задачу виконують методи. Наприклад, припустимо, що у вас є клас file. В ідеалі ваші програми повинні знати тільки те, що цей клас забезпечує методи file.print, який друкує копію поточного файла, або file.delete, який видаляє файл. Вашій програмі не вимагається знати, як ці два методи працюють. Іншими словами, програма повинна розглядати клас як "чорний ящик". Програма знає, які методи необхідно викликати і які параметри їм передати, але програма нічого не знає про реальну роботу, що виконується усередині класу (в "чорному ящику").
Ховання інформації є процесом, в результаті якого програмі надається тільки мінімальна інформація, необхідна для використання класу. Приватні і загальні елементи класу допомагають вам отримати інформацію, приховану усередині вашої програми.
^ ЗАГАЛЬНІ ДАНІ
На минулому уроці кожний із створених класів використовував мітку PUBLIC, що використовується для оголошення всіх елементів класу загальними, тобто видимими для всієї програми. Таким чином, програма могла б безпосередньо звернутися до будь-якого елемента класу, використовуючи оператор «крапку». Наприклад, командою happy.weight = 58 ми до поля weight об’єкта happy звертаємось через оператор «крапка» і надаємо йому значення 58 безпосередньо командою присвоєння. Це можливо тому, що поле weight загальне (помічене міткою PUBLIC).
^ ПРИВАТНІ ДАНІ
При створенні класу дуже часто використовуються елементи, значення яких використовуються тільки усередині класу. Звертатися до них самій програмі немає необхідності. Такі елементи є приватними (PRIVATE), і їх слідує приховувати від програми. Якщо ви не використовуєте мітку PUBLIC, то за умовчанням C++ має на увазі, що всі елементи класу є приватними (PRIVATE). Ваші програми не можуть звертатися до приватних елементів класу, використовуючи оператор «крапку» (як у програмі попереднього уроку).
До приватних елементів класу можуть звертатися тільки елементи самого класу, а саме через методи класу.
Змінемо опис класу person описаного в §2
class person
{
private:
char name[64] ;
long int identif;
float oklad;
public:
void show_person(void);
};
Запустивши програму на виконання компілятор покаже помилку в блоці:
for (int i=0;i<2;i++)
{
cin>>student[i].name;
cin>>student[i].identif;
cin>>student[i].oklad;
}
Це означає, що до поля name (а також і identif та oklad) безпосередньо звернутися використовуючи оператор «крапка» заборонено, так як ці поля приватні.
Надати значень цим полям можна через відповідні методи. Назвемо метод для введення значень з клавіатури приватним полям name, identif та oklad через read_person.
Тоді опис класу person та перша програма §2 матиме вигляд:
#include
#include
class person
{
private:
char name[64];
long int identif;
float oklad;
public:
void show_person(void);
void read_person(char *,long int, float);
};
void person::show_person(void)
{
cout<<"Name: "<
cout << "Identificat: "<
cout << "Oklad: " <
}
void person::read_person(char *n, long int id, float ok)
{ strcpy(name,n); identif = id; oklad = ok; }
void main()
{
person student[3];
char nam[64];
long int ident;
float okl;
for (int i=0;i<3;i++)
{
cin>>nam;
cin>>ident;
cin>>okl;
student[i].read_person(nam,ident,okl);
}
cout<<"----------------------"<
for (i=0;i<3;i++)
{ student[i].show_person();}
}
Отже, захистити елементи класу від прямого доступу до них можна, зробивши їх приватними. При цьому програма не може безпосередньо надавати значення таким елементам, використовуючи оператор «крапку». Замість того щоб надати їм значення (ініціалізувати об’єкт класу person) програма повинна викликати метод класу. Запобігаючи прямому доступу до елементів даних, таким чином, можна гарантувати, що їм завжди будуть надаватися допустимі значення.
Наприклад, ідентифікаційний код складається з 9-ти цифр. Тобто 100000000
а заробітна плата – 500
^ Виходячи з цього метод read_person можна переписати так:
З
int person::read_person(char *n, long int id, float ok)
{ if (id>=100000000&&id<=999999999&&ok>=500&&ok<=5000)
{ strcpy(name,n); identif = id; oklad = ok;return (1);}
else {cout<<"Error!\n"; return (-1);} }
верніть увагу, що функція read_person повертає в програму 1, якщо дані введено вірно і (-1), якщо дані недопустимі (при цьому виводиться повідомлення "Error!”. Тому функція read_person має тип int
^ Враховуючи це введення даних з клавіатури в головній програмі матиме вигляд:
for (int i=0;i<3;)
{
cin>>nam; cin>>ident; cin>>okl;
if (student[i].read_person(nam,ident,okl)==1) i++;
}
Лічильник і збільшується на одиницю (і++) лише в тому випадку, коли дані введені правильно. Отже, програма робитиме запит про введення даних до тих пір, поки небуде вірно введено інформацію про трьох працівників.
Методи класу, що забезпечують програмі доступ до приватних даних називаються інтерфейсними функціями.
У нашому прикладі обидві функції show_person та read_person – інтерфейсні, бо обробляють приватні дані.
Висновок
Для зниження кількості можливих помилок обмежують доступ програм до даних класу, визначаючи елементи даних класу як приватні. Таким чином, програма не зможе звернутися до елементів даних класу, використовуючи оператор крапку. Натомість клас повинен визначати інтерфейсні функції, за допомогою яких програма може привласнювати значення приватним елементам. Інтерфейсні функції у свою чергу, можуть досліджувати і скоректувати значення, які програма намагається привласнити. Одна з найбільш широко використовуваних операцій, яку програми виконують при створенні об'єкту, є ініціалізацією елементів даних об'єкту.
^ §4 КОНСТРУКТОР ТА ДЕСТРУКТОР
При створенні об'єктів однією з найбільш широко використовуваних операцій є ініціалізація елементів даних об'єкту (на попередньому уроці цю функцію виконував метод read_person).
Проте, щоб спростити процес ініціалізації елементів даних класу, в C++ є можливість використовувати так званий конструктор, який автоматично запускається для кожного створюваного об'єкту, ініціалізуючи його.
Конструктор є методом класу, який полегшує вашим програмам ініціалізацію елементів даних класу.
Конструктор має таке ж ім'я, як і клас.
Конструктор не має значення, що повертається.
Кожного разу, коли ваша програма створює змінну класу, C++ викликає конструктор класу, якщо конструктор існує.
Конструктор можна уявити як функцію, яка допомагає будувати (конструювати) об'єкт.
^ СТВОРЕННЯ ПРОСТОГО КОНСТРУКТОРА
Конструктор є методом класу, який має таке ж ім'я, як і клас. Наприклад, якщо ви використовуєте клас з ім'ям person, конструктор також буде мати ім'я person. Подібно цьому, для класу з ім'ям dogs конструктор буде мати ім'я dogs. Якщо ваша програма визначає конструктор, C++ буде автоматично викликати його кожного разу, коли ви створюєте об'єкт. Наступна програма створює клас з ім'ям person. Програма також визначає конструктор з ім'ям person який привласнює початкові значення об'єкту. Проте конструктор не повертає ніякого значення, не дивлячись на те, що він не оголошується як void. Тип значення, що повертається, для конструктора не вказується:
#include
#include
class person
{
конструктор
private:
char name[64];
long int identif;
float oklad;
public:
void show_person(void);
person(char *,long int, float);
};
void person::show_person(void)
{cout<<"Name: "<
cout << "Identificat: "<
cout << "Oklad: " <
person::person(char *n, long int id, float ok)
{strcpy(name,n); identif = id; oklad = ok;}
void main()
{
char nam[64];
long int ident;
float okl;
cin>>nam;
cin>ident;
cin>>okl;
person student1(nam,ident,okl);
person student2("Петров",987654321,1000);
cout<<"----------------------"<
student1.show_person();
student2.show_person();
}
Результат роботи програми
Иванов
123456789
3456
----------------------
Name: Иванов
Identificat: 123456789
Oklad: 3456
Name: Петров
Identificat: 987654321
Oklad: 1000
Н
person::person(char *name, long int identif, float oklad)
{ strcpy(person::name,name);
person::identif = identif;
person::oklad = oklad; }
аша програма створює два об’єкти класу person: student1 та student2. Причому конструктор відразу при створенні ініціалізує їх: student1 значеннями деяких змінних, введених з клавіатури, а аб’єкт student2 – деякими сталими.
^ ВИКОРИСТАННЯ ОПЕРАТОРА ГЛОБАЛЬНОГО ДОЗВОЛУ ДЛЯ ЕЛЕМЕНТІВ КЛАСУ
В якості імен параметрів для методів (в тому числі і для конструктора) можна використовувати імена елементів класу. Щоправда, щоб уникнути конфлікту між іменами параметрів і іменами елементів класу перед іменем елементу класу ставиться ім'я класу і оператором глобального дозволу.
Висновок
Конструктор представляє собою спеціальну функцію, яку C++ автоматично викликає кожного разу при створенні об'єкту. Звичайне призначення конструктора полягає в ініціалізації елементів даних об'єкту. Конструктор має таке ж ім'я, як і клас. Наприклад, клас з ім'ям file використовує конструктор з ім'ям file. Ви визначаєте конструктор усередині своєї програми так само, як і будь-який метод класу. Єдина відмінність полягає в тому, що конструктор не має значення, що повертається. Коли ви пізніше оголошуєте об'єкт, ви можете передавати параметри конструктору, якими ініціалізується об’єкт.
^ КОНСТРУКТОРИ І ПАРАМЕТРИ ЗА УМОВЧАННЯМ
Як відомо C++ дозволяє вказувати значення за замовченням для параметрів функції. Якщо користувач не вказує яких-небудь параметрів, функція буде використовувати значення за замовчанням. Конструктор не є виключенням. Програма може вказати для нього значення за умовчанням так само, як і для будь-якої іншої функції. Наприклад, наступний конструктор person використовує за умовчанням значення окладу рівним 100, якщо програма не вказує оклад при створенні об'єкту. Проте програма повинна вказати ім'я службовця і його ідентифікаційний код:
#include
#include
class person
{
private:
char name[64]; long int identif; float oklad;
public:
person(char *,long int, float);void show_person(void);
};
void person::show_person(void)
{ cout<<"Name: "<
cout << "Identificat: "<
cout << "Oklad: " <
person::person(char *name, long int identif, float oklad = 100)
{ strcpy(person::name,name);
person::identif = identif;
person::oklad = oklad; }
void main()
{
char nam[64];
long int ident;
cin>>nam;
cin>>ident;
person student1(nam,ident);
person student2("Петров",987654321,1000);
cout<<"----------------------"<
student1.show_person();
student2.show_person();
}
Об’єкт student1 отримає для поля oklad значення 100 за замовчуванням. Тоді як полю oklad об’єкта student2 буде привласнено значення 1000.
ДЕСТРУКТОР
Деструктор автоматично запускається кожного разу, коли програма знищує об'єкт. В наступних уроках ви взнаєте, як створити списки об'єктів, які збільшуються або зменшуються у міру виконання програми. Щоб створити такі динамічні списки, ваша програма для зберігання об'єктів розподіляє пам'ять динамічно (що ви ще не навчилися робити). Ви можете створювати і знищувати об'єкти в процесі виконання програми. В таких випадках має сенс застосування деструктора.
Кожна із створених вами до цих пір програм створювала об'єкти в самому початку свого виконання, просто оголошуючи їх. При завершенні програм C++ знищував об'єкти. Якщо ви визначаєте деструктор усередині своєї програми, C++ буде автоматично викликати деструктор для кожного об'єкту, коли програма завершується (тобто коли об'єкти знищуються). Подібно конструктору, деструктор має таке ж ім'я, як і клас об'єкту. Проте у разі деструктора перед його ім’ям ставиться символ тильди (~), як показано: ~person(void)
На відміну від конструктора ви не можете передавати параметри деструктору.
^ Опис деструктора для об’єкта класу person має вигляд:
void person::~ person (void)
{
cout << "Уничтожение объекта для "<}
В даному випадку деструктор просто виводить на екран повідомлення про те, що C++ знищує об'єкт. Коли програма завершується, C++ автоматично викликає деструктор для кожного об'єкту
^ §5. ПЕРЕВАНТАЖЕННЯ ОПЕРАТОРІВ
Як ви знаєте, тип змінної визначає набір значень, які вона може зберігати, а також набір операцій, які можна виконувати над цією змінною. Наприклад, над значенням змінної типу int ваша програма може виконувати дадовання, віднімання, множення і ділення. З другого боку, використовування оператора плюс для додавання двох рядків позбавлено всякого сенсу. Коли ви визначаєте в своїй програмі клас, то по суті ви визначаєте новий тип. А якщо так, C++ дозволяє вам визначити операції, відповідні цьому новому типу.
Перевантаження оператора полягає в зміні сенсу оператора (наприклад, оператора плюс (+), який звичайно в C++ використовується для додавання) при використанні його з певним класом. В даному уроці ви визначите клас string і перенавантажуватимете оператори плюс і мінус. Для об'єктів типу string оператор плюс буде додавати вказані символи до поточного вмісту рядка. Так само оператор мінус буде видаляти кожне входження вказаного символа з рядка.
Перевантаження операторів може спростити найбільш загальні операції класу і поліпшити читаємість програми.
^ ПЕРЕВАНТАЖЕННЯ ОПЕРАТОРІВ ПЛЮС І МІНУС
Коли ви перенавантажуєте оператор для якого-небудь класу, то сенс даного оператора не змінюється для змінних інших типів. Наприклад, якщо ви перенавантажуєте оператор плюс для класу string, то сенс цього оператора не змінюється, якщо необхідно скласти два числа. Коли компілятор С++ зустрічає в програмі оператор, то на підставі типу змінни він визначає ту операцію, яка повинна бути виконана.
Нижче приведено визначення класу, що створює клас string. Цей клас містить один елемент даних, який представляє собою власне символьний рядок. Крім того, цей клас містить декілька різних методів і поки не визначає яких-небудь операторів:
#include
#include
class string
{
public:
string(char *); //Конструктор
void str_append(char *);
void chr_minus(char);
void show_string(void);
private:
char data[256] ;
};
string::string(char *str)
{ strcpy(data, str);}
void string::str_append(char *str)
{ strcat(data, str); }
void string::chr_minus(char letter)
{
char temp[256] ;
for (int i = 0, int j = 0; data[i]; i++)
if (data[i] != letter) temp[j++] = data[i];
temp[j] = NULL;
strcpy(data, temp);
}
void string::show_string(void)
{ cout << data << endl; }
void main(void)
{
string title( "Учимся программировать на языке C++");
string lesson("Перегрузка операторов");
title.show_string() ;
title.str_append(" я учусь!");
title.show_string();
lesson.show_string();
lesson.chr_minus('р') ;
lesson.show_string();
}
Результат роботи програми:
Учимся программировать на языке C++
Учимся программировать на языке C++ я учусь!
Перегрузка операторов
Пеегузка опеатоов
Як бачите, програма використовує функцію str_append для додавання символів до рядкової змінни title. Програма також використовує функцію ch_ minus для видалення кожної букви "р" з символьного рядка lesson. В даному випадку програма використовує виклики функції для виконання цих операцій. Проте, використовуючи перевантаження операторів, програма може виконувати ідентичні операції за допомогою операторів плюс (+) і мінус (-). Про це буде вестися мова у наступному параграфі.
^ §6. ПЕРЕВАНТАЖЕННЯ ОПЕРАТОРІВ.
ВИКОРИСТАННЯ КЛЮЧОВОГО СЛОВА OPERATOR
При перевантаженні оператора можна використовувати ключове слово C++ operator разом з прототипом і визначенням функції, щоб повідомити компілятор C++, що клас буде використовувати цей метод як оператор. Наприклад, наступне визначення класу використовує ключове слово operator, щоб призначити оператори плюс і мінус функціям st_ append і ch_ minus усередині класу string (див попередній урок):
#include
#include
class string
{
public:
string(char *); //Конструктор
void operator+(char *);
void operator-(char);
void show_string(void);
private:
char data[256] ;
};
string::string(char *str)
{ strcpy(data, str);}
void string::operator+(char *str)
{ strcat(data, str); }
void string::operator-(char letter)
{
char temp[256] ;
for (int i = 0, int j = 0; data[i]; i++)
if (data[i] != letter)
temp[j++] = data[i];
temp[j] = NULL;
strcpy(data, temp);
}
void string::show_string(void)
{ cout << data << endl; }
void main(void)
{
string title( "Учимся программировать на языке C++");
string lesson("Перегрузка операторов");
title.show_string() ;
title + " я учусь!"; title.show_string();
lesson.show_string();
lesson - 'р'; lesson.show_string();
}
Результат роботи програми:
Учимся программировать на языке C++
Учимся программировать на языке C++ я учусь!
Перегрузка операторов
Пеегузка опеатоов
В даному випадку синтаксис операторів «+» та «–» трохи незвичний. Зазвичай оператор плюс використовується у виразі, який повертає результат, наприклад, як в операторі some_str = title + "текст ";. Коли ви визначаєте оператор, C++ надає вам повну свободу відносно поведінки оператора. Проте основна ціль при перевантаженні операторів полягає в тому, щоб спростити розуміння програм. Тому наступна програма трохи змінює попередню програму, щоб дозволити їй виконувати операції над змінними типу string, використовуючи синтаксис, який більш узгоджується із стандартними операторами привласнення:
#include
#include
class string
{
public:
string(char *); //Конструктор
char *operator+(char *);
char *operator-(char);
void show_string(void);
private:
char data[256] ;
};
string::string(char *str)
{ strcpy(data, str);}
char *string::operator+(char *str)
{ strcat(data, str);
return data; }
char *string::operator-(char letter)
{
char temp[256] ;
for (int i = 0, int j = 0; data[i]; i++)
if (data[i] != letter)
temp[j++] = data[i];
temp[j] = NULL;
strcpy(data, temp);
return data;
}
void string::show_string(void)
{ cout << data << endl; }
void main(void)
{
string title( "Учимся программировать на языке C++");
string lesson("Перегрузка операторов");
title.show_string() ;
title = title + " я учусь!"; title.show_string();
lesson.show_string();
lesson = lesson - 'р'; lesson.show_string();
}
Змінивши перевантажені оператори плюс і мінус так, щоб вони повертали покажчик на символьний рядок, програма може тепер використовувати ці оператори в звичному для оператора привласнення вигляді:
title = title + " я учусь!"; та
lesson = lesson - 'р'
П
int string::operator==(string str)
{
for (int i = 0; data[i] == str.data[i]; i++);
if (data[i] == NULL && str.data[i] == NULL) return 1;
else return 0;
}
ЕРЕ^ ВАНТАЖЕННЯ ОПЕРАТОРА ПОРІВНЯННЯ
Найбільш загальною операцією є перевірка, чи є два об'єкти однаковими. Використовуючи перевантаження, ваші програми можуть перенавантажувати оператори рівності (==), нерівності (!=) або інші оператори порівняння. Наступна приклад додає новий оператор в клас string, який перевіряє, чи рівні два об'єкти string.
Використовуючи перевантаження оператора ==, ваша програма може перевіряти, чи містять рядкові об'єкти однакові рядки, як показано нижче:
if (title == lesson) …….
^ ОПЕРАТОРИ, ЯКІ HE МОЖНА ПЕРЕНАВАНТАЖУВАТИ
В загальному випадку ваші програми можуть перенавантажувати майже всі оператори С++. Нижче перераховані оператори, які C++ не дозволяє перенавантажувати.
Оператори C++, які ваші програми не можуть перенавантажувати.
Оператор
Призначення
Приклад
.
Вибір елемента
object.member
.*
Покажчик на елемент
object.*member
::
Дозвіл області видимості
classname::member
?:
Умовний оператор порівняння
з = (а > b) ? а : b;
Підсумок
Перевантаження операторів — це можливість призначати новий сенс операторам при використанні їх з певним класом. Використовуючи перевантаження операторів, ви можете підвищити легкість для читання ваших програм і полегшити їх розуміння, виражаючи операції класу більш зрозумілим чином. Необхідно усвідомити наступне:
Щоб перенавантажувати оператор, ви повинні визначити клас, якому оператор буде призначений.
Коли ви перенавантажуєте оператор, перевантаження діє тільки для класу, в якому він визначається.
Щоб перенавантажувати оператор класу, використовуйте ключове слово C++ operator для визначення методу класу, який C++ викликає, кожного разу, коли змінна класу використовує оператор.
C++ не дозволяє вашим програмам перенавантажувати оператор вибору елемента (.), оператор покажчика на елемент (.*), оператор дозволу області глобальної видимості (::) і умовний оператор порівняння (?:).
^ §7. СТАТИЧНІ ФУНКЦІЇ І ЕЛЕМЕНТИ ДАНИХ
До цього моменту кожний створюваний вами об'єкт мав свій власний набір елементів даних. Залежно від призначення програми можуть бути ситуації, коли об'єкти одного і того ж класу повинні спільно використовувати один або декілька елементів даних. Наприклад, припустимо, що ви пишете програму платежів, яка відстежує робочий час для 1000 службовців. Для визначення податкової ставки програма повинна знати умови, в яких працює кожний службовець. Хай для цього використовується змінна класу state of work. Проте, якщо всі службовці працюють в однакових умовах, ваша програма могла б спільно використовувати цей елемент даних для всіх об'єктів типу person. Таким чином, ваша програма зменшує необхідну кількість пам'яті, викидаючи 999 копій однакової інформації. Для сумісного використовування елемента класу ви повинні оголосити цей елемент як static (статичний). Цей урок розглядає що ви повинні виконати для сумісного використовування елемента класу декількома об'єктами.
^ В першу чергу необхідно освоїти такі моменти:
C++ дозволяє мати об'єкти одного і того ж типу, які спільно використовують один або декілька елементів класу.
Якщо ваша програма привласнює значення спільно використовуваному елементу, то всі об'єкти цього класу відразу ж дістають доступ до цього нового значення.
^ СУМІСНЕ ВИКОРИСТОВУВАННЯ ЕЛЕМЕНТА ДАНИХ
Звичайно об'єкти певного класу при створенні одержує свій власний набір елементів даних. Проте можливі такі ситуації, при яких об'єктам одного і того ж класу необхідно спільно використовувати один або декілька елементів даних (статичні елементи даних). В таких випадках елементи даних оголошуються як загальні або приватні, а потім перед описом типу ставиться ключове слово static, як показано нижче:
class class_name
{
private:
static int value;
……
};
int class_name::value;
Після оголошення класу (class_name) елемент (value) оголошують як глобальну змінну зовні класу:
int class_name::value;
Наступна програма визначає клас books, що спільно використовує елемент page_count, який явився однаковим для всіх об'єктів (книг) класу (books). Якщо програма змінює значення цього елемента, зміна відразу ж виявляється у всіх об'єктах класу:
#include
#include
class book
{
public:
book(char *, char *, float);
void show_book(void);
void set_pages(int) ;
private:
static int page_count;
char title[64];
char author[64];
float price;
};
int book::page_count;
void book::set_pages(int pages)
{ page_count = pages; }
book::book(char *title, char *author, float price)
{
strcpy(book::title, title);
strcpy(book::author, author);
book::price = price;
}
void book:: show_book (void)
{
cout << "Заголовок: " << title << endl;
cout << "Автор: " << author << endl;
cout << "Цена: " << price << endl;
cout << "Страницы: " << page_count << endl;
}
void main(void)
{
book programming( "Изучаем C++", "Глинський", 22.95);
book word( "Word для Windows", "Ряжский", 19.95);
word.set_pages(256);
programming.show_book ();
word.show_book() ;
cout << endl << "Изменение page_count " << endl;
programming.set_pages(512);
programming.show_book();
word.show_book();
}
Як бачите, клас оголошує page_count як static int. Відразу ж за визначенням класу програма оголошує елемент page_count як глобальну змінну. Коли програма змінює елемент page_count, зміна відразу ж виявляється у всіх об'єктах класу book.
Нижче показано результат даної програми:
Заголовок: Изучаем C++
Автор: Глинський
Цена: 22.950001
Страницы: 256
Заголовок: Word для Windows
Автор: Ряжский
Цена: 19.950001
Страницы: 256
Изменение page_count
Заголовок: Изучаем C++
Автор: Глинський
Цена: 22.950001
Страницы: 512
Заголовок: Word для Windows
Автор: Ряжский
Цена: 19.950001
Страницы: 512
Підсумок
Залежно від вашої програми можливі ситуації, коли вам потрібно буде спільно використовувати певні дані декількома екземплярами об'єкту. Для цього необхідно оголосити такий елемент як static. Далі цей елемент необхідно оголосити зовні класу як глобальну змінну. Будь-які зміни, які ваша програма робить з цим елементом, будуть негайно відображені в об'єктах даного класу.
^ ВИКОРИСТАННЯ ЕЛЕМЕНТІВ З АТРИБУТАМИ PUBLIC STATIC,
ЯКЩО ОБ'ЄКТИ НЕ ІСНУЮТЬ
Як тільки що говорилося, при оголошенні елемента класу як static цей елемент спільно використовується всіма об'єктами даного класу. Проте можливі ситуації, коли програма ще не створила об'єкт, але їй необхідно використовувати елемент. Для використовування елемента ваша програма повинна оголосити його як public і static. Наприклад, наступна програма використовує елемент page_count з класу book, навіть якщо об'єкти цього класу не існують:
#include
#include
class book
{
public:
static int page_count;
private:
Результат роботи програми:
Текущее значение page_count равно 256
char title [64];
char author[64];
float price;
};
int book::page_count;
void main(void)
{
book::page_count = 256;
cout << "Текущее значение page_count равно "
<
}
В даному випадку, оскільки клас визначає елемент класу page_count як public, програма може звернутися до цього елемента класу, навіть якщо об'єкти класу book не існують.
^ ВИКОРИСТОВУВАННЯ СТАТИЧНИХ ФУНКЦІЙ-ЕЛЕМЕНТІВ
Попередня програма ілюструвала використовування статичних елементів даних. Так само C++ дозволяє визначити статичні функції-елементи (методи). Якщо ви створюєте статичний метод, ваша програма може викликати такий метод, навіть якщо об'єкти не були створені. Наприклад, якщо клас містить метод, який може бути використаний для даних зовні класу, ви могли б зробити цей метод статичним. Нижче приведений клас menu, який використовує esc-послідовність драйвера ANSI для очищення екрану дисплея. Якщо у вашій системі встановлений драйвер ANSI.SYS, ви можете використовувати метод clear screen для очищення екрану. Оскільки цей метод оголошений як статичний, програма може використовувати його, навіть якщо об'єкти типу menu не існують. Наступна програма використовує метод clear screen для очищення екрану дисплея:
#include
class menu void main(void)
{ {
public: menu::clear_screen();
static void clear_screen(void); }
private:
int number_of_menu_options;
};
void menu::clear_screen(void)
{ cout << '\033' << "[2J"; }
Оскільки програма оголошує елемент clear_screen як статичний, вона може використовувати цю функцію для очищення екрану, навіть якщо об'єкти типу menu не існують. Функція clea_ screen використовує
esc-послідовність ANSI Esc[2J для очищення екрану.
Отже, у міру створення методів класу можливі ситуації, коли функція, створена для використовування класом, може бути корисна для операцій, які не включають об'єкти класу. Наприклад, в класі menu була визначена функція clear_screen. Якщо клас містить метод, який буде використовуватись зовні об'єкту класу, то перед його прототипом ставиться ключове слово static і оголошуэться цей метод як public:
public:
static void clear screen(void);
Усередині програми для виклику такої функції використовується оператор глобального дозволу, як показано нижче:
menu::clear_screen();
^ § 8. УСПАДКУВАННЯ
Ціль об'єктно-орієнтованого програмування полягає в повторному використовуванні створених класів, що економить час і сили. Якщо ви вже створили деякий клас, то можливі ситуації, що новому класу потрібні деякі або навіть всі особливості вже існуючого класу, і необхідно додати один або декілька елементів даних або функцій. В таких випадках C++ дозволяє будувати новий об'єкт, використовуючи характеристики вже існуючого об'єкту. Іншими словами, новий об'єкт буде успадковувати елементи існуючого класу (базового класу). Коли будується новий клас з існуючого, цей новий клас часто називається похідним класом.
Необхідно усвідомити наступні основні концепції:
Якщо програми використовують успадкування, то для породження нового класу необхідний базовий клас, тобто новий клас успадковує елементи уже існуючого базового класу.
Для ініціалізації елементів похідного класу програма повинна викликати конструктори базового і похідного класів.
Використовуючи оператор крапку, програми можуть легко звертатися до елементів базового і похідного класів.
На додаток до загальних (public) (доступним всім) і приватних (private) (доступним методам класу) елементів C++ надає захищені (protected) елементи, які доступні базовому і похідному класам.
Для вирішення конфлікту імен між елементами базового
еще рефераты
Еще работы по разное