printКлассы

printДрузья класса и методы с явным объектом

Вызов метода похож на вызов обычной функции, за исключением того, что объект, к которому применяется метод, передается как скрытый аргумент. Получение длины строки можно реализовать как метод:
class String {
  int len;
  char * str;
public:
  int length() const { return len; }
  ...
};
int main()
{ String s;
  ...
  cout<<s.length()<<"\n";
}
или использовать обычную функцию, которой строка передается в качестве параметра. Тогда эта функция для получения доступа к закрытым элементам класса должна быть объявлена внутри класса со спецификатором friend
class String {
  int len;
  char * str;
public:
  friend int length(const String &);
  ...
};
int length(const String & s)
{ return s.len; // необходим доступ к закрытому элементу
}
int main()
{ String s;
  ...
  cout<<length(s)<<"\n";
}
Как реализовать операцию – через метод или дружественную функцию – зависит только от предпочтений программиста, но чаще через обычные функции реализуются такие операции, которым необходимы два или более объекта определяемого типа.

Функция может быть дружественной сразу несколько классам, можно объявить дружественным метод другого класса. Если многие методы другого класса должны иметь доступ к закрытым элементам, то можно объявить дружественным весь класс: friend class имя класса;

Спецификаторы доступа не оказывают влияния на друзей класса. Друзей класса можно описывать в любом разделе класса.

В С++23 можно явно указать имя параметра вместо неявного this для объекта, к которому применяется метод. Такой способ позволяет окончательно избавиться от обычных указателей и работать только со ссылками, а также использовать более понятный способ указания типа для this.

struct Point
{
  double x,y;
  Point& addto(this Point& self, const Point& other) { 
    // то же что и Point& addto(const Point& other) &;
    self.x+=other.x; // нельзя обращаться к полю как x или this->x
    self.y+=other.y;
    return self; // вместо странного *this
  }
  Point add(this Point self, const Point& other) { // в self копия *this
    return self.addto(other);
  }
};
loading