Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


День 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 из строковой константы.


Поделиться:



Популярное:

  1. Geld verdienen – зарабатывать деньги
  2. II. КАК ВЫЗДОРОВЕТЬ ОТ НЕИЗЛЕЧИМОЙ БОЛЕЗНИ ЗА ОДИН ДЕНЬ.
  3. Microsoft Office Word. Дополнительные функции
  4. S. Принимать по 1 таблетке 1 раз в день утром
  5. Seat крючки через бар под сиденье Коулинг на задней
  6. Амфифильные полимеры N-винилпирролидона, содержащие дополнительные функциональные группы
  7. Аналитическая платформа «Контур Стандарт» как инструмент реализации ROLAP-технологии: основные возможности, особенности и технология анализа информации
  8. Аналитические возможности, задачи и основные направления анализа СНС
  9. Аналитические фотограмметрические приборы ,назначение функциональные возможности ( Стереонаграф, SD20, SD2000)
  10. Аппараты для массового культивирования клеток. Типы, режимы работы и возможности использования для культивирования клеток.
  11. В день суда – а он неизбежен – каждый будет отвечать перед Богом за себя лично.
  12. В какой экономической теории источником богатства считали сферу обращения, а богатство отождествлялось с деньгами?


Последнее изменение этой страницы: 2017-03-08; Просмотров: 570; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.045 с.)
Главная | Случайная страница | Обратная связь