是否可以在初始化列表中向上转换共享指针对象引用?
我有两个具有匹配派生类的类层次结构。假设我有一个 Base
派生到 Foo
的类和一个 Bar
类(class)。然后我有一个单独的层次结构,带有 ProxyBase
类,然后(为了匹配其他层次结构)有 FooProxy
和 BarProxy
.
ProxyBase
类存储一个shared_ptr<Base>
.当 ProxyFoo
创建它需要一个 std::shared_ptr<Foo>&
, 当 ProxyBar
创建它需要一个 std::shared_ptr<Bar>&
.
我可以通过两种方式完成这项工作:
- 不要引用
std::shared_ptr<*>
对象。 - 使用
std::shared_ptr<Base>& obj
作为ProxyFoo
的输入和ProxyBar
构造函数。这需要在构造函数中进行向下转换(我想避免)(因为我想要Foo
和Bar
特定属性),而且它使契约(Contract)/API 比应有的更允许。
但我想知道这是否可以通过引用来完成。
我认为我知道问题是什么:当我删除引用时它起作用了,我认为那是因为“类型转换”了一个shared_ptr<X>
技术上不允许;它只能通过创建一个新的 shared_ptr
来“类型转换”派生/基类型的对象。当使用引用时,一个人试图实际转换一个 shared_ptr
反对另一个不允许的。这是正确的吗?
最初我认为这是其中一个案例 std::static_pointer_cast
会有所帮助,但如果我的假设是正确的,那也无济于事。
独立示例:
#include <memory>
class Base { };
class Foo : public Base
{
private:
int val_;
public:
Foo(int val) : val_(val) { }
};
class ProxyBase
{
protected:
std::shared_ptr<Base> obj_;
ProxyBase(std::shared_ptr<Base>& obj) : obj_(obj) { }
};
class FooProxy : public ProxyBase
{
public:
FooProxy(std::shared_ptr<Foo>& fobj) : ProxyBase(fobj) { }
};
int main()
{
auto f = std::make_shared<Foo>(42);
auto fp = std::make_shared<FooProxy>(f);
}
所以我的问题归结为:是否可以在不删除引用的情况下在上面的(当前非功能性)代码中执行我正在尝试执行的操作,同时保留 Foo
和 Bar
特定构造函数 FooProxy
和 BarProxy
?
最佳答案
A shared_ptr<Derived>
可以转换为shared_ptr<Base>
, 但它不是 shared_ptr<Base>
.
换句话说,这个编译:
std::shared_ptr<Derived> pd;
std::shared_ptr<Base> pb = pd;
但这不是:
std::shared_ptr<Base>& pb = pd;
但这确实如此,因为 const 引用可以绑定(bind)到临时对象,这将隐式执行转换:
std::shared_ptr<Base> const& pb = pd;
问题是您在构造函数中使用了非常量左值引用。您应该采用 const 左值引用或仅按值采用它们。
关于c++ - 在初始化列表中转换 shared_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57700321/