Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
День 15-й. Дополнительные возможности наследованияСодержание книги
Поиск на нашем сайте
До настоящего момента вы использовали одиночное и множественное наследование для создания относительно простых связей между классами. Сегодня вы узнаете: • Что такое вложение и как его использовать • Что такое делегирование и как его использовать • Как выполнить один класс внутри другого • Как использовать закрытое наследование Вложение
Анализируя примеры, приведенные на предыдущих занятиях, вы, вероятно, заметили, что в классах допускается использование в переменных-членах объектов других классов. В этом случае программисты на C++ говорят, что внешний класс содержит внутренний. Так, класс Employee в качестве переменных-членов может содержать строковые объекты (с именем сотрудника) и объекты с целочисленными значениями (зарплатой и т.д.). В листинге 15.1 представлен незавершенный, но весьма полезный класс String. Запуск такой программы не приведет к выводу каких-либо результатов, но она потребуется при написании других программ этого занятия. Листинг 15.1. Класс string 1: #include <iostream.h> 2: #include <string.h> 3: 4: class String 5: { 6: public: 7: // конструкторы 8: String(); 9: String(const char *const); 10: String(const String &) 11: ~String(); 12: 13: // перегруженные операторы 14: char & operator[](int offset); 15: char operator[](int offset) const; 16: String operator+(const String&); 17: void operator+=(const String&); 18: String & operator= (const String &); 19: 20: // Общие методы доступа 21: int GetLen()const { return itsLen; } 22: const char * GetString() const { return itsString; } 23: // статический целочисленный счетчик ConstructorCount; 24: 25: private: 26: String (int); // закрытый конструктор 27: char * itsString; 28: unsigned short itsLen; 29: 30: }; 31: 32: // конструктор класса String пo умолчанию создает строку длиной 0 байт 33: String::String() 34: { 35: itsString = new char[1]; 36: itsString[0] = '\0'; 37: itsLen=0; 38: // cout << "\tDefault string constructor\n"; 39: // ConstructorCount++; 40: } 41: 42: // закрытый конструктор, используемый только 43: // методами клаcса для создания новой cтроки 44: // указанного размера, заполненной нулями 45: String::String(int len) 46: { 47: itsString = new ohar[len+1]; 48: for (int i = 0; i<=len; i++) 49: itsString[i] = '\0'; 50: itsLen=len; 51: // cout << "\tString(int) constructor\n"; 52: // ConstructorCount++; 53: } 54: 55: // Преобразует массив символов в cтроку 56: String::String(const char * oonst cString) 57: { 58: itsLen = strlen(cString); 59: itsString = new char[itsLen+1]; 60: for (int i = 0; i<itsLen; i++) 61: itsString[i] = cString[i]; 62: itsString[itsLen]='\0'; 63: // cout << "\tString(char*) constructor\n"; 64: // ConstructorCount++; 65: } 66: 67: // конструктор-копировщик 68: String::String (const String & rhs) 69: { 70: itsLen=rhs.GetLen(); 71: itsString = new char[itsLen+1]; 72: for (int i = 0; i<itsLen;i++) 73: itsString[i] = rhs[i]; 74: itsString[itsLen] = '\0'; 75: // cout << "\tString(String&) constructor\n 76: // ConstructorCount++; 77: } 78: 79: // деструктор освобождает занятую память 80: String::~String () 81: { 82: delete [] itsString; 83: itsLen = 0; 84: // cout << "\tString destructor\n"; 85: } 86: 87: // этот оператор освобождает память, а затем 88: // копирует строку и размер 89: String& String::operator=(const String & rhs) 90: { 91: if (this == &rhs) 92: return *this; 93: delete [] itsString; 94: itsLen=rhs.GetLen(); 95: itsString = new char[itsLen+1]; 96: for (int i = 0; i<itsLen;i++) 97: itsString[i] = rhs[i]; 98: itsString[itsLen] = '\0'; 99: return *this; 100: // cout << "\tString operator=\n"; 101: } 102: 103: // неконстантный оператор индексирования, 104: // возвращает ссылку на символ, который можно 105: // изменить 106: char & String::operator[](int offset) 107: { 108: if (offset > itsLen) 109: return itsString[itsLen-1]; 110: else 111: return itsStnng[offset]; 112: } 113: 114: // константный оператор индексирования, 115: // используется для константных объектов (см. конструктор-копировщик!) 116: char String::operator[](int offset) const 117: { 118: if (offset > itsLen) 119: return itsString[itsLen-1]; 120: else 121: return itsString[offset]; 122: } 123: 124: // создает новую строку, добавляя текущую 125: // строку к rhs 126: String String::operator+(const String& rhs) 127: { 128: int totalLen = itsLen + rhs.GetLen(); 129: String temp(totalLen); 130: int i, j; 131: for (i = 0; i<itsLen; i++) 132: temp[i] = itsString[i]; 133: for (j = 0: j<rhs.GetLen(); j++, i++) 134: temp[i] = rhs[j]; 135: temp[totalLen]='\0'; 136: return temp; 137: } 138: 139: // изменяет текущую строку, ничего не возвращая 140: void String::operator+=(const String& rhs) 141: { 142: unsigned short rhsLen = rhs.GetLen(); 143: unsigned short totalLen = itsLen + rhsLen; 144: String temp(totalLen); 145: int i, j; 146: for (i = 0; i<itsLen; i++) 147: temp[i] = itsString[i]; 148: for (j = 0; j<rhs.GetLen(); j++, i++) 149: temp[i] = rhs[i-itsLen]; 150: temp[totalLen]='\0'; 151: *this = temp; 152: } 153: 154: // int String::ConstructorCount = 0;
Результат: Нет
Анализ: Представленный в листинге 15.1 класс String напоминает другой класс, использованный в листинге 12.12. Однако есть одно важное отличие между этими двумя классами: конструкторы и некоторые функции листинга 12.12 включали операторы вывода на печать, благодаря которым на экране отображались сообщения об их использовании. В листинге 15.1 эти операторы временно заблокированы, но они будут использоваться в следующих примерах. Статическая переменная-член ConstructorCount объявляется и инициализируется соответственно в строках 23 и 154. Значение этой переменной увеличивается на единицу при вызове любого конструктора класса String. Эти функции также заблокированы и будут использоваться в следующих листингах. В листинге 15.2 объявляется класс Employee, содержащий три объекта класса String. Листинг 15.2. Класс Employee 1: #include "String.hpp" 2: 3: class Employee 4: { 5: 6: public: 7: Employee(); 8: Employee(char *, char *, char >>, long); 9: ~Employee(); 10: Employee(const Employee&); 11: Employee & operator= (const Employee &); 12: 13: const String & GetFirstName() const 14: { return itsFirstName; } 15: const String & GetLastName() const { return itsLastName; } 16: const String & GetAddress() const { return itsAddress; } 17: long GetSalary() const { return itsSalary; } 18; 19: void SetFirstName(const String & fNama) 20: { itsFirstName = fName; } 21: void SetLastName(const String & lNama) 22: { itsLastName = lNamo; } 23: void SetAddress(const String & address) 24: { itsAddress = address; } 25: void SetSalary(long salary) { itsSalary = salary; } 26: private: 27: String itsFirstName; 28: String itsLastName; 29: String itsAddress; 30: long itsSalary; 31: }; 32: 33: Employee::Employee(); 34: itsFirstName(""), 35: itsLastName(""), 36: itsAddress(""), 37: itsSalary(0) 38: { } 39: 40: Employee::Employee(char * firstName, char * lastName, 41: char * address, long salary): 42: itsFirstName(firstName), 43: itsLastName(lastName), 44: itsAddress(address), 45: itsSalary(salary) 46: { } 47: 48: Employee::Employee(const Employee & rhs): 49: itsFirstName(rhs.GetFirstName()), 50: itsLastName(rhs,GetLastName()), 51: itsAddress(rhs,GetAddress()), 52: itsSalary(rhs.GetSalary()) 53: { } 54: 55: Employee::~Employea() { } 56: 57: Employee & Employae::Qperator= (const Employee & rhs) 58: { 59: if (thls — &rhs) 60: return *this; 61: 62: itsFlrstName = rhs.GetFlrstName(); 63: itsLastName = rhs,GetLastName(); 64: itsAddress = rhs,GetAddress(); 65: itsSalary = rhs,GetSalary(); 66: 67: return *thls; 68: } 69: 70: int main() 71: { 72: Employee Edie("Jane","Doe","1461 Shore Parkway", 20000); 73: Edie.SetSalary(50000); 74: String LastName("Levine"); 75: Edie.SetLastName(LastName); 76: Edie.SetFirstName("Edythe"); 77: 78: cout << "Имя: "; 79: cout << Edie.GetFirstName().GetString(); 80: cout << " " << Edie.GetLastName().GetString(); 81: cout << ".\nАдрес: "; 82: cout << Edie.GetAddress().GetString(); 83: cout << ".\nЗарплата: "; 84: cout << Edie.GetSalary(); 85: return 0; 86: }
Примечание: Сохраните листинг 15.1 в файле с именем string. hpp. Затем всякий раз, когда понадобится класс String, вы сможете вставить листинг 15.1, просто добавив строку #include "String.hpp". Это первая строка в листинге 15.2.
Результат: Name: Edythe Levine. Address: 1461 Shore Parkway. Salary: 50000
Анализ: В листинге 15.2 объявляется класс Employee, переменными-членами которого выступают три объекта класса String — itsFirstName, itsLastName и itsAddress. В строке 72 создается объект Employee, который инициализируется четырьмя значениями. В строке 73 вызывается метод доступа SetSalary класса Employee, который принимает константное значение 50000. В реальной программе это значение определялось бы либо динамически в процессе выполнения программы, либо устанавливалось бы константой. В строке 74 создается и инициализируется строковой константой объект класса String, который в строке 75 используется в качестве аргумента функции SetLastName(). В строке 76 вызывается метод SetFirstName класса Employee с еще одной строковой константой в качестве параметра. Однако если вы обратитесь к объявлению класса Employee, то увидите, что в нем нет функции SetFirstName(), принимающей строку символов как аргумент. Для функции SetFirstName() в качестве параметра задана константная ссылка на объект String. Тем не менее компилятор не покажет сообщения об ошибке, поскольку в строке 9 листинга 15.1 объявлен конструктор, создающий объект String из строковой константы.
|
||||
Последнее изменение этой страницы: 2016-12-10; просмотров: 269; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.149.238.67 (0.01 с.) |