//
destru.cpp
//
demonstrates constructors, destructors,
//
and storage classes
#include
<iostream.h>
#include
<string.h>
// for strncpy()
class
omega
{
private:
static const int size = 20; // array size
char obname[size];
// array for obname string
static int total_now; // objects
in existence now
static int total_ever; // objects ever
created
int snumber;
// serial number of this object
public:
// one-arg constructor
omega(char str[]) : snumber(++total_ever)
{
strncpy(obname, str, size);
cout << "\n 1-arg constructor creating "
<< obname << "-" << snumber
<< ". Total=" << ++total_now;
}
// copy constructor
omega(const omega & om) : snumber(++total_ever)
{
strncpy(obname, om.obname, size);
cout << "\n Copy constructor creating "
<< obname << "-" << snumber
<< ". Total=" << ++total_now;
}
// destructor
~omega()
{
cout << "\n Destructor destroying
"
<< obname << "-" << snumber
<< ". Total = " << --total_now;
}
}; // end class omega
int
omega::total_now = 0;
int
omega::total_ever = 0;
omega om0("Adam"); // external object
////////////////////////////////////////////////////////////////
void
main()
{
cout << "\nmain() starting";
void func(omega); // declaration
omega om1("Jane"); // uses
one-arg constructor
omega om2("Paul"); // uses
one-arg constructor
omega om3(om2);
// uses copy constructor
cout << "\nmain() calling func(om1)";
func(om1);
cout << "\nmain() calling func(om2)";
func(om2);
cout << "\nmain() terminating";
} // main()
void
func(omega og)
// argument passed by value
{
cout << "\nfunc() starting";
omega om4("Mike"); // object is local to func()
cout << "\nfunc() terminating";
}
В програмата нарочно не е поставен ред, който извиква функцията getch(), която ни служи в другите програми за задържане на екрана преди връщането към интегрираната работна среда (IDE). Това е така, защото е наложително програмата да бъде стартирана извън IDE.
! Така написана, програмата трябва да се стартира извън интегрираната работна среда (IDE, Integrated Development Environment), понеже е необходимо да се види какво става след излизането от главната функция на програмата, main(). Това може да се осъществи при стартиране на Command Prompt от менюто Start/Programs/Accessories, преминаване на директорията където е файлът destr.exe и стартирането му чрез изписване на името му.
Работна директория при мен е \PROGRAMMING\C++\Cpp_Lafore\Programs\ch05>destr на диск D:. Изходът от изпълнението на програмата е следният (дадени са и двата реда с показалеца (промта) на операционната система):
D:\PROGRAMMING\C++\Cpp_Lafore\Programs\ch05>destru
1-arg constructor creating Adam-1. Total=1
main()
starting
1-arg constructor creating Jane-2. Total=2
1-arg constructor creating Paul-3. Total=3
Copy constructor creating Paul-4. Total=4
main()
calling func(om1)
Copy constructor creating Jane-5. Total=5
func()
starting
1-arg constructor creating Mike-6. Total=6
func()
terminating
Destructor destroying Mike-6. Total = 5
Destructor destroying Jane-5. Total = 4
main()
calling func(om2)
Copy constructor creating Paul-7. Total=5
func()
starting
1-arg constructor creating Mike-8. Total=6
func()
terminating
Destructor destroying Mike-8. Total = 5
Destructor destroying Paul-7. Total = 4
main()
terminating
Destructor destroying Paul-4. Total = 3
Destructor destroying Paul-3. Total = 2
Destructor destroying Jane-2. Total = 1
Destructor destroying Adam-1. Total = 0
D:\PROGRAMMING\C++\Cpp_Lafore\Programs\ch05>
2. Кога и как се създават и унищожават обектите в програмата?. Отместените надясно линии на този изход са изписани от конструкторите и деструктора, а другите (изпъкналите наляво) - от твърденията в главната функция main() и функцията func().
Както се вижда от изхода, общо се създават осем обекта от класа omega. Първият създаден обект е с име Adam и е създаден от едноаргумнтния конструктор при дефиницията на глобален обект om0, още преди главната функция main(). Той е т.н. външна променлива (External Variable). Той не само първи се създава, но и последен се разрушава и то чак след излизане на програмата от главната функция. Както може да се види, обектите се създават в даден ред и се разрушават в обратен на него.
В главната функция main() се създават два обекта с едноаргумнтния конструктор - om1 и om2, с имена Jane и Paul. Тъй като са втори и трети подред, техните номера са 2 и 3. След това с помощта на копиращия конструктор се създава четвърти обект, копие на третия (с име Paul) - ето защо той има същото име, но е с номер 4.
След това два пъти подред се извиква функцията func() с аргумент, първия път om1, и втория - om2. Тя прави техни копия (в og с копиращия конструктор), които имат същите имена, но други номера, и отделно създава локален обект om4 с име Mike.
Всеки път при излизане от функцията func(), локалният обект om4 се унищожава първи, а след него и копирания аргумент og.
3. Връщане по стойност. В горната програма няма връщане по стойност от функция, където отново става създаване на нов обект с копиращия конструктор. Ето защо в следващата програма, която е променената destru.cpp, сме променили функцията func(), така че да връща по стойност променлива от типа на класа omega. Обърнете внимание, че в C++ функциите, които връщат стойност могат да се извикват по два начина - func(om1); и om3 = func(om1);, така както е направено в програмата destru1.cpp,.
//
destru1.cpp
//
demonstrates constructors, destructors,
//
and storage classes
#include
<iostream.h>
#include
<string.h>
// for strncpy()
class
omega
{
private:
static const int size = 20; // array size
char obname[size];
// array for obname string
static int total_now; // objects
in existence now
static int total_ever; // objects ever
created
int snumber;
// serial number of this object
public:
// one-arg constructor
omega(char str[]) : snumber(++total_ever)
{
strncpy(obname, str, size);
cout << "\n 1-arg constructor creating "
<< obname << "-" << snumber
<< ". Total=" << ++total_now;
}
// copy constructor
omega(const omega & om) : snumber(++total_ever)
{
strncpy(obname, om.obname, size);
cout << "\n Copy constructor creating "
<< obname << "-" << snumber
<< ". Total=" << ++total_now;
}
// destructor
~omega()
{
cout << "\n Destructor destroying
"
<< obname << "-" << snumber
<< ". Total = " << --total_now;
}
}; // end class omega
int
omega::total_now = 0;
int
omega::total_ever = 0;
omega om0("Adam"); // external object
////////////////////////////////////////////////////////////////
void
main()
{
cout << "\nmain() starting";
omega func(omega); // declaration
omega om1("Jane"); // uses
one-arg constructor
omega om2("Paul");
omega om3(om2);
// uses copy constructor
cout << "\nmain() calling func(om1)";
func(om1);
cout << "\nmain() calling om3 = func(om1)";
om3 = func(om1);
cout << "\nmain() terminating";
} // main()
omega
func(omega og)
// argument passed by value
{
cout << "\nfunc() starting";
omega om4("Mike"); // object is local to func()
cout << "\nfunc() terminating";
return og;
}
Изходът от програмата е следният:
D:\PROGRAMMING\C++\Cpp_Lafore\Programs\ch05>destru1
1-arg constructor creating Adam-1. Total=1
main()
starting
1-arg constructor creating Jane-2. Total=2
1-arg constructor creating Paul-3. Total=3
Copy constructor creating Paul-4. Total=4
main()
calling func(om1)
Copy constructor creating Jane-5. Total=5
func()
starting
1-arg constructor creating Mike-6. Total=6
func()
terminating
Copy constructor creating Jane-7. Total=7
Destructor destroying Mike-6. Total = 6
Destructor destroying Jane-5. Total = 5
Destructor destroying Jane-7. Total = 4
main()
calling om3 = func(om1)
Copy constructor creating Jane-8. Total=5
func()
starting
1-arg constructor creating Mike-9. Total=6
func()
terminating
Copy constructor creating Jane-10. Total=7
Destructor destroying Mike-9. Total = 6
Destructor destroying Jane-8. Total = 5
Destructor destroying Jane-10. Total = 4
main()
terminating
Destructor destroying Jane-10. Total = 3
Destructor destroying Paul-3. Total = 2
Destructor destroying Jane-2. Total = 1
Destructor destroying Adam-1. Total = 0
D:\PROGRAMMING\C++\Cpp_Lafore\Programs\ch05>
При първото извикване на функцията, във вида func(om1);, промяната в изхода при излизане от функцията са вторият и последният ред в тези пет реда от изхода:
func()
terminating
Copy constructor creating Jane-7. Total=7
Destructor destroying Mike-6. Total = 6
Destructor destroying Jane-5. Total = 5
Destructor destroying Jane-7. Total = 4
Вторият ред показва, че при излизане от функцията се създава нов обект, който е с името на аргумента Jane (защото просто се връща аргумента в кода на функцията). Чак след това се унищожават локалният обект om4 (Mike-6) и обектът og (Jane-5), който бе копиран от аргумента. Разбира се, накрая се унищожава и върнатия обект Jane-7.
При второто извикване, във вида om3 = func(om1);, промяната в изхода при излизане от функцията са също вторият и последният ред в тези пет реда от изхода:
func()
terminating
Copy constructor creating Jane-10. Total=7
Destructor destroying Mike-9. Total = 6
Destructor destroying Jane-8. Total = 5
Destructor destroying Jane-10. Total = 4
Логиката е същата като горното обяснение. Само трябва да се каже, че вече върната стойност е копирана в om3, както това се вижда при унищожаване на обекта om3 от следните редове на изхода:
main()
terminating
Destructor destroying Jane-10. Total = 3
Хубаво е читателят да компилира и стартира (извън интегрираната работна среда) двете разгледани програми и да осмисли изхода от тях.
В следващите лекции
започваме темата с т.н. предефиниране на оператори (Operator Overloading).
.
Keywords: С++,
OOP programming , C++ , Classes , Inheritance , Reusability , Creating
New Data Types , Polymorphism and Overloading
Ключови думи: клас
, обект, обектно ориентирано програмиране , полиморфизъм switch if else
?
External Variables
Variables in main()
Passing by Value
Returning by Value