Программирование >>  Дополнительные возможности наследования 

1 ... 155 156 157 [ 158 ] 159 160 161 ... 265


ствуют друг с другом и открытие доступа одного класса к данным и методам другого класса существенно упрощает код профаммы. Однако зачастую проще организовать взаимодействие между классами с помощью открытых методов доступа.


примечание

От начинающих программистов С++ часто можно услышать замечание, что объявление классов-друзей противоречит принципу инкапсуляции, лежащему в основе объектно-ориентированного программирования. Это, честно говоря, довольно широко распространенная бессмыслица. Объявление класса-друга просто расширяет интерфейс другого класса, что влияет на инкапсуляцию не больше, чем открытое наследование классов.

Дружественный класс

Объявление одного класса другом какого-либо иного с помощью ключевого слова friend в объявлении второго класса открывает первому классу доступ к членам второго класса. Иными словами, я могу объявить вас своим другом, но вы не можете объявить себя моим другом. Пример:

ь;,:p(iblieH:j;?-:* ;;-:- у/уу: уЯ - и :Уух: MxP ~W

; :::г1е

Шункции-друзья

Иногда бывает необходимо предоставить права доступа не всему классу, а только одной или нескольким функциям-членам. Это реализуется посредством объявления друзьями функций-членов другого класса. Причем объявлять другом весь класс вовсе не обязательно. Фактически другом можно объявить любую функцию, независимо от того, является ли она функцией-членом другого класса или нет.

Шункции-друзья и перегрузка оператора

в листинге 15.1 представлен класс String, в котором перегружается operator+. В нем также объявляется конструктор, принимающий указатель на константную строку, поэтому объект класса String можно создавать из строки с концевым нулевым символом.


нримечанне

Строки в С и С++ представляют собой массивы символов, заканчивающиеся концевым нулевым символом. Такая строка получается, например, в следующем выражении присвоения: myString[ ] = Hello World .



Но чего невозможно сделать в классе string, так это получить новую строку в результате сложения объекта этого класса с массивом символов:

char cString[] = { Hello } ; String sString( World ):

String sStringTwo = cString + sString; ошибка!

Строки нельзя использовать с перефуженной функции operator+. Как объяснялось на занятии 10, выражение cString + sString на самом деле вызывает функцию cString.operator+(sString). Поскольку функция operator+() не может вызываться для символьной строки, данная попытка приведет к ошибке компиляции.

Эту проблему можно решить, объявив функцию-друга в классе String, которая пе-рефужает operator+ таким образом, чтобы суммировать два объекта string. Соответствующий конструктор класса string преобразует строки в объекты String, после чего вызывается функция-друг operator+, выполняющая конкатенацию двух объектов.

Аисшинг 15.8. Функцня-уруг operateг+

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

Листинг 15.8. Операторы друзья

Sinclude <iostream.h> Sinclude <string.h>

Рудиментарный класс string

class String

public: constructors StringO;

String(const char *const); String(const String &); StringO;

перегруженные операторы char & operator[](int offset); char operator[](int offset) const; String operator+(const String&);

friend String operator+(const Strings const String*); void operator+=(const String&); String & operator= (const String &);

методы общего доступа

int GetLen( )const { return itsLen; }

const char ♦ GetStringO const { return itsString; }

private:

String (int); закрытый конструктор char * itsString; unsigned short itsLen;



34: конструктор, заданный по умолчанию, создает строку длиной О байт

35; String::String()

36; {

37: itsString = new char[1];

38; itsString[0] = \ 0;

39: itsLen=0;

40: cout << X tDefault string constructor\ n ;

41: ConstructorCount++;

42: } 43:

44: закрытый конструктор, используемый только

45: методами класса для создания новой строки

46: указанного размера, заполненной нулями.

47: String;:String(int len)

48: {

49: itsString = new char[len+1];

50: for (int i = 0; i<=len; i++)

51: itsString[i] = \ 0 ;

52; itsLen=len;

53: cout \ tString(int) constructor\ n ;

54: ConstructorCount++;

55: } 56:

57: Преобразует массив символов в строку

58: String::String(const char * const cString)

59: {

60: itsLen = strlen(cString);

61: itsString = new char[itsLen+1];

62: for (int i = 0; i<itsLen; i++)

63: itsString[i] = cString[i];

64; itsString[itsLen]=\ 0;

65: cout X tString(char*) constructor\ n ;

66: ConstructorCount++;

67: I 68:

69: конструктор-копировщик

70: String::String (const String & rhs)

71: {

72; itsLen=rhs.GetLen();

73: itsString = new char[itsLen+1];

74; for (int i = 0; i<itsLen;i++)

75: itsString[i] = rhs[i];

76: itsString[itsLen] = \ 0 ;

77; cout X tString(String&) constructor\ n ;

78: ConstructorCount++:

79; } 80:

81; деструктор, освобождает занятую память

82: String::String ()

83: {



1 ... 155 156 157 [ 158 ] 159 160 161 ... 265

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика