Главная страница Случайная страница Разделы сайта АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
💸 Как сделать бизнес проще, а карман толще?
Тот, кто работает в сфере услуг, знает — без ведения записи клиентов никуда. Мало того, что нужно видеть свое раписание, но и напоминать клиентам о визитах тоже.
Проблема в том, что средняя цена по рынку за такой сервис — 800 руб/мес или почти 15 000 руб за год. И это минимальный функционал.
Нашли самый бюджетный и оптимальный вариант: сервис VisitTime.⚡️ Для новых пользователей первый месяц бесплатно. А далее 290 руб/мес, это в 3 раза дешевле аналогов. За эту цену доступен весь функционал: напоминание о визитах, чаевые, предоплаты, общение с клиентами, переносы записей и так далее. ✅ Уйма гибких настроек, которые помогут вам зарабатывать больше и забыть про чувство «что-то мне нужно было сделать». Сомневаетесь? нажмите на текст, запустите чат-бота и убедитесь во всем сами! Листинг 15.7. Использование классов-друзей
1: #include < iostream.h> 2: 3: 4: 5: 6: // **************** Класс Part ************ 7: 8: // Абстрактный базовый класс всех деталей 9: class Part 10: { 11: public: 12: Part(): itsPartNumber(1) { } 13: Part(int PartNumber): 14: itsPartNumber(PartNumber){ } 15: virtual ~Part(){ } 16: int GetPartNumber() const 17: { return itsPartNumber; } 18: virtual void Display() const =0; 19: private: 20: int itsPartNumber; 21: }; 22: 23: // выполнение чистой виртуальной функции в 24: // стандартном виде для всех производных классов 25: void Part:: Display() const 26: { 27: cout < < " \nPart Number: "; 28: cout < < itsPartNumber < < endl; 29: } 30: 31: // ************** Класс Car Part ************ 32: 33: class CarPart: public Part 34: { 35: public: 36: CarPart(): itsModelYear(94){ } 37: CarPart(int year, int partNumber); 38: virtual void Display() const 39: { 40: Part:: Display(); 41: cout < < " Model Year: "; 42: cout < < itsModelYear < < endl; 43: } 44: private: 45: int itsModelYear; 46: }; 47: 48: CarPart:: CarPart(int year, int partNumber): 49: itsModelYear(year), 50: Part(partNumber) 51: { } 52: 53: 54: // *********** Класс AirPlane Part *********** 55: 56: class AirPlanePart: public Part 57: { 58: public: 59: AirPlanePart(): itsEngineNumber(1){ }; 60: AirPlanePart 61: (int EngineNumber, int PartNumber); 62: virtual void Display() const 63: { 64: Part:: Display(); 65: cout < < " Engine No.: "; 66: cout < < itsEngineNumber < < endl; 67: } 68: private: 69: int itsEngineNumber; 70: }; 71: 72: AirPlanePart:: AirPlanePart 73: (int EngineNumber, int PartNumber): 74: itsEngineNumber(EngineNumber), 75: Part(PartNumber) 76: { } 77: 78: // **************** Класс Part Node ************ 79: class PartNode 80: { 81: public: 82: friend class PartsList; 83: PartNode (Part*); 84: ~PartNode(); 85: void SetNext(PartNode * node) 86: { itsNext = node; } 87: PartNode * GetNext() const; 88: Part * GetPart() const; 89: private: 90: Part *itsPart; 91: PartNode * itsNext; 92: }; 93: 94: 95: PartNode:: PartNode(Part* pPart): 96: itsPart(pPart), 97: itsNext(0) 98: { } 99: 100: PartNode:: ~PartNode() 101: { 102: delete itsPart; 103: itsPart = 0; 104: delete itsNext; 105: itsNext = 0; 106: } 107: 108: // Возвращается NULL, если нет следующего узла PartNode 109: PartNode * PartNode:: GetNext() const 110: { 111: return itsNext; 112: } 113: 114: Part * PartNode:: GetPart() const 115: { 116: if (itsPart) 117: return itsPart; 118: else 119: return NULL; //ошибка 120: } 121: 122: 123: // ************** Класс Part List 124: class PartsList 125: { 126: public: 127: PartsList(); 128: ~PartsList(); 129: // Необходимо, чтобы конструктор-копировщик и оператор соответствовали друг другу 130: void Iterate(void (Part:: *f)()const) const; 131: Part* Find(int & position, int PartNumber) const; 132: Part* GetFirst() const; 133: void Insert(Part *); 134: Part* operator[](int) const; 135: int GetCount() const { return itsCount; } 136: static PartsList& GetGlobalPartsList() 137: { 138: return GiobalPartsList; 139: } 140: private: 141: PartNode * pHead; 142: int itsCount; 143: static PartsList GiobalPartsList; 144: }; 145: 146: PartsList PartsList:: GlobalPartsList; 147: 148: // Implementations for Lists... 149: 150: PartsList:: PartsList(); 151: pHead(0), 152: itsCount(0) 153: { } 154: 155: PartsList:: ~PartsList() 156: { 157: delete pHead; 158: } 159: 160: Part* PartsList:: GetFirst() const 161: { 162: if (pHead) 163: return pHead-> itsPart; 164: else 165: return NULL; // ловушка ошибок 166: } 167: 168: Part * PartsList:: operator[](int offSet) const 169: { 170: PartNode* pNode = pHead; 171: 172: if (! pHead) 173: return NULL; // ловушка ошибок 174: 175: if (offSet > itsCount) 176: return NULL; // ошибка 177: 178: for (int i=0; i< offSet; i++) 179: pNode = pNode-> itsNext; 180: 181: return pNode-> itsPart; 182: } 183: 184: Part* PartsList:: Find(int & position, int PartNumber) const 185: { 186: PartNode * pNode = 0; 187: for (pNode = pHead, position = 0; 188: pNode! =NULL; 189: pNode = pNode-> itsNext, position++) 190: { 191: if (pNode-> itsPart-> GetPartNumber() == PartNumber) 192: break; 193: } 194: if (pNode == NULL) 195: return NULL; 196: else 197: return pNode-> itsPart; 198: } 199: 200: void PartsList:: Iterate(void (Part:: *func)()const) const 201: { 202: if (! pHead) 203: return; 204: PartNode* pNode = pHead; 205: do 206: (pNode-> itsPart-> *func)(); 207: while (pNode = pNode-> itsNext); 208: } 209: 210: void PartsList:: Insert(Part* pPart) 211: { 212: PartNode * pNode = new PartNode(pPart); 213: PartNode * pCurrent = pHead; 214: PartNode * pNext = 0; 215: 216: int New = pPart-> GetPartNumber(); 217: int Next = 0; 218: itsCount++; 219: 220: if (! pHead) 221: { 222: pHead = pNode; 223: return; 224: } 225: 226: // если это значение меньше головного узла, 227: // то текущий узел становится головным 228: if (pHead-> itsPart-> GetPartNumber() > New) 229: { 230: pNode-> itsNext = pHead; 231: pHead = pNode; 232: return; 233: } 234: 235: for (;;) 236: { 237: // если нет следующего, вставляется текущий 238: if (! pCurrent-> itsNext) 239: { 240: pCurrent-> itsNext = pNode; 241: return; 242: } 243: 244: // если текущий больше предыдущего, но меньше следующего, то вставляем 245: // здесь. Иначе присваиваем значение указателя Next 246: pNext = pCurrent-> itsNext; 247: Next = pNext-> itsPart-> GetPartNumber(); 248: if (Next > New) 249: { 250: pCurrent-> itsNext = pNode; 251: pNode-> itsNext = pNext; 252: return; 253: } 254: pCurrent = pNext; 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 = new AirPlanePart(value, PartNumber); 334: } 335: pc.Insert(pPart); 336: } 337: pc.ShowAll(); 338: return 0; 339: }
Результат: (0)Quit (1)Cat (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
Анализ: В строке 82 класс PartsList объявляется другом класса PartNode. В данном случае объявление класса другом происходит в разделе public объявления класса PartNode, но так поступать вовсе не обязательно. Это объявление можно размещать в любом месте объявления класса, что не изменит его суть. В результате объявления класса как друга все закрытые методы и переменные-члены класса PartNode становятся доступными любой функции-члену класса PartsList. В строке 160 были внесены изменения в вызове функции-члена GetFirst() с учетом появившихся новых возможностей. Теперь вместо возвращения pHead-> GetPart эта функция может возвращать закрытую переменную-член pHead-> itsPart. Аналогичным образом в функции Insert() можно написать pNode-> itsNext = pHead вместо переменной-члена pHead-> SetNext(pHead). В данном случае внесенные изменения существенно не улучшили код программы, поэтому нет особых причин делать класс PartsList другом PartNode. В данном примере просто хотелось проиллюстрировать, как работает ключевое слово friend. Объявление классов-друзей следует применять с осторожностью. Класс объявляется как друг какого-либо иного класса в том случае, когда два класса тесно взаимодействуют друг с другом и открытие доступа одного класса к данным и методам другого класса существенно упрощает код программы. Однако зачастую проще организовать взаимодействие между классами с помощью открытых методов доступа.
Примечание: От начинающих программистов C++ часто можно услышать замечание, что объявление классов-друзей противоречит принципу инкапсуляции, лежащему в основе объектно-ориентированного программирования. Это, честно говоря, довольно широко распространенная бессмыслица. Объявление класса-друга просто расширяет интерфейс другого класса, что влияет на инкапсуляцию не больше, чем открытое наследование классов.
|