Удосконалена програма роботи з типом String 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Удосконалена програма роботи з типом String



Використовуючи вказівник this можна переробити функцію operator=() в програмі 13.17 і змусити її повертати резултат за посиланням. Таким чином можна здійснювати множинні присвоювання для класу String, наприклад:

а1=а2=а3

В той же час, ми уникнемо і створення хибних об’єктів у вигляді копій для створення результату, як це було, коли повернення здійснювалося за значенням.

Далі приведений лістінг програми 13.21

 #include<iostream.h>

 #include<conio.h>

 #include<stdio.h>

 #include<bios.h>

 #include<string.h>

 /////////////////

 class strCount

 {private:

 int count;

 char* str;

 friend class String;

 strCount(char* s)

 {int length=strlen(s);

 str=new char[length+1];

 strcpy(str,s);

 count=1;

 }

 ~strCount()

 {delete[] str;}

 };

 /////////////////

 class String

 {private:

 strCount* psc;

 public:

 String()//конструктор без аргументів

 {psc=new strCount(“NULL”);}

 //-------

 String(char* s)//конструктор з 1 аргументом

 {psc=new strCount(s);}

 //-----------

 String(String& S) //конструктор копіювання

 {psc=S.psc;

 (psc->count)++;}

 //----------

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

{if(psc->count==1)

delete psc;

else

(psc->count)--;

}

//----------

void display()

{cout<<psc->str;

cout<<” (addr=”<<psc<<”)”; //виведення адреси

}

//-----------

 String& operator=(String& S)

 {cout<<”\nПрисвоювання”;

 if(psc->count==1) //if last

 delete psc;

 else

 (psc->count)--;

 psc=S.psc;

 (psc->count)++;

 return *this;

 }

 };

 //////////////

 int main()

 {clrscr();

 String s3=”Будь-яка пробна фраза”;

 cout<<”\ns3=”;s3.display();

 String s1,s2;

 s1=s2=s3;

 cout<<”\ns1=”;s1.display();

 cout<<”\ns2=”;s2.display();

 cout<<endl;

 bioskey(0);

 return 0;

 }

Програма 13.21

Тепер описувачем оператору присвоювання є

String& operator=(String& S)

і програма повертає вказівник на this.

Слід відмітити, що вказівник this не можна використовувати у статичних методах, оскільки вони не асоційовані з конкретним об’єктом.

 

Уникайте неправильних присвоювань

Пам’ятаймо: якщо ми перевизначили оператор присвоювання, хто-небудь помилково зможе використати його для присвоювання об’єктів самим собі:

alpha=alpha;

Якщо перезавантажений = не передбачить і не заблокує такої ситуації, програма, найвірогідніше, зависне – таке, наприклад, трапилося б з програмою 13.21. Проблема полягає в тому, що, згідно з кодом перезавантаженої операції присвоювання, цей оператор видаляє об’єкт strCount, якщо вважає, що цей об’єкт є єдиним, що використовує strCount. Присвоювання об’єкту самому собі впевнить оператор у цьому факті, хоча насправді ніхто і не збирався видаляти якісь об’єкти.

Щоб все привести до порядку, потрібно ввести перевірку на присвоювання самому собі на початку роботи кожного перезавантаженого =. В більшості випадків це робиться шляхом порівняння адрес об’єктів, що стоять справа і зліва від знаку рівності. Зрозуміло, що, раз адреси рівні, отже, здійснюється присвоювання об’єкту самому собі і необхідно негайно повернутися з цієї функції. Наприклад, в програму 13.21 з цією метою можна вставити таку перевірку:

if(this==&S)

return *this;

в початок функції operator=(). Це повинно розв’язати проблему, яка виникла.

 

Підсумок

Віртуальні функції дозволяють розв’язувати безпосередньо в процесі виконання програми, яку саме функцію викликати. Без їх використання це рішення приймається на етапі компіляції програми. Віртуальні функції дають більшу гнучкість при виконанні однакових дій над різнорідними об’єктами. Зокрема, вони дозволяють використання функцій, що викликаються з масиву вказівників на базовий клас, що насправді містить вказівники на породжені класи. Це приклад поліморфізму. Звичайно функція оголошується віртуальною в базовому класі, а інші функції з тим самим іменем оголошуються в породжених класах.

Використання принаймні однієї чистої віртуальної функції робить клас, що її містить, абстрактним. Це означає, що за допомогою цього методу не можна створювати ніяких об’єктів.

Дружня функція має доступ до прихованих даних класу, по відношенню до якого вона оголошена дружньою. Це буває корисним, якщо одна функція повинна мати доступ до двох не зв’язаних між собою класів і коли перезавантажувана операція повинна використовувати дані «чужого» класу, методом якого вона не є. Дружність також використовується для спрощення запису функцій.

