#include class Test { public: // конструктор по подразбиране Test() { std::cout << "Default Test object was created!\n"; } // копиращ конструктор // За да създадем копие на вече съществуващ обект... // Забележете аргумента на конструктора!!! // Ако няма &, това означа, че аргументът се предава по стойност. // По стойност => вътре във функцията се работи с копие, // което трябва да се създаде от копиращия конструктор. // (Т.е. за да дефинираме копиращ конструктор, трябва да използваме самия него...) // Ако пропуснете const, не можете да създавате копия на константни обекти... Test(const Test& other) { std::cout << "Test object was copied\n"; } // Деструктор // Извиква се автоматично, когато обектът излезе от област // на видимост и трябва да бъде унищожен ~Test() { std::cout << "~Test()\n"; } }; // Предаване по псевдоним, няма копие, закачаме се директно // за обекта, който е подаден като аргумент void f(const Test& t) { std::cout << "f()\n"; } // Предаването на аргумента на функцията е по СТОЙНОСТ, // което означава, че вътре във функцията се работи с копие. // За да се създаде това копие се използва копиращия конструктор. void g(Test t) { std::cout << "g()\n"; // Предаването на аргумента е по псевдоним, няма създаване на копие f(t); // с приключването на функцията, копието t излиза от област на видимост // и трябва да бъде унищожено, ще бъде извикан деструктор } int main() { // Създаваме константен обект с конструктора по подразбиране // Изрично е константент, за да проверите какво се случва, // ако премахнете const от аргумента на копиращия конструктор... const Test t; // Извикваме функцията g, чиито аргумент се предава по стойност. // Тук, преди да се изпише g(), трябва да видите обръщението към // копиращия конструктор. g(t); std::cout << "\ng() has finished!\n"; // след това съобщение трябва да се види и съобщението от // деструктора на константния обект t, създаден в main std::cout << "\nDynamic object..." << std::endl; Test* dt = new Test(); // при освобождаване на паметта с оператора delete // се извиква деструкторът на обекта dt delete dt; std::cout << "\nDynamically allocating array of objects..." << std::endl; Test* dynArr = new Test[3]; // за всеки от елементите на масива се извиква конструкторът по подразбиране, // който да инициализира данните в паметта // При освобождаването на паметта // ВНИМАНИЕ!!! // Не забравяйте [] с delete! // Ако бъдат пропуснати, се извиква деструкторът само на първия обект от масива. // delete dynArr; // ГРЕШКА! delete[] dynArr; std::cout << "\nDynamically allocating array of dynamic objects..." << std::endl; // В случай, че класът не разполага с конструктор по подразбиране // можем да създадем масив от указатели, които сочат към динамични обекти. Test** dynArrDynObjs = new Test*[3]; for(size_t i = 0; i < 3; ++i) { // За тези динамични обекти можем да извикаме подходящ конструктор. // (В случая не може да се види разликата, защото класът Test разполага // само и единствено с конструктор по подразбиране.) dynArrDynObjs[i] = new Test; } // Освобождаване на паметта за масива от динамични обекти for(size_t i = 0; i < 3; ++i) { // първо освобождаваме всеки от обектите.. delete dynArrDynObjs[i]; } delete[] dynArrDynObjs; }