智能指针与哑指针:多态行为奇怪

时间:2014-04-25 21:40:35

标签: c++ pointers c++11 polymorphism smart-pointers

我在一些更大的代码中调试了一个问题,并且发现了一些关于智能指针及其多态属性的奇怪之处。通过简单的例子可以看出这一点:

#include <iostream>
#include <memory>

using namespace std;

class A {
public:
  virtual void who() {cout << "I am class A" << endl; };
}; 

class B : public A{
public:
  void who() {cout << "I am class B" << endl; };
}; 

int main(int argc, char *argv[])
{
  B b;  
  A * aptr = &b;
  aptr->who(); //Output: I am class B

  B * bptr = &b;
  bptr->who(); //Output: I am class B

  shared_ptr<A> sptr;
  sptr = make_shared<A>(b);
  sptr->who(); //Output: I am class A

  sptr = make_shared<B>(b);
  sptr->who(); //Output: I am class B

  return 0;
}

前两个输出对我来说很有意义,但是当我初始化的唯一对象是B类时,为什么我可以访问A中定义的成员函数(参见第三个输出)?从某种意义上说,这是一个很好的技巧,可以访问派生类型对象的基类成员。然而,这对我来说仍然有点怪异......

有人能解释为什么智能指针可以实现这种行为,而不是常规指针吗?

3 个答案:

答案 0 :(得分:11)

std::make_shared始终会创建一个全新的对象。也就是说,

sptr = make_shared<A>(b);

更像是

A* p1 = new A(b);

而不喜欢

A* p2 = &b;

p1并且make_shared的返回值根本不指向b

答案 1 :(得分:4)

以下声明:

sptr = make_shared<A>(b);

基本上与:

相同
sptr = shared_ptr(new A(b));

您正在使用B的复制构造函数创建一个新的A对象,而不是从指向A的指针创建shared_ptr。

答案 2 :(得分:4)

make_shared<A>(b)使用b构造类型为A的对象,并指向新构造的对象。这会对B对象进行切片,因此shared_ptr真正指向A