Статичною називається функція, що працює з класом в цілому, а не з його окремими об’єктами. Зокрема, вона може обробляти статичні змінні. Вона може бути викликана з використанням імені класу і оператора явного задання функції.

Оператор присвоювання = може бути перезавантаженим. Це необхідно, коли він повинен виконувати більш складну роботу, ніж просте копіювання вмісту одного об’єкту в інший. Конструктор копіювання, що створює копії об’єктів під час ініціалізації, також може бути перезавантаженим. Це необхідно, коли він повинен виконувати складнішу роботу, ніж просте копіювання об’єкту.

Вказівник this може використовуватися в функції для вказування на об’єкт, чиїм методом він є. Він корисний, якщо в якості результату повертається об’єкт, чиїм методом є дана функція.

 

Питання по темі

1. Чи істинне твердження: вказівник на базовий клас може посилатися на об’єкти породженого класу?

а) так

б) ні

2. Нехай вказівник р посилається на об’єкти базового класу і містить адресу об’єктів породженого класу. Нехай в обох цих класах міститься невіртуальний метод ding(). Тоді вираз p->ding() поставить на виконання версію функції з ___________ класу

а) базового

б) породженого

3. Нехай вказівник р посилається на об’єкти базового класу і містить адресу об’єктів породженого класу. Нехай в обох цих класах міститься віртуальний метод ding(). Тоді вираз p->ding() поставить на виконання версію функції з ___________ класу

а) базового

б) породженого

4. Написати описувач для віртуальної функції dang(), що повертає результат типу void і має аргумент типу int

а) virtual void dang(int);

б) virtual dang(int);

в) void dang(int); virtual;

5. Написати описувач для чистої віртуальної функції dang(), що повертає результат типу void і має аргумент типу int

а) virtual void dang(int)=0;

б) virtual dang(int);

в) void dang(int); virtual;

 

6. Чиста віртуальна функція – це віртуальна функція, яка:

а) робить свій клас абстрактним

б) не повертає результату

в) не має аргументів

 

7. Абстрактний клас в С++ використовується, коли:

а) не планується створювати породжені класи

б) ми хочемо відкласти визначення класу

в) з його допомогою заборонено створювати будь-які об’єкти

 

8. Як написати означення масиву parr, що містить 10 вказівників на об’єкти класу dong?

а) dong* parr[10];

б) dong *parr[10];

в) dong parr*[10];

 

9. Який метод базового класу слід робити віртуальним?

а) конструктор

б) деструктор

 

10. Чи істинне твердження: дружня функція має доступ до прихованих даних класу, не будучи його методом?

а) так

б) ні

 

11. Як написати описувач дружної функції func(), що повертає результат типу void і має аргумент типу float?

а) void func(float); friend;

б) friend void func(float);

в) friend func(float);

 

12. Написати описувач, який в тому класі, де він з’явиться, зробить кожен метод класу klass дружньою функцією

а) class klass; friend:

б) klass friend class;

в) friend class klass;

 

13. Статична функція:

а) повинна викликатися при виклику об’єкта

б) дуже зв’язана з індивідуальним об’єктом класу

в) може бути викликана з використанням імені класу та імені функції

14. Як правильно написати описувач перезавантажуваної операції присвоювання для класу zeta?

а) operator =(zeta)

б) zeta operator =(zeta)

в) zeta& operator =(zeta&)

 

15. Операції, виконувані оператором присвоювання і конструктором копіювання:

а) схожі, за винятком того, що конструктор копіювання створює новий об’єкт

б) схожі, за винятком того, що оператор присвоювання копіює компонентні дані

 

16. Як правильно написати описувач конструктора копіювання для класу zeta?

а) zeta(zeta)

б) zeta(zeta&)

в) operator zeta(zeta)

 

17. Конструктор копіювання запускається, коли:

а) функція повертається за значенням

б) функція повертається за посиланням

в) аргумент передається за значенням

г) аргумент передається за посиланням

 

18. Чи відрізняється дія таких виразів

person p1(p0)

person p1=p0

а) так

б) ні

 

19. Якщо в заданому класі змінна da є компонентними даними, то як правильно присвоїти значення 3 змінній da, використовуючи this?

а) this->da=3;\

б) this.da=3;

в) this*.da=3;

 

20. Як правильно написати вираз, за допомогою якого функція може повертати весь об’єкт, методом якого вона є, без створення тимчасових об’єктів?

а) return this

б) return *this;

в) return()



Поделиться:


Последнее изменение этой страницы: 2021-12-15; просмотров: 140; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.191.13.255 (0.024 с.)