Анимация
JavaScript
|
Главная Библионтека 93. Пользуйтесь контрольными таблицами Одной из причин того, что Си++ имеет такую крутую кривую обучения, заключается в том, что вы должны отслеживать большое количество деталей, чтобы выполнить даже простые задачи. Просто забыть что-то, даже если вы это сделаете не надолго. Я решаю эту проблему, применяя повсюду несколько образцовых шаблонных файлов - по одному для каждой распространенной ситуации. (У меня есть один для определения базового класса, один - для определения производного класса, и т.д.). Я начинаю с копирования соответствующего шаблона в свой текущий рабочий файл и затем использую возможности своего редактора по поиску и замене для заполнения пустот. Я также перемещаю подходящие функции в файлы .cpp, когда нужно, и т.п.. Листинги 5 и 6 показывают простые шаблонные (в смысле естественного языка, а не языка С++) файлы для базового и производного классов (где кое-что опущено по сравнению с теми, которыми я пользуюсь на самом деле, но идею вы поняли). Листинг 5. base.tem - контрольная таблица для определения базового класса I class base 2{ 3 cls obj; 4 public: 5 virtual 6 ~base ( void ); 7 base ( void ); 8 base ( const base &r ); 9 10 const base &operator=( const base &r ); II private: 12 }; 13 ------------------------------------------------------14 /* виртуальн1Й */ base:: ~base( void ) 15 { 16 } 17 ------------------------------------------------------18 inline base::base( void ) : obj( value ) 19 { 20 } 21 /-------------------------------------------------------22 inline base::base( const base &r ) : obj( r.obj ) 23 {} 24 ------------------------------------------------------25 inline const base& base::operator=( const base &r ) 26 { 27 if( this != &r ) 28 { 2 9 obj = r.obj; 30 } 31 return *this; 32 } Листинг 6. derived.tem - контрольная таблица для определения производного класса 1 class derived : public base 3 cls obj; 4 public: 5 virtual 6 -derived ( void ); 7 derived ( void ); 8 derived ( const derived& r ); 10 const derived &operator=( const derived &r ); 11 12 private: 13 }; 14 ------------------------------------------------------15 /* виртуальн1й */ derived:: ~derived( void ) 16 { 17 } 18 ------------------------------------------------------19 inline derived::derived( void ) : base( value ) , 20 obj( value ) 21 { 22 } 23 ------------------------------------------------------24 inline derived::derived( const derived &r):base(r), 2 5 obj( r.obj ) 26 {} 27 ------------------------------------------------------28 inline const derived& derived::operator=( const derived &r ) 29 { 30 if( this != &r ) 31 { 32 *((base *)this) = r; 3 3 obj = r.obj; 34 } 35 return *this; 36 } 4 Чтобы быть строго корректным, по крайней мере на язхке вхражений Си++, я должен называть поле "компонентом данных-членов". Однако довольно неудобно говорить "компонент данных-членов name", поэтому буду использовать просто "поле", когда его значение ясно из контекста. 94. Сообщения должны выражать возможности, а не запрашивать информацию Объектно-ориентированные и структурные системы склонны подходить к проблемам с диаметрально противоположных направлений. Возьмите в качестве примера скромную запись employee. В структурных системах вы бы использовали тип struct и имели бы доступ к полям этого типа повсюду из своей программы. Например, код для печати записи мог бы свободно повторяться в нескольких сотнях мест программы. Если вы меняете что-то в основе, вроде изменения типа поля name с массива char на 16-битные символы Unicode, то вы должны разыскать каждую ссылку на name и модифицировать ее для работы с новым типом. В хорошо спроектированной объектно-ориентированной системе было бы невозможно получить доступ к полю name.4 Позвольте мне повторить это, потому что эта концепция так фундаментальна: невозможно получить доступ к полю внутри объекта, даже такому простому, как name в объекте employee. Скорее всего вы попросите employee проявить какую-нибудь способность, такую как "напечатать себя", "сохранить себя в базе данных" или "модифицировать себя, взаимодействуя с пользователем". В этом последнем случае обработчик сообщений вывел бы диалоговое окно, которое бы использовалось пользователем для ввода или изменения данных. Главным преимуществом этого подхода является то, что отправитель сообщения может меньше волноваться о том, как организовано внутреннее хранение данных. Пока объект может себя печатать, модифицировать или делать что-нибудь еще - проблемы нет. Вы можете перевести name на Unicode, не затрагивая отправителя сообщения. Этот вопрос рассматривается далее во многих правилах этой главы книги. 95. Вам обычно не удастся переделать имеющуюся структурную программу в объектно-ориентированную Одним из побочных эффектов только что описанной организации является то, что обычно невозможно преобразовать структурный подход в соответствии с этим образом мыслей без полного переписывания кода. 0 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 |