2014-10-01 50 views
0
class Base 
{ 
    bool a; 
}; 

class Derived : public Base 
{ 
    bool b; 
}; 

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

所以在这个例子中,shared_ptr的原始指针将指向Base,NOT Derived的一个实例。我不明白。std :: shared_ptr的原始指针返回基地而不是派生的

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?我确定我错过了一些东西。有人可以向我解释为什么会发生这种情况吗?

+1

指针在这两种情况下指向“派生”实例。在这方面,共享指针与原始指针没有区别。 – 2014-10-01 10:48:05

+2

你如何确定它指向调试器?如果基类没有至少一个虚函数,则某些信息不会嵌入类中以确定其类型,并且调试器可能无法推断其派生类型。 – 2014-10-01 10:49:27

+0

@NeilKirk即使类是多态的,我使用的调试器也不能推导出类型。(但是,当然,如果'Base'不是多态的,调试器就不可能知道它实际上是一个Derived'。 – 2014-10-01 13:46:56

回答

2

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

+0

shared_ptr既不存储基数也不派生。它存储指针。 (1)这些指针指向什么,(2)指针的类型是什么,以及(3)在运行时执行哪些成员函数是三个不同的问题。 – 2014-10-01 11:00:13

+0

在这两种情况下,指针都存储一个指向“Base”的指针,它是“Derived”的子对象,它继续存在。在第二种情况下'Base'是多态的这一事实使得访问'Derived'变得更加容易和更自然,但是在两种情况下存储的和它指向的内容都是相同的。 – 2014-10-01 13:45:01

1

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

std::shared_ptr和原始 指针之间有一些差异。例如,在第一个示例中,将 std::shared_ptr<Base>替换为Base*,并通过指针手动删除 将导致未定义的行为; std::shared_ptr有避免这种情况的额外复杂性。 (但 并发症并非没有缺点,给Base 虚析构函数,因为它应该有,然后进行 析构函数Derived私人的,出于某种奇怪的原因, 和你的第一个例子将无法编译。)

相关问题