Website Summary Files Commits Branches @commit @diff @stats
path: root / Sem. 07 / README.md
blob: a39a179ce543a98ee2a17ca3301eaf381a0f9b89 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# Голямата четворка

 - Конструктор по подразбиране (конструктор без параметри)
 - Конструктор за копиране
 - Оператор =
 - Деструктор
 
Да разгледаме следната структура:
```c++
struct Test
{	
	A obj1;
	B obj2;
	C obj3;
};
 ```
 Понеже функциите (от голямата четворка) не са дефинирани в структурата, компилаторът ще създаде такива:
 ```c++
int main()
{
	Test currentObject; //default constructor
	 
	Test object2(currentObject); //copy constructor
	 
	currentObject = object2; //operator =

} //destructor (x2)
 ```
 Кодът се компилира успешно и функциите имат правилно поведение.
###  Как работят дефинираните от компилатора функции?
 Всяка една от тези функции **извиква 'рекурсивно' същите функции върху член-данните.**
 ####  Пример за конструктора по подразбиране:
 
![enter image description here](https://i.ibb.co/smKkDpJ/def-constr.png)
 
  ####  Пример за деструктора:
![enter image description here](https://i.ibb.co/qNHfSTL/def-constr.png)

 ####  Пример за копиращия конструктор:
![enter image description here](https://i.ibb.co/QmCh9z6/cc.png)
### Проблем при функциите, генерирани от компилатора:

Да разгледаме следния код:

 ```c++
struct Person
{
	PersonA(const char* name, int age)
	{
		this->name = new char[strlen(name) + 1];
		strcpy(this->name, name);
		this->age = age;
	}
private:

	char* name;
	int age;
};

int main()
{
	Person p1;
	Person p2(p1);
}

 ```
 Горното извикване на копиращия конструктор има **неправилно поведение**:

![enter image description here](https://i.ibb.co/q5rfGBf/Capture.png)


Това е **shallow copy**. В p2 са се копирали стойностите на p1, което довежда до споделяне на една и съща динамична памет.
В тази ситуация ще трябва да се имплементират експлицитно **копиращия конструктор, оператора за присвояване и деструктора**, защото генерираните от компилатора не биха работили правилно.

**Правилното поведение** на копиращия конструктор е следното:

![enter image description here](https://i.ibb.co/XZq5rGT/33.png)

### Собствена имплементация на функциите за копиране и деструктора

 ```c++
struct Person
{
	Person(const char* name, int age) : name(nullptr), age(age)
	{
		setName(name);
		setAge(age);
	}

	Person(const Person& other)
	{	
		copyFrom(other); // копираме
	}

	Person& operator=(const Person& other)
	{
		if (this != &other)
		{
			free(); //трием
			copyFrom(other); //копираме
		}
		return *this;
	}
	~Person()
	{
		free(); //трием
	}
	
	.
	.
	.
	
	

};

 ```

При всички класове, които използват динамична памет, тези функции изглеждат по този начин. Разликите са в имплементациите на функциите **free** и **copyFrom**.