Главная страница Случайная страница КАТЕГОРИИ: АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника |
Листинг 10.5. Конструктор-копировщик
1: // Листинг 10.5. 2: // Конструктор-копировщик 3: 4: #include < iostream.h> 5: 6: class CAT 7: { 8: public: 9: CAT(); // конструктор по умолчанию 10: CAT (const CAT &); // конструктор-копировщик 11: ~CAT(); // деструктор 12: int GetAge() const { return *itsAge; } 13: int GetWeight() const { return *itsWeight; } 14: void SetAge(int age) { *itsAge = age; } 15: 16: private: 17: int *itsAge; 18: int *itsWeight; 19: }; 20: 21: CAT:: CAT() 22: { 23: itsAge = new int; 24: itsWeight = new int; 25: *itsAge = 5; 26: *itsWeight = 9; 27: } 28: 29: CAT:: CAT(const CAT & rhs) 30: { 31: itsAge = new int; 32: itsWeight = new int; 33: *itsAge = rhs.GetAge(); // открытый метод доступа 34: *itsWeight = *(rhs.itsWeight); // закрытый метод доступа 35: } 36: 37: CAT:: ~CAT() 38: { 39: delete itsAge; 40: itsAge = 0; 41: delete itsWeight; 42: itsWeight = 0; 43: } 44: 45: int main() 46: { 47: CAT frisky; 48: cout < < " frisky's age: " < < frisky.GetAge() < < endl; 49: cout < < " Setting frisky to 6...\n"; 50: frisky.SetAge(6); 51: cout < < " Creating boots from frisky\n"; 52: CAT boots(frisky); 53: cout < < " frisky's age: " < < frisky.GetAge() < < endl; 54: cout < < " boots' age; " < < boots.GetAge() < < endl; 55: cout < < " setting frisky to 7...\n"; 56: frisky.SetAge(7); 57: cout < < " frisky's age: " < < frisky.GetAge() < < endl; 58: cout < < " boot's age: " < < boots.GetAge() < < endl; 59: return 0; 60: }
Результат: frisky's age: 5 Setting frisky to 6... Creating boots from frisky frisky's age: 6 boots' age: 6 setting frisky to 7... frisky's age: 7 boots' age: 6
Анализ: В строках программы с 6 по 19 объявляется класс CAT. Обратите внимание, что в строке 9 объявляется конструктор по умолчанию, а в строке 10 — конструктор-копировщик. В строках 17 и 18 объявляется две переменные-члены, представляющие собой указатели на целочисленные значения. В реальной жизни трудно вообразить, для чего может понадобиться создание переменных-членов как указателей на целочисленные значения. Но в данном случае такие переменные являются отличными объектами для демонстрации методов управления переменными-членами, сохраненными в динамической области памяти. Конструктор по умолчанию в строках с 21 по 27 выделяет для переменных области динамической памяти и инициализирует эти переменные. Работа копировщика начинается со строки 29. Обратите внимание, что в копировщике задан параметр rhs. Использовать в параметрах копировщиков символику rhs, что означает right-hand side (стоящий справа), — общепринятая практика. Если вы посмотрите на строки 33 и 34, то увидите, что в выражениях присваивания имена параметров копировщика располагаются справа от оператора присваивания (знака равенства). Вот как работает копировщик. Строки 31 и 32 выделяют свободные ячейки в области динамической памяти. Затем, в строках 33 и 34 в новые ячейки переписываются значения из существующего класса CAT. Параметр rhs соответствует объекту классу CAT, который передается в копировщик в виде константной ссылки. Как объект класса CAT, rhs содержит все переменные- члены любого другого класса CAT. Любой объект класса CAT может открыть доступ к закрытым переменным-членам для любого другого объекта класса CAT. В то же время для внешних обращений всегда лучше создавать открытые члены, где это только возможно. Функция-член rhs.GetAge() возвращает значение, сохраненное в переменной-члене itsAge, адрес которой представлен в rhs. Процедуры, осуществляемые программой, продемонстрированы на рис. 10.3. Значение, на которое ссылалась переменная-член исходного класса CAT, копируется в новую ячейку памяти, адрес которой представлен в такой же переменной-члене нового класса CAT. В строке 47 вызывается объект frisky из класса CAT. Значение возраста, заданное в frisky, выводится на экран, после чего в строке 50 переменной возраста присваивается новое значение — 6. В строке 52 методом копирования объекта frisky создается новый объект boots класса CAT. Если бы в качестве параметра передавался объект frisky, то вызов копировщика осуществлялся бы компилятором. В строках 53 и 54 выводится возраст обеих кошек. Обратите внимание, что в обоих случаях в объектах frisky и boots записан возраст 6, тогда как если бы объект boots создавался не методом копирования, то по умолчанию было бы присвоено значение 5. В строке 56 значение возраста в объекте было изменено на 7 и вновь выведены на экран значения обоих объектов. Значение объекта frisky действительно изменилось на 7, тогда как в boots сохранилось прежнее значение возраста 6. Это доказывает, что переменная объекта frisky была скопирована в объект boots по новому адресу.
Рис. 10.3 Пример глубинного копирования
Когда выполнение программы выходит за область видимости класса CAT, автоматически запускается деструктор. Выполнение деструктора класса CAT показано в строках с 37 по 43. Оператор delete применяется к обоим указателям — itsAge и itsWeigth, после чего оба указателя для надежности обнуляются.
|