View in Telegram
​​Виртуальная дружественная функция #новичкам Вчера мы поговорили о том, что таких функций не бывает, но очень хочется получить альтернативу. Хочется изменять работу функции в зависимости от динамического типа, который в нее передается. Ну и на самом деле ничего сложного здесь нет. Можно ведь сделать полиморфный метод, который будет вызываться в этой функции. И вот его поведение мы можем изменять примерно как нашей душеньке захочется. Рассмотрим банальный пример - сериализация объекта в поток. Обычно для такой задачи используют дружественный оператор <<. Но вот хотелось бы сериализовать в зависимости от динамического типа. Фигня вопрос.
struct Person {
  Person(const std::string &first_name,
       const std::string &last_name) : first_name_{first_name},
                      last_name_{last_name} {}
  
  friend std::ostream& operator<<(std::ostream& o, const Person& b) {
    return o << b.to_str();
  }
protected:
  virtual std::string to_str() const{
    return first_name_ + " " + last_name_;
  }
private:
  std::string first_name_;
  std::string last_name_;
};

struct TaxPayer : Person {
  TaxPayer(const std::string first_name,
       const std::string last_name,
       const std::string itn) : Person{first_name, last_name}, itn_{itn} {}
protected:
  virtual std::string to_str() const{
    return Person::to_str() + " " + itn_;
  }
private:
  std::string itn_;
};

int main() {
  auto prs1 = std::make_unique<Person>("Ter", "Minator");
  auto prs2 = std::make_unique<TaxPayer>("Ace", "Ventura", "0000");
  std::cout << *prs1 << std::endl;
  std::cout << *prs2 << std::endl;
}
// OUTPUT:
// Ter Minator
// Ace Ventura 0000
Есть у нас класс человека с его именем и фамилией. Есть класс налогоплательщика, который наследуется от человека и добавляет к полям ИНН. Допустим, мы хотим как-то выводить на консоль содержимое этих людей(в смысле поля; расчленением мы не занимаемся, не в Питере живем все-таки). Можно конечно в каждом классе определять свой оператор или выводить на консоль результат работы метода to_str, но это лишний апи и лишний код. Мы просто в базовом классе определяем другана и говорим, чтобы он вызывал виртуальный метод. И все. Да, это очень просто. Но подход скрытия деталей реализации за закрытым виртуальным методом используется, например в идиоме невиртуального интерфейса и еще невесть где. Поэтому о даже о таком приеме надо знать и применять его в подходящих ситуациях. Have a real friends. Stay cool. #cppcore
Love Center
Love Center
Find friends or serious relationships easily