Advertisement
kqlul123

Лекция(29.10.18)

Oct 29th, 2018
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.35 KB | None | 0 0
  1. Деструкторы при наследовании
  2.  
  3. Явно вызывать деструкторы не надо.
  4. Если в конструкторе дочернего класса выделялась память под специфические поля, эту память нужно освободить в деструкторе производного класса. Чтобы деструктор родительского класса вызывался автоматически перед прототипом деструктора нужно писать virtual.
  5. virtual прототип_деструктора
  6.  
  7. Динамический полиморфизм
  8. Классы могут иметь одноименные методы(это также касается классов, являющихся членами наследственной иерархии)
  9. При этом начинка методов может быть совершенно разной -> разная реализация
  10.  
  11. Создается объект род. класса, потом выделяется память под спец.поля.
  12. Указатель на объект предка является одновременно указателем на объекты любых его наследников.
  13. Таким образом, через указатель на объект базового класса можно обеспечить создание объектов любого из классов-наследников.
  14.  
  15. Пример 1.
  16. class TPar
  17. {
  18. int x;
  19. public:
  20. TPar(int xx=1);
  21. void pvvod(); //Mетод 1
  22. void fff(int a); //2
  23. };
  24.  
  25. TPar::TPar(int xx)
  26. {
  27. x=xx;
  28. }
  29.  
  30. void TPar::pvvod()
  31. {
  32. cout << "Vv. X" << endl;
  33. cin >> x;
  34. }
  35.  
  36. void TPar::fff(int a)
  37. {
  38. x*=a;
  39. }
  40.  
  41.  
  42. class TChl:public TPar
  43. {
  44. int y;
  45. public:
  46. TChl(int xx=1, int yy=2);
  47. void cvvod(); //Mетод 3
  48. void fff(int a); //Mетод 4
  49. };
  50.  
  51. TChl::TChl(int xx, int yy):TPar(xx)
  52. {
  53. y=yy;
  54. }
  55.  
  56. void TChl::cvvod()
  57. {
  58. pvvod();
  59. cout << "Vv. Y" << endl;
  60. cin >> y;
  61. }
  62.  
  63. void TChl::fff(int a)
  64. {
  65. for(int i = 1; i <= a; i++)
  66. {
  67. x+=y;
  68. }
  69. }
  70.  
  71. void main()
  72. {
  73. TPar *p1,*p2;
  74. TChl *c1,*c2;
  75. p1 = new TPar; //Создание объекта родительского класса
  76. p2 = new TChl; //Создается объект дочернего класса
  77. с1 = new TPar; //Ошибка
  78. с2 = new TChl; //Создается объект дочернего класса
  79.  
  80. p1 -> pvvod(); //1
  81. p1 -> fff(5); //2
  82. c2 -> pvvod(); //1
  83. c2 -> fff(27); //4
  84. c2 -> TPar::fff(19); //2
  85. c2 -> cvvod(); //3
  86.  
  87. p2 -> pvvod(); //1
  88. p2 -> fff(7); //2 (потому что объявлено как TPar *p2)
  89. p2 -> cvvod(); //Ошибка
  90. p2 -> TChl::fff(3); //Ошибка
  91.  
  92. Чтобы обратиться к собственным методам дочернего класса в данном случае нужно выполнить явное преобразование типа указателя р2 к типу (TChl*)
  93.  
  94. ((TChl*)p2) - > cvvod(); //3
  95. ((TChl*)p2) - > fff(3); //4
  96. }
  97.  
  98.  
  99. +В ходе работы программы можно выбирать нужный объект из родственной иерархии, соответствующим образом, выделяя память.
  100. -Указатель на объект не знает с объектом какого класса он связан, для того чтобы получить доступ к собственным методов классов - наследников нужно выполнять явное преобразование типа, что сводит на нет позитивное.
  101.  
  102. Для решения этой проблемы в с++ имеется инструмент - виртуальные функции.
  103. Особенности виртуальных функций.
  104. 1) Функции должны быть одноименными и кроме того иметь полностью совпадающие сигнатуры(возвращаемое значение и список параметров)
  105. Не следует путать это с перегрузкой функций, при перегрузке список параметров должен различаться.
  106. 2) Виртуальные функции должны быть членами классов.
  107. 3) Виртуальность передается по наследству, какой бы длинной не была цепочка наследников.
  108. 4) Если определение виртуальной функции отстутствует в середине цепочки, то виртальность сохраняется, а работать будет предыдущая реализация.
  109.  
  110.  
  111. (1) - Есть, работает (1)
  112. (2) - Нет, работает (1)
  113. (3) - Есть, работает (3)
  114.  
  115. Пример 2.
  116. (TA)
  117. \
  118. (TB)
  119. \
  120. (TC)
  121.  
  122. class TA
  123. {
  124. int x;
  125. public:
  126. TA(int xx=1);
  127. virtual void fff();
  128. .... //виртуальных методов 100 штук
  129. };
  130.  
  131. //Реализация
  132.  
  133. class TB:public TA
  134. {
  135. int y;
  136. public:
  137. TB(int xx=1, int yy=2);
  138. void fff(); //Виртуальность передается по наследству
  139. ... // 100 штук
  140. };
  141. //Реализация
  142.  
  143. class TC:public TB
  144. {
  145. int z;
  146. public:
  147. TC(int xx = 1, int yy = 2, int zz = 3);
  148. void fff();
  149. ... // 100 штук
  150. };
  151. //Реализация
  152.  
  153. void main()
  154. {
  155. TA* uk;
  156. int n;
  157. do
  158. {
  159. cout << " 1 - объект TA, 2 - объект TB, 3 - объект TC;
  160. cin >> nl
  161. }
  162. while(n < 1 || n > 3);
  163. switch (n)
  164. {
  165. case 1:
  166. uk = new TA; break;
  167. case 2:
  168. uk = new TB; break;
  169. case 3:
  170. uk = new TC; break;
  171. }
  172.  
  173. uk - > fff();
  174. ...//все 100 виртуальных методов
  175. delete uk;
  176. }
  177.  
  178.  
  179. Виртуальных конструкторов быть не может.
  180.  
  181. Достаточно часто в базовом классе виртуальный метод не имеет собственной осмысленной реализации.
  182.  
  183. Пример:
  184. геометрическая фигура
  185. базовый класс - фигура
  186. от этого класса наследуем прямоугольник/трапеция/окружность..........
  187.  
  188. В таком случае виртуальный метод делают чисто виртуальным.
  189. Класс который содержит хотя бы 1 чисто виртуальный метод - абстрактный.
  190. Особенно чисто виртуальных функций и абстрактных классов:
  191. 1)Прописывать реализацию чисто виртуального метода не надо
  192. 2)Нельзя создавать объекты абстрактных классов, они используются только для того, чтобы от них что-то наследовалось
  193. 3)Чистая виртуальность передается по наследству, пока функция не получит реализацию, после этого она становится виртуальной
  194.  
  195. Чисто виртуальная : virtual прототип_деструктора = 0
  196.  
  197. Пример 3:
  198. Окрашенная фигура на плоскости.
  199.  
  200. Фигура
  201. / | \
  202. Прямоугольник Круг Трапеция
  203.  
  204.  
  205. class TFig
  206. {
  207. int color;
  208. public:
  209. TFig(int c=0)
  210. virtual float sq() = 0;
  211. };
  212. TFig::TFig(int c)
  213. {
  214. color = c;
  215. }
  216. //
  217.  
  218.  
  219. class TPr:public TFig
  220. {
  221. float a, b; //ширина + высота
  222. public:
  223. TPr(int c = 0, float a = 1, float b = 2);
  224. float sq();
  225. };
  226. //Реализация конструктора
  227. float TPr()
  228. {
  229. return a*b;
  230. }
  231.  
  232. Также для классов круг и трапеция.
  233. class TCirc:public TFig
  234. class TTr:public TFig
  235.  
  236. Точно также как в примере 2 можно организовать меню для выбора фигуры, в операторе switch будет выделяться память под прямоугольник,
  237. круг или трапецию, далее будет выполнятсья метод вычисления площади + другие методы, если бы они были
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement