Бьерн Страуструп - Абстракция данных в языке С++ - Дружественные и составляющие функции

ОГЛАВЛЕНИЕ

            Дружественные и составляющие функции

      Если новая операция должна быть добавлена в класс, есть
  фактически два пути ее реализации - как дружественной функции или
  как составляющей. Зачем предоставляются две альтернативы, и для
  какого рода операций каждая из них предпочтительнее ?
      Дружественная функция есть совершенно обычная функция,
  отличающаяся лишь своим правом на использование приватных имен
  членов класса. Программирование с использованием дружественных
  функций есть во многом программирование в условиях, когда как
  будто бы и нет никакого упрятывания информации.

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

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

      class matrix { 
            friend matrix operator * (matrix, vector);
            ...
      };
      class vector {
            friend matrix operator * (matrix, vector);
            ...
      };

  Необходимо бы было иметь две составляющих функции -
  m a t r i x . o p e r o t o r ( ) и v e c t o r . o p e r a t o r ()
  -для достижения того, что обеспечивает дружественная функция
  o p e r a t o r * ( ) .

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

      Наконец, если нет очевидных причин для предпочтения одной
  реализации операции другой, следует выбрать составляющую функцию.