Рассмотрим еще раз перегруженные операторы равенства для класса String, определенные в области видимости пространства имен. Оператор равенства для двух объектов String выглядит следующим образом:
bool operator==( const String &str1, const String &str2 )
{
if ( str1.size() != str2.size() )
return false;
return strcmp( str1.c_str(), str2.c_str() ) ? false : true;
}
Сравните это определение с определением того же оператора как функции-члена:
bool String::operator==( const String &rhs ) const
{
if ( _size != rhs._size )
return false;
return strcmp( _string, rhs._string ) ? false : true;
}
Нам пришлось модифицировать способ обращения к закрытым членам класса String. Поскольку новый оператор равенства– это глобальная функция, а не функция-член, у него нет доступа к закрытым членам класса String. Для получения размера объекта String и лежащей в его основе C-строки символов используются функции-члены size() и c_str().
Альтернативной реализацией является объявление глобальных операторов равенства друзьями
класса String. Если функция или оператор объявлены таким образом, им предоставляется доступ к неоткрытым членам.
Объявление друга (оно начинается с ключевого слова friend) встречается только внутри определения класса. Поскольку друзья не являются членами класса, объявляющего дружественные отношения, то безразлично, в какой из секций – public, private или protected – они объявлены. В примере ниже мы решили поместить все подобные объявления сразу после заголовка класса:
class String {
friend bool operator==( const String &, const String & );
friend bool operator==( const char *, const String & );
friend bool operator==( const String &, const char * );
public:
// ... остальная часть класса String
};
В этих трех строчках три перегруженных оператора сравнения, принадлежащие глобальной области видимости, объявляются друзьями класса String, а следовательно, в их определениях можно напрямую обращаться к закрытым членам данного класса: