на тему рефераты Информационно-образоательный портал
Рефераты, курсовые, дипломы, научные работы,
на тему рефераты
на тему рефераты
МЕНЮ|
на тему рефераты
поиск
Розробка власного класу STRING
i>struct string {

char* p;

int size; // розмір вектора, на який указує p

string (int size) { p = new char [size=sz]; }

~string () { delete p; }

string& operator= (const string&);

string (const string&);

};

string:: string (const string& a)

{

p=new char [size=sz];

strcpy (p,a. p);

}

Ініціалізація об'єкта типу X відбувається за допомогою конструктора X (const X&). Особливо це важливо в тих випадках, коли визначений деструктор. Якщо в класі X є нетривіальний деструктор, наприклад, що робить звільнення об'єкта у вільній пам'яті, найімовірніше, у цьому класі буде потрібно повний набір функцій, щоб уникнути копіювання об'єктів по членах:

class X {

// ...

X (something); // конструктор, що створює об'єкт

X (const X&); // конструктор копіювання

operator= (const X&); // присвоювання:

// видалення й копіювання

~X (); // деструктор

};

Є ще два випадки, коли доводиться копіювати об'єкт: передача параметра функції й повернення нею значення. При передачі параметра неініціалізована змінна, тобто формальний параметр ініціалізується. Семантика цієї операції ідентична іншим видам ініціалізації. Теж відбувається й при поверненні функцією значення, хоча цей випадок не такий очевидний. В обох випадках використається конструктор копіювання:

string g (string arg)

{

return arg;

}

main ()

{

string s = "asdf";

s = g (s);

}

Очевидно, після виклику g () значення s повинне бути "asdf". Не важко записати в параметр s копію значення s, для цього треба викликати конструктор копіювання для string. Для одержання ще однієї копії значення s по виходу з g () потрібний ще один виклик конструктора string (const string&). Цього разу ініціалізується тимчасова змінна, котра потім привласнюється s. Для оптимізації одну, але не обидві, з подібних операцій копіювання можна забрати. Природно, тимчасові змінні, використовувані для таких цілей, знищуються належним чином деструктором string:: ~string ().

Якщо в класі X операція присвоювання X:: operator= (const X&) і конструктор копіювання X:: X (const X&) явно не задані програмістом, що бракують операції будуть створені транслятором. Ці створені функції будуть копіювати по членах для всіх членів класу X. Якщо члени приймають прості значення, як у випадку комплексних чисел, це, те, що потрібно, і створені функції перетворяться в просте й оптимальне поразрядное копіювання. Якщо для самих членів визначені користувальницькі операції копіювання, вони й будуть викликатися відповідним чином:

class Record {

string name, address, profession;

// ...

};

void f (Record& r1)

{

Record r2 = r1;

}

Тут для копіювання кожного члена типу string з об'єкта r1 буде викликатися string:: operator= (const string&).

У нашому першому й неповноцінному варіанті строковий клас має член-вказівник і деструктор. Тому стандартне копіювання по членах для нього майже напевно невірно. Транслятор може попереджати про такі ситуації.

1.15.6 Інкремент і декремент

Нехай є програма з розповсюдженою помилкою
:

void f1 (T a) // традиційне використання

{

T v [200];

T* p = &v [10];

p--;

*p = a; // Приїхали: `p' настроєні поза масивом,

// і це не виявлено

++p;

*p = a; // нормально

}

Природне бажання замінити вказівник p на об'єкт класу CheckedPtrTo, по якому непряме звертання можливо тільки за умови, що він дійсно вказує на об'єкт. Застосовувати інкремента і декремента до такого вказівника буде можна тільки в тому випадку, що вказівник настроєний на об'єкт у границях масиву й у результаті цих операцій вийде об'єкт у границях того ж масиву:

class CheckedPtrTo {

// ...

};

void f2 (T a) // варіант із контролем

{

T v [200];

CheckedPtrTo p (&v [0],v, 200);

p--;

*p = a; // динамічна помилка:

// 'p' вийшов за межі масиву

++p;

*p = a; // нормально

}

Інкремент і декремент є єдиними операціями в С++, які можна використати як постфіксні так і префіксні операції. Отже, у визначенні класу CheckedPtrTo ми повинні передбачити окремі функції для префіксних і постфіксних операцій інкремента й декремента:

class CheckedPtrTo {

T* p;

T* array;

int size;

public:

// початкове значення 'p'

// зв'язуємо з масивом 'a' розміру 's'

CheckedPtrTo (T* p, T* a, int s);

// початкове значення 'p'

// зв'язуємо з одиночним об'єктом

CheckedPtrTo (T* p);

T* operator++ (); // префіксна

T* operator++ (int); // постфіксна

T* operator-- (); // префіксна

T* operator-- (int); // постфісна

T& operator* (); // префіксна

};

Параметр типу int служить вказівкою, що функція буде викликатися для постфісної операції. Насправді цей параметр є штучним і ніколи не використається, а служить тільки для розходження постфіксної і префіксної операції. Щоб запам'ятати, яка версія функції operator++ використається як префіксна операція, досить пам'ятати, що префіксна є версія без штучного параметра, що вірно й для всіх інших унарних арифметичних і логічних операцій. Штучний параметр використається тільки для "особливих" постфіксних операцій ++ і - -. За допомогою класу CheckedPtrTo приклад можна записати так:

void f3 (T a) // варіант із контролем

{

T v [200];

CheckedPtrTo p (&v [0],v, 200);

p. operator-і (1);

p. operator* () = a; // динамічна помилка:

// 'p' вийшов за межі масиву

p. operator++ ();

p. operator* () = a; // нормально

}

1.15.7 Перевантаження операцій помістити в потік і взяти з потоку

C++ здатний вводити й виводити стандартні типи даних, використовуючи операцію помістити в потік
" і операцію взяти з потоку ". Ці операції вже перевантажені в бібліотеках класів, якими постачені компілятори C++, щоб обробляти кожний стандартний тип даних, включаючи рядки й адреси пам'яті. Операції помістити в потік і взяти з потоку можна також перевантажити для того, щоб виконувати введення й вивід типів користувача. Програма на малюнку 8 демонструє перевантаження операцій помістити в потік і взяти з потоку для обробки даних певного користувачем класу телефонних номерів PhoneNumber. У цій програмі передбачається, що телефонні номери вводяться правильно. Перевірку помилок ми залишаємо для вправ.

На мал.8 функція-операція взяти з потоку (operator") одержує як аргументи посилання input типу istream, і посилання, названу num, на заданий користувачем тип PhoneNumber; функція повертає посилання типу istream. Функція-операція (operator") використається для введення номерів телефонів у вигляді

(056) 555-1212

в об'єкти класу PhoneNumber. Коли компілятор бачить вираження

cin >> phone

в main, він генерує виклик функції

operator>> (cin, phone);

Після виконання цього виклику параметр input стає псевдонімом для cin, а параметр num стає псевдонімом для phone. Функція-операція використовує функцію-елемент getline класу istream, щоб прочитати з рядка три частини телефонного номера викликаного об'єкта класу PhoneNumber (num у функції-операції й phone в main) в areaCode (код місцевості), exchange (комутатор) і line (лінія). Символи круглих дужок, пробілу й дефіса пропускаються при виклику функції-елемента ignore класу istream, що відкидає зазначену кількість символів у вхідному потоці (один символ за замовчуванням). Функція operator" повертає посилання input типу istream (тобто cin). Це дозволяє операціям введення об'єктів PhoneNumber бути зчепленими з операціями уведення інших об'єктів PhoneNumber або об'єктів інших типів даних. Наприклад, два об'єкти PhoneNumber могли б бути уведені в такий спосіб:

cin >> phonel >> phone2;

Спочатку було б виконане вираження cin " phonel шляхом виклику

operator>> (cin, phonel);

// Перевантаження операцій помістити в потік і взяти з потоку.

#include <iostream. h>

class PhoneNumber{

friend ostream soperator << (ostream &, const PhoneNumber &); friend istream ^operator >> (istream &, PhoneNumber &);

private:

char areaCode [4]; // трицифровий код місцевості й нульовий символ

char exchange [4]; // трицифровий комутатор і нульовий символ

char line [5]; // чотирицифрова лінія й нульовий символ

};

// Перевантажена операція помістити в потік

// (вона не може бути функцією-елементом).

ostream &operator<< (ostream soutput, const PhoneNumber &num)

{

output << " (" << num. areaCode << ")"

"num. exchange << "-" " num. line;

return output; // дозволяє cout << a << b <<c;

}

// Перевантажена операція взяти зпотоку

istream &operator>> (istream sinput, PhoneNumber &num)

{

input. ignore (); // пропуск (

input. getline (num. areaCode,

4); // введення коду місцевості

input. ignore (2); // пропуск) і пробілу

input. getline (num. exchange,

4); // введення комутатора

input. ignore (); // пропуск дефіса (-)

input. getline (num. line,

5); // введення лінії

return input; // дозволяє cin >> a >>b >>c;

}

main () {

PhoneNumber phone; // створення об'єкта phone

cout << "Введіть номер телефону у "

"" вигляді (123) 456-7890: " " endl;

// cin >> phone активізує функцію operator>> // шляхом виклику operator>> (cin, phone). cin >> phone;

// cout << phone активізує функцію operator<< // шляхом виклику operator<< (cout, phone).

cout << "Був введений номер телефону: "<<endl

<< phone << endl;

return 0; }

Введіть номер телефону у вигляді (123) 456-7890: (800) 555-1212

Був введений номер телефону: (800) 555-1212

Мал.8 Задані користувачем операції "помістити в потік" і "взяти з потоку"

Цей виклик міг би потім повернути посилання на cin як значення cin " phonel, так що частина, що залишилася, вираження була б інтерпретована просто як cin " phone2. Це було б виконане шляхом виклику

operator" (cin, phone2);

Операція помістити в потік одержує як аргументи посилання output типу ostream і посилання пшп на певний користувачем тип PhoneNumber і повертає посилання типу ostream. Функція operator" виводить на екран об'єкти типу PhoneNumber. Коли компілятор бачить вираження

cout << phone

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15



© 2003-2013
Рефераты бесплатно, курсовые, рефераты биология, большая бибилиотека рефератов, дипломы, научные работы, рефераты право, рефераты, рефераты скачать, рефераты литература, курсовые работы, реферат, доклады, рефераты медицина, рефераты на тему, сочинения, реферат бесплатно, рефераты авиация, рефераты психология, рефераты математика, рефераты кулинария, рефераты логистика, рефераты анатомия, рефераты маркетинг, рефераты релиния, рефераты социология, рефераты менеджемент.