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

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

Класа Time – с конструктор с елементи по премълчаване.

  1. #include <iostream.h>
  2. class Time
  3.  { public:
  4.      Time (int = 0, int = 0, int = 0);
  5.      void setTime (int, int, int);
  6.      void printMilitary ();
  7.      void printStandard ();
  8.    private:
  9.      int hour;
  10.      int minute;
  11.      int second;
  12.   };
  13. Time::Time (int hr, int min, int sec)
  14.  { setTime (hr, min, sec); }
  15. ...
  16. //описание на другите функции елементи
  17. ...
  18. void main ()
  19.  { Time t1, t2 (2), t3 (21, 34), t4 (12, 25, 42), t5 (27, 74, 99);
  20.    // при t1 всички аргументи са по премълчаване;
  21.    t1.printMilitary ();    // 00:00:00
  22.    t2.printMilitary ();    //  02:00:00
  23.    t3.printMilitary ();    //  21:34:00
  24.    t4.printStandard (); // 12:25:42 PM
  25.    t5.printStandard (); // 12:00:00 AM
  26.  }

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

Деструкторът е специална функция елемент на класа. Името на деструктора съвпада с името на класа, но пред него се поставя символ ‘~’. Мнемониката е, че ‘~’ означава поразрядно логическо отрицание. И така деструкторът може да се разглежда като отрицание на конструктора. Деструкторът на класа се извиква при унищожаване на обекта. Например, деструкторът за даден обект се извиква когато изпълнението на програмата напусне областта на действие на този обект. В действителност, самият деструктор не унищожава обекта, той извършва завършителни действия, преди системата да освободи паметта, в която е бил съхраняван обекта. Деструкторът няма параметри и не връща резултат. Не се разрешава предефиниране на деструктора, т.е. един клас може да има само един деструктор.На практика деструкторите рядко се използват в обикновени класове; деструкторите имат смисъл за класове, които използват динамично разпределение на паметта за обектите.

Конструкторите и деструкторите се извикват автоматично. Редът в който се изпълняват тези извиквания зависи от реда, в който изпълнението на програмата влиза или излиза от областите на действие на обектите. В общия случай, извикването на деструкторите се изпълнява в ред, обратен на извикването на конструкторите на съответните обекти; класът памет на обектите може да измени този ред:
-    конструкторите на обекти, дефинирани като външни се извикват преди изпълнението на функциите от даден файл. Съответните деструктори се извикват когато завърши изпълнението на главната функция main или когато се извика функция exit.
-    конструкторите на автоматичните вътрешни обекти се извикват, когато изпълнението на програмата достигне мястото, където те са дефинирани. Съответните деструктори се изпълняват когато се напусне областта на действие на обектите, т.е. когато се напусне блока в който тези обекти са дефинирани. Конструкторите и деструкторите на автоматичните обекти се извикват всеки път при влизане или излизане от областта им на действие.
-    конструкторите на статичните вътрешни обекти се извикват еднократно, когато изпълнението на програмата достигне за първи път мястото, където те са дефинирани. Съответните деструктори се извикват когато завършва главната функция main или когато се извиква функция exit.

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

  1. #include <iostream.h>
  2. class CreateAndDestroy
  3.  { public:
  4.     CreateAndDestroy (int);
  5.     ~CreateAndDestroy ();
  6.    private
  7.      int data;
  8.  } ;
  9. CreateAndDestroy::CreateAndDestroy (int value)
  10.  { data = value; cout << “Обект “ << data << “ конструктор”; }
  11. CreateAndDestroy::~CreateAndDestroy()
  12.  { cout << “Обект “ << data << “ деструктор” << endl; }
  13. void Create ();
  14. CreateAndDestroy first (1);
  15. void main ()
  16.  { cout << “ външен създаден до main” << endl;
  17.    CreateAndDestroy second (2);
  18.    cout << “ вътрешен автоматичен в main” << endl;
  19.    static CreateAndDestroy third (3);
  20.    cout << “ вътрешен статичен в main” << endl;
  21.    Create ();
  22.    CreateAndDestroy fourth (4);
  23.    cout << “ вътрешен автоматичен в main” << endl;
  24.  }
  25. void Create ()
  26.  { CreateAndDestroy fifth (5);
  27.    cout << “ вътрешен автоматичен в Create” << endl;
  28.    static CreateAndDestroy sixth (6);
  29.    cout << “ вътрешен статичен в Create” << endl;
  30.    CreateAndDestroy seventh (7);
  31.    cout << “ вътрешен автоматичен в Create” << endl;
  32.  }

резултат от изпълнението:
Обект 1 конструктор външен до main
Обект 2 конструктор вътрешен автоматичен в main
Обект 3 конструктор вътрешен статичен в main
Обект 5 конструктор вътрешен автоматичен в Create
Обект 6 конструктор вътрешен статичен в Create
Обект 7 конструктор вътрешен автоматичен в Create
Обект 7 деструктор
Обект 5 деструктор
Обект 4 конструктор вътрешен автоматичен в main
Обект 4 деструктор
Обект 2 деструктор
Обект 6 деструктор
Обект 3 деструктор
Обект 1 деструктор