首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从派生类调用的复制构造函数

从派生类调用的复制构造函数
EN

Stack Overflow用户
提问于 2015-10-26 18:57:32
回答 1查看 169关注 0票数 0

有人能在这里解释一下输出吗?createTreap()工作得很好,而且r不是nullptr,但是createTreapPair()treapPair.first.display(); treapPair.second.display();之后离开了r == nullptr。为什么?这两者有什么区别呢?这里发生了什么事?

代码语言:javascript
运行
复制
#include <iostream>
#include <memory>

class BinaryTree {
public:
    class Node {
        int value;
        std::shared_ptr<Node> left = nullptr, right = nullptr, parent = nullptr;
        friend class BinaryTree;  friend class Treap;
    public:
        Node (int v) : value(v) {}
        virtual ~Node() = default;
        Node (const Node&);
    };
    BinaryTree() : root(nullptr) {}
    BinaryTree (const BinaryTree& other) : root(std::shared_ptr<Node>(new Node(*other.root))) {std::cout << "BinaryTree copy constructor called.\n";}
    void setRoot (const std::shared_ptr<Node>& node) {root = node;}
protected:
    std::shared_ptr<Node> root;
};

BinaryTree::Node::Node (const Node& other) : value(other.value) {
    std::cout << "Node copy constructor called, value = " << value << '\n';
    if (other.left) left = std::shared_ptr<Node>(new Node(*other.left));
    if (other.right) right = std::shared_ptr<Node>(new Node(*other.right));
}

class Treap : public BinaryTree {
public:
    class Node : public BinaryTree::Node {
        int priority;
        friend class Treap;
    public:
        Node (int value) : BinaryTree::Node(value), priority(std::rand() % 100) {}
        Node (const Node& other) : BinaryTree::Node(other), priority(other.priority) {}  // Treap::Node copy constructor.
    };
    void display() const {
        std::shared_ptr<Node> r = std::dynamic_pointer_cast<Node>(root);  // Casting from BinaryTree::Node to Treap::Node.
        std::cout << "r = " <<  r << '\n';
        if (root) std::cout << "Root exists and has value " << root->value << ".\n";
    }
};

Treap createTreap() {
    std::cout << "\n\ncreateTreap() called.\n";
    Treap treap;
    std::shared_ptr<Treap::Node> r = std::make_shared<Treap::Node>(4);
    treap.setRoot(r);
    return treap;
}

std::pair<Treap, Treap> createTreapPair() {
    std::cout << "\n\ncreateTreapPair() called.\n";
    Treap treap1, treap2;
    std::shared_ptr<Treap::Node> r = std::make_shared<Treap::Node>(11);
    treap1.setRoot(r);
    treap2.setRoot(r);
    return std::make_pair(treap1, treap2);
}

int main() {
    const Treap treap = createTreap();
    treap.display();  // Works fine, r != nullptr.

    const std::pair<Treap, Treap> treapPair = createTreapPair();
    treapPair.first.display();  // r is nullptr!
    treapPair.second.display();  // r is nullptr!

    std::cin.get();
}

如何修正上面的代码,使rtreapPair.first.display(); treapPair.second.display();之后不转到nullptr?rcreateTreap()createTreapPair()中都是std::make_shared<Treap::Node>类型,那么为什么r = std::dynamic_pointer_cast<Node>(root);Treap::display()中将r转换为nullptr呢?createTreapPair()

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-10-26 19:29:35

@IgorTandetnik已经在您的代码中指出了问题。

BinaryTree复制构造函数显式地分割Treap::Node,并创建根用户持有的BinaryTree::Node实例。当然,dynamic_cast<Treap::Node>(root)返回nullptr

解决这个问题的一种方法是创建一个virtual成员函数来克隆一个BinaryTree::Node,并在NodeBinaryTree的复制构造函数中使用它。

下面是您的代码的更新版本:

代码语言:javascript
运行
复制
class BinaryTree {
   public:
      class Node {
         int value;
         std::shared_ptr<Node> left = nullptr, right = nullptr, parent = nullptr;
         friend class BinaryTree;  friend class Treap;
         public:
         Node (int v) : value(v) {}
         virtual ~Node() = default;
         Node (const Node&);

         //////////////////////////////
         // New code
         //////////////////////////////
         virtual Node* clone() const = 0;

      };
      BinaryTree() : root(nullptr) {}
      BinaryTree (const BinaryTree& other) : root(nullptr)
      {
         //////////////////////////////
         // Updated code
         //////////////////////////////
         if ( other.root )
         {
            root = std::shared_ptr<Node>(other.root->clone());
         }

         std::cout << "BinaryTree copy constructor called.\n";
      }
      void setRoot (const std::shared_ptr<Node>& node) {root = node;}
   protected:
      std::shared_ptr<Node> root;
};

BinaryTree::Node::Node (const Node& other) : value(other.value) {
   std::cout << "Node copy constructor called, value = " << value << '\n';

   //////////////////////////////
   // Updated code
   //////////////////////////////
   if (other.left) left = std::shared_ptr<Node>(other.left->clone());
   if (other.right) right = std::shared_ptr<Node>(other.right->clone());
}

class Treap : public BinaryTree {
   public:
      class Node : public BinaryTree::Node {
         int priority;
         friend class Treap;
         public:
         Node (int value) : BinaryTree::Node(value), priority(std::rand() % 100) {}
         Node (const Node& other) : BinaryTree::Node(other), priority(other.priority) {}  // Treap::Node copy constructor.

         //////////////////////////////
         // New code
         //////////////////////////////
         virtual Node* clone() const
         {
            return new Node(*this);
         }
      };
      void display() const {
         std::shared_ptr<Node> r = std::dynamic_pointer_cast<Node>(root);  // Casting from BinaryTree::Node to Treap::Node.
         std::cout << "r = " <<  r.get() << '\n';
         if (root) std::cout << "Root exists and has value " << root->value << ".\n";
      }
};
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33353507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档