Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
💸 Как сделать бизнес проще, а карман толще?
Тот, кто работает в сфере услуг, знает — без ведения записи клиентов никуда. Мало того, что нужно видеть свое раписание, но и напоминать клиентам о визитах тоже.
Проблема в том, что средняя цена по рынку за такой сервис — 800 руб/мес или почти 15 000 руб за год. И это минимальный функционал.
Нашли самый бюджетный и оптимальный вариант: сервис VisitTime.⚡️ Для новых пользователей первый месяц бесплатно. А далее 290 руб/мес, это в 3 раза дешевле аналогов. За эту цену доступен весь функционал: напоминание о визитах, чаевые, предоплаты, общение с клиентами, переносы записей и так далее. ✅ Уйма гибких настроек, которые помогут вам зарабатывать больше и забыть про чувство «что-то мне нужно было сделать». Сомневаетесь? нажмите на текст, запустите чат-бота и убедитесь во всем сами! Листинг 15.6. Закрытое наследование
1: // Листинг 15.6. Закрытое наследование 2: #include < iostream.h> 3: 4: //****************Класс Part ************ 5: 6: // Абстрактный базовый класс всех деталей 7: class Part 8: { 9: public: 10: Part(): itsPartNumber(1) { } 11: Part(int PartNumber): 12: itsPartNumber(PartNumber){ } 13: virtual ~Part(){ } 14: int GetPartNumber() const 15: { return itsPartNumber; } 16: virtual void Display() const =0; 17: private: 18: int itsPartNumber; 19: }; 20: 21: // выполнение чистой виртуальной функции в 22: // стандартном виде для всех производных классов 23: void Part:: Display() const 24: { 25: cout < < " \nPart Number: " < < itsPartNumber < < endl; 26: } 27: 28: // **************** Car Part ************ 29: 30: class CarPart: public Part 31: { 32: public: 33: CarPart(): itsModelYear(94){ } 34: CarPart(int year, int partNumber); 35: virtual void Display() const 36: { 37: Part:: Display(); 38: cout < < " Model Year: "; 39: cout < < itsModelYear < < endl; 40: } 41: private: 42: int itsModelYear; 43: }; 44: 45: CarPart:: CarPart(int year, int partNumber): 46: itsModelYear(year), 47: Part(partNumber) 48: { } 49: 50: 51: // *********** Класс AirPlane Part ********** 52: 53: class AirPlanePart: public Part 54: { 55: public: 56: AirPlanePart(): itsEngineNumber(1){ } 57: AirPlanePart 58: (int EngineNumber, int PartNumber); 59: virtual void Display() const 60: { 61: Part:: Display(); 62: cout < < " Engine No.: "; 63: cout < < itsEngineNumber < < endl; 64: } 65: private: 66: int itsEngineNumDer; 67: }; 68: 69: AirPlanePart:: AirPlanePart 70: (int EngineNumber, int PartNumber): 71: itsEngineNumber(EngineNumber), 72: Part(PartNumber) 73: { } 74: 75: // ************ Класс Part Node ************ 76: class PartNode 77: { 78: public: 79: PartNode (Part> >); 80: ~PartNode(); 81: void SetNext(PartNode * node) 82: { itsNext = node; } 83: PartNode * GetNext() const; 84: Part * GetPart() const; 85: private: 86: Part *itsPart; 87: PartNode * itsNext; 88: }; 89: //Выполнение PartNode... 90: 91: PartNode:: PartNode(Part* pPart): 92: itsPart(pPart), 93: itsNext(0) 94: { } 95: 96: PartNode:: ~PartNode() 97: { 98: delete itsPart; 99: itsPart = 0; 100: delete itsNext; 101: itsNext = 0; 102: } 103: 104: // Возвращает NULL NULL, если нет следующего узла PartNode 105: PartNode * PartNode:: GetNext() const 106: { 107: return itsNext; 108: } 109: 110: Part * PartNode:: GetPart() const 111: { 112: if (itsPart) 113: return itsPart; 114: else 115: return NULL; //ошибка 116: } 117: 118: 119: 120: // ************ Класс Part List ************ 121: class PartsList 122: { 123: public: 124: PartsList(); 125: ~PartsList(); 126: // Необходимо, чтобы конструктор-копировщик и оператор соответствовали друг другу! 127: void Iterate(void (Part:: *f)()const) const; 128: Part* Find(int & position, int PartNumber) const; 129: Part* GetFirst() const; 130: void Insert(Part *); 131: Part* operator[](int) const; 132: int GetCount() const { return itsCount; } 133: static PartsList& GetGlobalPartsList() 134: { 135: return GiobalPartsList; 136: } 137: private: 138: PartNode * pHead; 139: int itsCount; 140: static PartsList GiobalPartsList; 141: }; 142: 143: PartsList PartsList:: GlobalPartsList; 144: 145: 146: PartsList:: PartsList(): 147: pHead(0), 148: itsCount(0) 149: { } 150: 151: PartsList:: ~PartsList() 152: { 153: delete pHead; 154: } 155: 156: Part* PartsList:: GetFirst() const 157: { 158: if (pHead) 159: return pHead-> GetPart(); 160: else 161: return NULL; // ловушка ошибок 162: } 163: 164: Part * PartsList:: operator[](int offSet) const 165: { 166: PartNode* pNode = pHead; 167: 168: if (! pHead) 169: return NULL; // ловушка ошибок 170: 171: if (offSet > itsCount) 172: return NULL; // ошибка 173: 174: for (int i=0; i< offSet; i++) 175: pNode = pNode-> GetNext(); 176: 177: return pNode-> GetPart(); 178: } 179: 180: Part* PartsList:: Find( 181: int & position, 182: int PartNumber) const 183: { 184: PartNode * pNode = 0; 185: for (pNode = pHead, position = 0; 186: pNode! =NULL; 187: pNode = pNode-> GetNext(), position++) 188: { 189: if (pNode-> GetPart()-> GetPartNumber() == PartNumber) 190: break; 191: } 192: if (pNode == NULL) 193: return NULL; 194: else 195: return pNode-> GetPart(); 196: } 197: 198: void PartsList:: Iterate(void (Part:: *func)()const) const 199: { 200: if (! pHead) 201: return; 202: PartNode* pNode = pHead; 203: do 204: (pNode-> GetPart()-> *func)(); 205: while (pNode = pNode-> GetNext()); 206: } 207: 208: void PartsList:: Insert(Part* pPart) 209: { 210: PartNode * pNode = new PartNode(pPart); 211: PartNode * pCurrent = pHead; 212: PartNode * pNext = 0; 213: 214: int New = pPart-> GetPartNumber(); 215: int Next = 0; 216: itsCount++; 217: 218: if (! pHead) 219: { 220: pHead = pNode; 221: return; 222: } 223: 224: // если это значение меньше головного узла, 225: // то текущий узел становится головным 226: if (pHead-> GetPart()-> GetPartNumber()-> New) 227: { 228: pNode-> SetNext(pHead); 229: pHead = pNode; 230: return; 231: } 232: 233: for (;;) 234: { 235: // еcли нет следующего, вставляется текущий 236: if (! pCurrent-> GetNext()) 237: { 238: pCurrent-> SetNext(pNode); 239: return; 240: } 241: 242: // если текущий больше предыдущего, но меньше следующего, то вставляем 243: // здесь, Иначе присваиваем значение указателя Next 244: pNext = pCurrent-> GetNext(); 245: Next = pNext-> GetPart()-> GetPartNumber(); 246: if (Next > New) 247: { 248: pCurrent-> SetNext(pNode); 249: pNode-> SetNext(pNext); 250: return; 251: } 252: pCurrent = pNext; 253: } 254: } 255: 256: 257: 258: class PartsCatalog: private PartsList 259: { 260: public: 261: void Insert(Part *); 262: int Exists(int PartNumber); 263: Part * Get(int PartNumber); 264: operator+(const PartsCatalog &); 265: void ShowAll() { Iterate(Part:: Display); } 266: private: 267: }; 268: 269: void PartsCatalog:: Insert(Part * newPart) 270: { 271: int partNumber = newPart-> GetPartNumber(); 272: int offset; 273: 274: if (! Find(offset, partNumber)) 275: PartsList:: Insert(newPart); 276: else 277: { 278: cout < < partNumber < < " was the "; 279: switch (offset) 280: { 281: case 0: cout < < " first "; break; 282: case 1: cout < < " second "; break; 283: case 2: cout < < " third "; break; 284: default: cout < < offset+1 < < " th "; 285: } 286: cout < < " entry. Rejected! \n"; 287: } 288: } 289: 290: int PartsCatalog:: Exists(int PartNumber) 291: { 292: int offset; 293: Find(offset, PartNumber); 294: return offset; 295: } 296: 297: Part * PartsCatalog:: Get(int PartNumber) 298: { 299: int offset; 300: return (Find(offset, PartNumber)); 301: 302: } 303: 304: int main() 305: { 306: PartsCatalog pc; 307: Part * pPart = 0; 308: int PartNumber; 309: int value; 310: int choice; 311: 312: while (1) 313: { 314: cout < < " (0)Quit (1)Car (2)Plane: "; 315: cin > > choice; 316: 317: if (! choice) 318: break; 319: 320: cout < < " New PartNumber?: "; 321: cin > > PartNumber; 322: 323: if (choice == 1) 324: { 325: cout < < " Model Year?: "; 326: cin > > value; 327: pPart = new CarPart(value, PartNumber); 328: } 329: else 330: { 331: cout < < " Engine Number?: "; 332: cin > > value; 333: pPart = newAirPlanePart(value, PartNumber); 334: } 335: pc.Insert(pPart); 336: } 337: pc.ShowAll(); 338: return 0; 339: }
Результат: (0)Quit (1)Car (2)Plane: 1 New PartNumber?: 1234 Model Year?: 94 (0)Quit (1)Car (2)Plane: 1 New PartNumber?: 4434 Model Year?: 93 (0)Quit (1)Car (2)Plane: 1 New PartNumber?: 1234 Model Year?: 94 1234 was the first entry. Rejected! (0)Quit (1)Car (2)Plane: 1 New PartNumber?: 2345 Model Year?: 93 (0)Quit (1)Car (2)Plane: 0 Part Number: 1234 Model Year: 94 Part Number: 2345 Model Year: 93 Part Number: 4434 Model Year: 93
Анализ: В листинге 15.6 был изменен интерфейс класса PartsCatalog и переписана функция main(). Интерфейсы других классов остались такими же, как и в листинге 15.5. В строке 258 листинга 15.6 класс PartsCatalog производится как private от класса PartsList. Интерфейс класса PartsCatalog остался таким же, как и в листинге 15.5, хотя, конечно же, необходимость в объектах класса PartsList как переменных-членах отпала. Функция-член ShowAll() класса PartsCatalog вызывает функцию Iterate() из PartsList, параметром которой задается указатель на функцию-член класса Part. Таким образом, функция ShowAll() выполняет роль открытого интерфейса, позволяя пользователям получать информацию, не обращаясь напрямую к закрытой функции Iterate(), прямой доступ к которой закрыт для клиентов класса PartsCatalog. Функция Insert()тоже изменилась. Обратите внимание, в строке 274 функция Find() теперь вызывается непосредственно, поскольку она наследуется из базового класса. Чтобы при вызове функции Insert() не возникло зацикливания функции на самое себя, в строке 275 делается явный вызов функции с указанием имени класса. Таким образом, если методам класса PartsCatalog необходимо вызвать методы PartsList, они могут делать это напрямую. Единствейное исключение состоит в том, что при необходимости заместить метод базового класса в классе PartsList следует явно указать класс и имя функции. Закрытое наследование позволяет PartsCatalog унаследовать функциональность базового класса и создавать интерфейс, косвенно открывающий доступ к его методам, которые нельзя вызывать напрямую.
Рекомендуется: Применяйте открытое наследование, когда производный класс является разновидностью базового. Используйте вложение классов, когда необходимо делегировать выполнение задач другому классу, ограничив при этом доступ к его защищенным членам. Применяйте закрытое наследование, если необходимо реализовать один класс в пределах другого и обеспечить доступ к защищенным членам базового класса.
Не рекомендуется: Не применяйте закрытое наследование, если необходимо использовать более одного объекта базового класса. Для этих целей больше подойдет вложение классов. Например, если для одного объекта PartsCatalog необходимы два объекта PartsList, вы не сможете использовать закрытое наследование. Не используйте открытое наследование, если необходимо закрыть клиентам производного класса прямой доступ к методам базового класса.
|