【发布时间】:2021-04-12 23:17:16
【问题描述】:
我无法理解shared_ptr 的转换。
This thread 很好地解释了使用普通指针的行为,结果非常直观 - 正是我所期望的。但是,shared_ptr 显示不同的结果 - 我创建了 3 个类,一个 Base 和两个 Derived,并使用 ***_ptr_cast 玩了一下:
#include <iostream>
#include <memory>
using namespace std;
struct Base
{
virtual void f() { cout << "Base" << endl; }
string name = "Base";
};
struct FirstDerived : public Base
{
void f() override { cout << "FirstDerived" << endl; }
void firstDerived() { cout << "FirstDerived only method" << endl; }
string name = "FirstDerived";
};
struct SecondDerived : public Base
{
void f() override { cout << "SecondDerived" << endl; }
void secondDerived() { cout << "SecondDerived only method" << endl; }
string name = "SecondDerived";
};
int main()
{
FirstDerived fd;
std::shared_ptr<Base> bf = make_shared<Base>(fd);
std::shared_ptr<FirstDerived> fdp = std::static_pointer_cast<FirstDerived>(bf);
if (fdp)
{
fdp.get()->f();
fdp.get()->firstDerived();
//cout << fdp.get()->name;
}
FirstDerived sd;
std::shared_ptr<Base> bs = make_shared<Base>(sd);
std::shared_ptr<SecondDerived> sdp = std::static_pointer_cast<SecondDerived>(bs);
if (sdp)
{
sdp.get()->f();
sdp.get()->secondDerived();
//cout << sdp.get()->name;
}
return 0;
}
这个程序的输出显示(有趣的是cout << fdp.get()->name; 是不可能的,因为它会出现段错误):
Base
FirstDerived only method
Base
SecondDerived only method
进一步研究后我得出结论,static_cast 可能是错误的演员,所以我与dynamic_cast 交换了他们。然而,即使我正在转换为正确的派生版本,动态版本也永远不会返回有效值。
期望的结果是,只有当初始对象的类型与下一步要转换的对象的类型相同时,才会有结果。否则它应该为空。
我应该如何正确执行此操作,是否有我正在搜索的内容的演员表?
【问题讨论】:
-
“即使我正在转换为正确的派生版本” - 是的。如果不是,则您没有指向正确派生版本的对象。您在测试中的先决条件是错误的。重新评估您的断言。
-
StoryTeller 是对的。问题似乎是您假设
make_shared<Base>(fd);复制了fd。它没有。它使用可以采用fd的Base构造函数创建一个Base对象。那恰好是Base::Base(base const&),复制构造函数,因为fd有一个Base子对象。 -
我明白了,谢谢。那么以目前的状态绝对没有办法实现我想要的输出?
-
其实有一个很简单的方法:用
make_shared<FirstDerived>(fd)复制整个fd。请记住,您的演员正在处理共享对象*bf,而不是用于创建*bf的 ctor 参数。 -
@Nestroy 我更新了我的答案。
标签: c++ inheritance casting shared-ptr