Отделянето на интерфейса от реализацията е един от най-фундаменталните принципи за създаване на добро програмно осигуряване; това улеснява модификацията на програмата;
измененията в реализацията на класа не влияят на клиента, ако интерфейсът остане същия;
препоръчва се дефиницията на класа да се оформи като отделен заглавен файл; така тя е достъпна за всеки клиент, който иска да използва класа; това формира открития интерфейс на класа;
препоръчва се описанието на функциите-елементи на класа да се оформи в отделен първичен файл; това формира реализацията на класа;
заглавният файл, в който е описана дефиницията на класа, обаче, може да съдържа някои части от реализацията и кратки сведения за други части от реализацията; вградените функции-елементи, например, трябва да се намират в заглавния файл – по този начин клиентът може да включва определени функции 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 деструктор
Сподели с приятели: |