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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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 11:29:35

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

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

复制
相关文章
复制构造函数
生成一个对象的副本有两种途径——第一种途径是建立一个新的对象,然后将一个已有对象的数据成员值取出来,赋值给新的对象。这样做虽然可行 但是实在是太麻烦了。而接下来,向大家介绍 复制构造函数 ——它的作用就是用一个已有的对象,来执行一个新的对象的构造。
小飞侠xp
2022/03/23
8480
复制控制---复制构造函数
复制构造函数 只有单个形参,而且该参数是对本类类型对象的引用。 主要用于: 1 根据另一个同类型的对象显示或隐式的初始化一个对象 string a = "abc"; //调用复制构造函数将a初始化为abc string aa = string(); //调用string()的构造函数,创建一个新的对象,再调用 复制构造函数初始化aa string aa(5,"c"); //直接初始化 2 复制一个对象,将它作为实参传给一个函数 3 从函数返回时复制一个对象 AA function(AA& a){ ...
用户1154259
2018/01/17
1.2K0
复制控制---复制构造函数
Java复制构造函数
----------------------------------------------------------------------------------
用户7886150
2020/12/15
9640
拷贝(复制)构造函数
如果类的设计者不写复制构造函数,编译器就会自动生成复制构造函数。大多数情况下,其作用是实现从源对象到目标对象逐个字节的复制,即使得目标对象的每个成员变量都变得和源对象相等。编译器自动生成的复制构造函数称为“默认复制构造函数”。
用户7272142
2023/10/16
2090
派生类的构造过程
1、先基类、后对象、再子类 多继承,初始化顺序跟基类的声明顺序有关,从左到右。 对象 ,与声明类的顺序有关,从上到下。
我与梦想有个约会
2023/10/20
1440
派生类的构造过程
【C++】构造函数调用规则 ( 默认构造函数 | 默认无参构造函数 | 默认拷贝构造函数 | 构造函数调用规则说明 )
如果 C++ 类中 没有定义构造函数 , C++ 编译器会自动为该类提供一个 " 默认的无参构造函数 " , 函数体为空 , 不做任何操作 ;
韩曙亮
2023/10/15
1.3K0
【C++】构造函数调用规则 ( 默认构造函数 | 默认无参构造函数 | 默认拷贝构造函数 | 构造函数调用规则说明 )
C++ 复制控制之复制构造函数
C++类用三个特殊的成员函数:复制构造函数、赋值操作符和析构函数 来决定类对象之间的初始化或赋值时发生什么。所谓的“复制控制”即通过这三个成员函数控制对象复制的过程。本篇文章将介绍复制构造函数。
Tencent JCoder
2022/05/06
7910
虚函数中构造函数的调用顺序
1 /*曾经有段时间一直被构造函数中的虚函数所困扰,现在通过自己重新学习了一遍,标注一下容易忘记的知识*/ 2 #include<iostream> 3 using namespace std; 4 class Base0 5 { 6 public: 7 Base0(int var):var0(var) 8 { 9 cout<<"Construct base0"<<endl; 10 } ; 11 int var0; 12 void fun()
Gxjun
2018/03/22
3.5K0
虚函数中构造函数的调用顺序
c++学习笔记4,调用派生类的顺序构造和析构函数(一个)
能够看到,在创建派生类的对象的时候,首先调用的是基类中的构造函数,然后才是调用派生类自己的构造函数。
全栈程序员站长
2022/07/05
7150
c++学习笔记4,调用派生类的顺序构造和析构函数(一个)
java构造函数调用另一个构造函数_java中的构造函数
* 构造方法是专门用来创建对象的方法,当我们通过关键字new来创建对象时,其实就是在调用构造方法
用户7886150
2021/04/29
4.5K0
Java构造函数调用顺序问题
今天对Java的构造函数调用顺序进行研究,使用的是与C++类似的方法,即不对源码进行研究,而是直接通过打印代码对构造函数的调用顺序进行研究。
用户7886150
2021/04/20
1.1K0
析构函数-复制构造函数-赋值操作符重载-默认构造函数<代码解析>
通过下面primer中的一道习题,可以更深刻的了解,析构函数,复制构造函数,赋值操作符重载,默认构造函数的使用。 但是我的结果与primer习题解答里面的并不相同,可能是编译器不同的原因导致。 // test1107.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <iostream> #include <vector> using namespace std; struct Exam{ Exam(){ cout<<"Exam()"<<e
用户1154259
2018/01/17
9230
析构函数-复制构造函数-赋值操作符重载-默认构造函数<代码解析>
禁止在构造函数里调用虚函数
在构造函数中调用虚函数会导致程序出现莫名其妙的行为,这主要是对象还没有完全构造完成。下面我们先来看一段代码:
喵叔
2020/09/08
1.6K0
【C++】构造函数意义 ( 构造函数显式调用与隐式调用 | 构造函数替代方案 - 初始化函数 | 初始化函数缺陷 | 默认构造函数 )
C++ 提供的 构造函数 和 析构函数 作为 类实例对象的 初始化 和 销毁 方案 ;
韩曙亮
2023/10/15
8780
【C++】构造函数意义 ( 构造函数显式调用与隐式调用 | 构造函数替代方案 - 初始化函数 | 初始化函数缺陷 | 默认构造函数 )
Java构造函数调用顺序问题
今天对Java的构造函数调用顺序进行研究,使用的是与C++类似的方法,即不对源码进行研究,而是直接通过打印代码对构造函数的调用顺序进行研究。
全栈程序员站长
2022/06/28
7290
【Kotlin】Kotlin 构造函数 ( 主构造函数 | 主构造函数声明属性 | init 初始化代码块 | 次构造函数 | 构造函数委托 | 调用构造函数创建实例对象 )
1 . 构造函数个数 : Kotlin 类定义时需要指定主构造函数 , 还可以指定 0 ~ 多个次构造函数 ;
韩曙亮
2023/03/27
4.2K0
【C++】This指针和复制构造函数
在声明一个类的时候,是没有分配存储空间的,只有在真正定义一个对象的时候,程序才会为这个对象分配相应的存储空间。 如果定义了多个对象,这些对象都有自己的存储空间,但是这些对象都是用相同的成员方法的。
谙忆
2021/01/21
8430
构造函数调用子类的方法,写过吗?
这段示例代码,类Derive派生于Base,Base的构造函数与虚构函数均调用虚函数GetValue(),根据C++多态特性,应该是要调用Derive的GetValue()返回2,真的是这样吗?让我们看下最终的输出。
gaigai
2021/04/13
1.4K0
构造函数调用子类的方法,写过吗?
JavaScript 的 this 小结纯粹的函数调用作为对象方法的调用作为构造函数调用apply 调用
函数的不同使用场合,this有不同的值。 总的来说,this就是函数运行时所在的环境对象。 下面分情况,详细讨论
JavaEdge
2018/08/02
2.7K0
JavaScript 的 this 小结纯粹的函数调用作为对象方法的调用作为构造函数调用apply 调用
【说站】javascript new调用构造函数
以上就是JavaScript new调用构造函数的方法,希望对大家有所帮助。更多Javascript学习指路:Javascript
很酷的站长
2022/11/24
7630
【说站】javascript new调用构造函数

相似问题

如何从派生类复制构造函数调用基类复制构造函数?

20

从派生类调用构造函数

25

从复制构造函数调用构造函数

23

从派生类构造函数调用基类构造函数

44

从派生类构造函数调用基类构造函数

53
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文