Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь 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; просмотров: 364; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 216.73.216.170 (0.007 с.) |