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

Smart pointers vs dumb pointers: polymorphism behavior oddity

本文关键字:指针 智能 多态      更新时间:2023-10-16

我正在调试一些更大的代码中的问题,并意识到智能指针及其多态属性有些奇怪。通过简单示例可以最好地看到这一点:

#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 中定义的成员函数(请参阅第三个输出(?从某种意义上说,这是访问派生类型对象的基类成员的一个很好的技巧。然而,这对我来说仍然有点诡异......

谁能解释为什么这种行为可以用智能指针而不是常规指针?

std::make_shared总是创建一个全新的对象。 那是

sptr = make_shared<A>(b);

更像

A* p1 = new A(b);

而不是像

A* p2 = &b;

p1make_shared 的返回值根本不指向b

以下语句:

sptr = make_shared<A>(b);

基本同:

sptr = shared_ptr(new A(b));

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

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