# std::shared_from_this Обсуждая особенности [`std::make_shared`](shared_ptr_constructor.md), я упомянул, что иногда крайне необходимо убедиться, что объекты вашего класса всегда создаются только в куче и управляются с помощью умного указателя. Вот сейчас будет еще один такой случай. Вы разрабатываете графический интерфейс и, как это было принято лет 20 назад, решили что все должно быть объектно-ориентированно и красиво. Компонентики. Виджеты. Всех мы будем по требованию создавать, управлять умными shared и weak указателями, чтоб не очень сильно задумываться о владении — очень стандартный подход, между прочим. Rust библиотеки для GUI, например, часто [критикуют](https://www.warp.dev/blog/why-is-building-a-ui-in-rust-so-hard) за чудовищную сложность именно из-за владений. И так у вас появились некоторые базовые типы: ```C++ enum class EventType { Clicked, Created, // и другие }; class Widget { public: virtual ~Widget() = default; }; class EventListener { public: // Уведомить Listener, что такой-то Widget породил некоторое событие void notify(EventType, std::weak_ptr event_source); }; ``` Хорошо. Дальше давайте заведем кнопку! Куда же без кнопки в хорошем UI?! ```C++ class Button: public Widget { public: Button(std::shared_ptr listener): listener_ {listener} { // (1) хотелось бы уведомить listener, что кнопка создана! listener_->notify(EventType::Created, this); // Это неправильно... } void click() { // (2) хотелось бы уведомить listerner, что на кнопочку нажали! listener_->notify(EventType::Clicked, this); // И это разумеется неправильно } private: std::shared_ptr listener_; }; ``` К нашему большому счастью, этот [код не компилируется](https://godbolt.org/z/v77aG9rhz) ``` :26:47: error: cannot convert 'Button*' to 'std::weak_ptr' 26 | listener_->notify(EventType::Created, this); // Это неправильно... | ^~~~ | | | Button* ``` Ах, ну да, типы разные... Опытного разработчика на C++ это, конечно, заставило бы задуматься. А вот неопытного... Он может просто выполнить «преобразование» типов! ```C++ Button(std::shared_ptr listener): listener_ {listener} { // (1) хотелось бы уведомить listener, что кнопка создана! listener_->notify(EventType::Created, std::shared_ptr