diff --git a/tree.cc b/tree.cc index 974e297..17ecd8c 100644 --- a/tree.cc +++ b/tree.cc @@ -27,8 +27,6 @@ class INode : public ILinkMixin { public: ~INode() override = default; virtual const std::string& name() const = 0; - // УБРАНО: const. Этот метод используется для получения указателя, - // который может участвовать в не-константных операциях. virtual NodePtr getSelf() = 0; }; @@ -92,7 +90,7 @@ public: if (!parentLink) return; parentLink->removeChild(this->getLink()); link_->setParent(nullptr); - downgradeLinkIfPossible(); + // downgradeLinkIfPossible() здесь не нужен, т.к. узел просто отсоединяется } LinkPtr getLink() override { @@ -101,13 +99,8 @@ public: } protected: - // УБРАНО: const. Возвращаем неконстантный указатель. virtual std::shared_ptr getShared() = 0; - - // УБРАНО: const. Соответствует базовому классу. - NodePtr getSelf() override { - return getShared(); - } + NodePtr getSelf() override { return getShared(); } private: void lazyInit() { @@ -115,47 +108,63 @@ private: link_ = std::make_shared(getSelf()); } } + + // ИСПРАВЛЕНО: Эта функция теперь корректно обновляет родителя void upgradeLinkIfNeeded() { if (!std::dynamic_pointer_cast(link_)) return; - auto oldParent = link_->getParent(); - link_ = std::make_shared(getSelf()); - link_->setParent(oldParent); + + // Создаем новую, улучшенную связь + auto newLink = std::make_shared(getSelf()); + + // Если был родитель, уведомляем его о замене + if (auto parentLink = link_->getParent()) { + parentLink->removeChild(link_); // Удаляем старую связь + parentLink->addChild(newLink); // Добавляем новую + } + + // Переносим родителя в новую связь и заменяем старую + newLink->setParent(link_->getParent()); + link_ = newLink; } + + // ИСПРАВЛЕНО: Эта функция теперь тоже корректно обновляет родителя void downgradeLinkIfPossible() { - if (link_->getChildren().empty()) { - auto oldParent = link_->getParent(); - link_ = std::make_shared(getSelf()); - link_->setParent(oldParent); + if (link_->getChildren().empty() && std::dynamic_pointer_cast(link_)) { + // Создаем новую, упрощенную связь + auto newLink = std::make_shared(getSelf()); + + // Если был родитель, уведомляем его о замене + if (auto parentLink = link_->getParent()) { + parentLink->removeChild(link_); // Удаляем старую связь + parentLink->addChild(newLink); // Добавляем новую + } + + // Переносим родителя в новую связь и заменяем старую + newLink->setParent(link_->getParent()); + link_ = newLink; } } + LinkPtr link_; }; // --- КОНКРЕТНЫЙ УЗЕЛ --- -// УБРАНО: final. Теперь от класса можно наследоваться. class SimpleNode : public LazyLinkMixin, - public std::enable_shared_from_this -{ + public std::enable_shared_from_this { public: static NodePtr create(std::string name) { - // Теперь эта структура может легально наследоваться от SimpleNode struct EnableMakeShared : public SimpleNode { EnableMakeShared(std::string n) : SimpleNode(std::move(n)) {} }; return std::make_shared(std::move(name)); } - const std::string& name() const override { return name_; } - protected: - // УБРАНО: const. Теперь возвращается неконстантный shared_ptr, как и ожидается. std::shared_ptr getShared() override { return shared_from_this(); } - private: - friend struct std::enable_shared_from_this; friend class LazyLinkMixin; explicit SimpleNode(std::string name) : name_(std::move(name)) {} std::string name_; @@ -186,11 +195,13 @@ int main() { auto subchild = SimpleNode::create("SubChild"); child1->linkChild(subchild); + std::cout << "Initial tree:\n"; printTree(root); std::cout << "\nUnlinking Child1...\n"; child1->unlinkParent(); + std::cout << "\nFinal tree:\n"; printTree(root); return 0;