【问题标题】:Raw pointer of std::shared_ptr returns base instead of derivedstd::shared_ptr 的原始指针返回基而不是派生
【发布时间】:2014-10-01 10:42:54
【问题描述】:
class Base
{
  bool a;
};

class Derived : public Base
{
  bool b;
};

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

所以在本例中,shared_ptr 的原始指针将指向 Base 的一个实例,而不是 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?我确定我错过了一些东西。有人可以向我解释为什么会这样吗?

【问题讨论】:

  • 在这两种情况下,指针都指向Derived 实例。在这方面,共享指针与原始指针没有什么不同。
  • 调试器你如何确定它指向什么?如果基类没有至少一个虚函数,则类中没有嵌入某些信息来确定其类型,调试器可能无法推断其派生类型。
  • @NeilKirk 我使用的调试器经常无法推断出类型,即使类是多态的。 (当然,如果Base 不是多态的,调试器就没有机会知道它实际上是Derived。)
  • @JamesKanze VS 调试器通常可以从多态基础中分辨出来。
  • @NeilKirk 这不是我的经验。它只显示基类数据(通常为空,因为基类是一个接口)。我可以得到最派生类的 name,因为它被修改为 vtable 的名称,但仅此而已。)

标签: c++ shared-ptr


【解决方案1】:

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

【讨论】:

  • shared_ptr 既不存储基础也不存储派生。它存储指针。 (1) 这些指针指向的位置和 (2) 指针的类型以及 (3) 在运行时执行哪些成员函数是三个不同的问题。
  • 在这两种情况下,指针都存储了指向Base 的指针,它是Derived 的子对象,它继续存在。 Base 在第二种情况下是多态的,这一事实使得访问Derived 变得更加容易和自然,但是在两种情况下存储的内容和指向的内容都是相同的。
【解决方案2】:

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

std::shared_ptr 和 raw 之间存在一些差异 指针。例如,在您的第一个示例中,替换 std::shared_ptr&lt;Base&gt;Base* 并手动删除 通过指针会导致未定义的行为; std::shared_ptr 有额外的复杂性来避免这种情况。 (但 并发症并非没有缺点。给Base 一个虚拟的析构函数,它应该有,然后使 Derived private 的析构函数,无论出于什么奇怪的原因, 并且您的第一个示例无法编译。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-18
    相关资源
    最近更新 更多