Website Summary Files Commits Branches @commit @diff @stats
path: root / Sem. 11 / README.md
blob: b7a61aeb3c4feeaa78348c41761c1eb564fd0d98 (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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179

# Наследяване
## Пример за наследяване

При създаване на нов клас, който има общи компоненти и поведение с вече дефиниран клас, вместо да дефинира повторно тези компоненти и поведение, можем да го обявим за наследник на вече дефинирания.

```c++
class A
{
	.
	. 
	.
public:
	void f()
	{
	.
	.
	.
	}
	
	.
	.
	.	
};
class B : public A
{
	.
	.
	.
};

int main()
{
	B obj;
	obj.f(); // OK!
}
 ```
 При наследяването:
 - Наследяват се член-данните и методите на основните класове
 - Получава се достъп до **някои** от наследените компоненти на основните класове


В нашия пример класът **В е наследник на класа А.** Обекти от класовете изглеждат така:

![enter image description here](https://i.ibb.co/Fshm2LJ/Untitled-Diagram.png)


След като  В е наследник на класа А, то при създаване на обект от тип В се създава обект от тип А, **който е част от обекта** от тип В.


## Видове наследяване
Някои типове наследяване в c++:

 - private (по подразбиране)
 - protected
 - public

Примери:
```c++
class A 
{
    public:
       int x;
    protected:
       int y;
    private:
       int z;
};

class B : public A
{
    // x is public
    // y is protected
    // z is not accessible from B
};

class C : protected A
{
    // x is protected
    // y is protected
    // z is not accessible from C
};

class D : private A    // 'private' is default for classes
{
    // x is private
    // y is private
    // z is not accessible from D
};
 ```

## Подаване като параметри на функции.
Класове-наследници могат да бъдат подавани като параметри на функции, които приемат обекти от базовия клас. Може да се използва функционалността само от базовия клас.

```c++
class A
{
public:
	int a;
};
class B : public A
{
public:
	int b;
};
void f(A& obj)
{
	obj.a++;
}

void g(A* ptr)
{
	(*ptr).a++;
}

void t(B& obj)
{
	obj.b++;
}

int main()
{
	A obj1;
	B obj2;
	
	f(obj1); //OK!
	f(obj2); //OK!
	
	g(&obj1); //OK!
	g(&obj2); //OK!
	
	t(obj2);  //OK!
	//t(obj1)// not ok!
}
 ```

## Конструктори и деструктори при наследяване.
Във всеки конструктор на класа-наследник трябва да се оказва кой конструктор да се извика за базовия клас. Ако не е оказано, ще се извика конструкторът по подразбиране.

```c++
class B : public A
{
.
.
.
public:
	B(...) : A(...) //some constructor of A.
	{
	.
	.
	.
	}
};
 ```
Деструкторът на наследения клас извиква деструктора на базовия клас.


## Копиране при наследяване
При разписване на конструктора за копиране и оператора за присовяване на клас-наследник, трябва експлицитно да извикваме копиране и за базовия клас.
 ```c++
B::B(const B& other) : A(other) // (copy constructor of A (base class)
{
	copyFrom(other);
}

B& B::operator=(const B& other)
{

	if (this != &other)
	{
		A::operator=(other); //operator= of A (base class)
		free();
		copyFrom(other);
	}
	return *this;
}
 ```
 
 Разписваме копирането и триенето само ако наследникът ползва необработена динамична памет! Ако няма, то генерираните от компилатора (по горната схема) работят коректно!