std :: shared_ptr的原始指针返回base而不是derived

时间:2014-10-01 10:42:55

标签: c++ shared-ptr

class Base
{
  bool a;
};

class Derived : public Base
{
  bool b;
};

void main()
{
  std::shared_ptr<Base> base(new Derived());
}

因此,在此示例中,shared_ptr的原始指针将指向Base的实例,NOT Derived。我不明白。

class Base
{
  virtual void foo() {}
  bool a;
};

class Derived : public Base
{
  virtual void foo() {}
  bool b;
};

void main()
{
  std::shared_ptr<Base> base(new Derived());
}

但是在这种情况下,shared_ptr的原始指针确实指向Derived?我确定我错过了什么。有人可以向我解释为什么会这样吗?

2 个答案:

答案 0 :(得分:2)

在第一个示例中,类没有虚拟表,因为没有虚函数。 这意味着,由于shared_ptr需要一个静态类型的Base,它将存储一个Base。 第二种情况也存储Base,但是存在虚拟表允许您看到对象的动态类型是Derived。

答案 1 :(得分:1)

首先,这里使用std::shared_ptr是一个红鲱鱼。在 在这种情况下,std::shared_ptr和原始指针都表现出来 完全相同的。在这两种情况下,表达式new Derived() 返回指向整个对象的Derived*。并在 两种情况,用它来初始化指向Base的指针,就是这样 原始指针或任何合理设计的智能指针 导致Derived*转换为Base*,指向 到Base中的Derived子对象。 Derived对象 但是,仍然存在,可以通过几种不同的方式访问 方式:通过虚拟功能,使用std::dynamic_cast if Base是多态的(至少有一个虚函数),by 使用std::static_cast,如果您100%确定指向 对象实际上是Derived,可能还有其他一些我 没有想到。在你的第一种情况下,只有最后一种是可能的, 因为在第一个中,Base不是多态的。在你们两个 但是,示例指针指向Base,即 较大的Derived

的子对象

std::shared_ptr与原始版本之间存在一些差异 指针。例如,在您的第一个示例中,替换 std::shared_ptr<Base> Base*std::shared_ptr并手动删除 通过指针将导致未定义的行为; Base有额外的复杂功能可以避免这种情况。 (但 并发症没有它们的缺点。给Derived 一个虚拟的析构函数,它应该有,然后制作 {{1}}私有的析构函数,出于任何奇怪的原因, 并且你的第一个例子不会编译。)