我在一些更大的代码中调试了一个问题,并且发现了一些关于智能指针及其多态属性的奇怪之处。通过简单的例子可以看出这一点:
#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中定义的成员函数(参见第三个输出)?从某种意义上说,这是一个很好的技巧,可以访问派生类型对象的基类成员。然而,这对我来说仍然有点怪异......
有人能解释为什么智能指针可以实现这种行为,而不是常规指针吗?
答案 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
。