Лекции по обектно-ориентирано програмиране



страница9/16
Дата25.07.2016
Размер0.95 Mb.
#6568
ТипЛекции
1   ...   5   6   7   8   9   10   11   12   ...   16

15. Интерфейс и реализация.

Отделянето на интерфейса от реализацията е един от най-фундаменталните принципи за създаване на добро програмно осигуряване; това улеснява модификацията на програмата;

измененията в реализацията на класа не влияят на клиента, ако интерфейсът остане същия;
препоръчва се дефиницията на класа да се оформи като отделен заглавен файл; така тя е достъпна за всеки клиент, който иска да използва класа; това формира открития интерфейс на класа;

препоръчва се описанието на функциите-елементи на класа да се оформи в отделен първичен файл; това формира реализацията на класа;

заглавният файл, в който е описана дефиницията на класа, обаче, може да съдържа някои части от реализацията и кратки сведения за други части от реализацията; вградените функции-елементи, например, трябва да се намират в заглавния файл – по този начин клиентът може да включва определени функции inline; закритите елементи са изброени в заглавния файл, така че тези елементи са видими за клиента, макар че той няма достъп до тях;
заглавните файлове се включват чрез директивата include в първичните файлове, в който се използва класа; тези първични файлове и първичният файл с главната функция се компилират разделно;

илюстрация (с класа Time)


заглавен файл time1.h

#ifndef TIME1_H

#define TIME1_H
дефиниране на класа Time…
#endif
първичен файл time1.cpp

#include “time1.h”

#include
описание на функциите елементи...
първичен файл prog.cpp

#include “time1.h”

#include
описание на главната функция...
тук главната функция се явява като клиент;

използваните директиви на препроцесора в заглавния файл time1.h предотвратяват включването на кода между #ifndef и #endif, ако е дефиниран макроса TIME1_H;

ако заглавният файл още не е включван в даден първичен файл, то се дефинира макросa TIME1_H чрез директивата define и заглавният файл се включва в първичния файл; ако заглавният файл е вече включен, това означава, че макросът TIME1_H е вече дефиниран и заглавният файл не се включва повторно в първичния файл;

опити за многократно включване на заглавен файл обикновено се правят в големи програми с много заглавни файлове, които от своя страна включват други заглавни файлове; мнемонично е името на макроса да се получава от името на заглавния файл (например чрез замяната на ‘.’ с ‘_’);



16. Конструктори и деструктори.

След създаване на един обект, неговите елементи могат да бъдат инициализирани с помощта на функция конструктор; конструкторът е функция-елемент, която има същото име, както името на класа; конструкторът се извиква автоматично при създаването на обекта; за конструкторите не може да се задава тип на връщания резултат и те не връщат резултат;

конструкторите могат да се предефинират и така да се определя множество от начални стойности за обектите на класа; когато се дефинира обект от даден клас, между името на обекта и ‘;’ може в скобки да се зададе списък за инициализация на елементи – тези начални стойности се предават като параметри в конструктора на класа; конструктор при който всички аргументи са по премълчаване или който няма аргументи, се нарича конструктор по премълчаване; за всеки клас може да съществува само един конструктор по премълчаване;
модификация на класа Time – с конструктор с елементи по премълчаване;
#include

class Time

{ public:

Time (int = 0, int = 0, int = 0);

void setTime (int, int, int);

void printMilitary ();

void printStandard ();

private:


int hour;

int minute;

int second;

};

Time::Time (int hr, int min, int sec)



{ setTime (hr, min, sec); }

описание на другите функции елементи



void main ()

{ Time t1, t2 (2), t3 (21, 34), t4 (12, 25, 42), t5 (27, 74, 99);

// при t1 всички аргументи са по премълчаване;

t1.printMilitary (); // 00:00:00

t2.printMilitary (); // 02:00:00

t3.printMilitary (); // 21:34:00

t4.printStandard (); // 12:25:42 PM

t5.printStandard (); // 12:00:00 AM

}
тук конструкторът извиква функцията SetTime със стойности, предадени на конструктора или със стойности по премълчаване;

това извикване улеснява съпровождането на програмата, тъй като при промяна на реализацията на SetTime, това ще бъде отразено и в конструктора; въпреки това се губи ефективност – това може да се поправи, ако функцията SetTime явно се обяви като inline (в описанието извън класа); ако функцията SetTime е описана вътре в дефиницията на класа, тя по подразбиране се обявява като inline;
добър стил на програмиране е декларирането на аргументи по премълчаване само в прототипа на функцията елемент вътре в дефиницията на класа; грешка е задаването на начални стойности по премълчаване за една и съща функция елемент както в прототипа, така и в нейното описание;
ако за класа не е дефиниран конструктор, то компилаторът създава конструктор по премълчаване; този конструктор не задава начални стойности, така че след създаването на обекта, данните в него могат да са некоректни;
деструкторът е специална функция елемент на класа;

името на деструктора съвпада с името на класа, но пред него се поставя символ ‘~’; мнемониката е, че ‘~’ означава поразрядно логическо отрицание;

и така деструкторът може да се разглежда като отрицание на конструктора; деструкторът на класа се извиква при унищожаване на обекта; например, деструкторът за даден обект се извиква когато изпълнението на програмата напусне областта на действие на този обект; в действителност, самият деструктор не унищожава обекта, той извършва завършителни действия, преди системата да освободи паметта, в която е бил съхраняван обекта; деструкторът няма параметри и не връща резултат; не се разрешава предефиниране на деструктора, т.е. един клас може да има само един деструктор;
на практика деструкторите рядко се използват в обикновени класове; деструкторите имат смисъл за класове, които използват динамично разпределение на паметта за обектите;
конструкторите и деструкторите се извикват автоматично; редът в който се изпълняват тези извиквания зависи от реда, в който изпълнението на програмата влиза или излиза от областите на действие на обектите; в общия случай, извикването на деструкторите се изпълнява в ред, обратен на извикването на конструкторите на съответните обекти; класът памет на обектите може да измени този ред:


  • конструкторите на обекти, дефинирани като външни се извикват преди изпълнението на функциите от даден файл; съответните деструктори се извикват когато завърши изпълнението на главната функция main или когато се извика функция exit;

  • конструкторите на автоматичните вътрешни обекти се извикват, когато изпълнението на програмата достигне мястото, където те са дефинирани; съответните деструктори се изпълняват когато се напусне областта на действие на обектите, т.е. когато се напусне блока в който тези обекти са дефинирани; конструкторите и деструкторите на автоматичните обекти се извикват всеки път при влизане или излизане от областта им на действие;

  • конструкторите на статичните вътрешни обекти се извикват еднократно, когато изпълнението на програмата достигне за първи път мястото, където те са дефинирани; съответните деструктори се извикват когато завършва главната функция main или когато се извиква функция exit;

примерна програма, илюстрираща реда на извикване на конструкторите и деструкторите;


#include

class CreateAndDestroy

{ public:

CreateAndDestroy (int);

~CreateAndDestroy ();

private


int data;

} ;


CreateAndDestroy::CreateAndDestroy (int value)

{ data = value; cout << “Обект “ << data << “ конструктор”; }

CreateAndDestroy::~CreateAndDestroy()

{ cout << “Обект “ << data << “ деструктор” << endl; }

void Create ();

CreateAndDestroy first (1);

void main ()

{ cout << “ външен създаден до main” << endl;

CreateAndDestroy second (2);

cout << “ вътрешен автоматичен в main” << endl;

static CreateAndDestroy third (3);

cout << “ вътрешен статичен в main” << endl;

Create ();

CreateAndDestroy fourth (4);

cout << “ вътрешен автоматичен в main” << endl;

}

void Create ()



{ CreateAndDestroy fifth (5);

cout << “ вътрешен автоматичен в Create” << endl;

static CreateAndDestroy sixth (6);

cout << “ вътрешен статичен в Create” << endl;

CreateAndDestroy seventh (7);

cout << “ вътрешен автоматичен в Create” << endl;

}
резултат от изпълнението:

Обект 1 конструктор външен до main

Обект 2 конструктор вътрешен автоматичен в main

Обект 3 конструктор вътрешен статичен в main

Обект 5 конструктор вътрешен автоматичен в Create

Обект 6 конструктор вътрешен статичен в Create

Обект 7 конструктор вътрешен автоматичен в Create

Обект 7 деструктор

Обект 5 деструктор

Обект 4 конструктор вътрешен автоматичен в main

Обект 4 деструктор

Обект 2 деструктор

Обект 6 деструктор

Обект 3 деструктор

Обект 1 деструктор




Сподели с приятели:
1   ...   5   6   7   8   9   10   11   12   ...   16




©obuch.info 2024
отнасят до администрацията

    Начална страница