在初始化列表中转换 shared_ptr
Casting shared_ptr in initializer list
是否可以向上转换初始化列表中的共享指针对象引用?
我有两个 class 层次结构,它们具有匹配的派生 classes。假设我有一个 Base
class 派生到 Foo
和 Bar
class。然后我有一个单独的层次结构 ProxyBase
class 然后(为了匹配其他层次结构)有 FooProxy
和 BarProxy
.
ProxyBase
class 存储一个 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 比它更允许应该是。
但我想知道这是否可以通过引用来完成。
我 认为 我知道问题出在哪里:当我删除引用时它起作用了,我认为那是因为 "casting" a shared_ptr<X>
在技术上是不允许;它只能通过创建 derived/base 类型的新 shared_ptr
对象来 "casted"。当使用引用时,人们试图将一个 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
?
的特定构造函数
一个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 引用可以绑定到临时对象,这将隐式执行转换:
std::shared_ptr<Base> const& pb = pd;
问题是您在构造函数中使用了非常量左值引用。您应该采用 const 左值引用或仅按值采用它们。
是否可以向上转换初始化列表中的共享指针对象引用?
我有两个 class 层次结构,它们具有匹配的派生 classes。假设我有一个 Base
class 派生到 Foo
和 Bar
class。然后我有一个单独的层次结构 ProxyBase
class 然后(为了匹配其他层次结构)有 FooProxy
和 BarProxy
.
ProxyBase
class 存储一个 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 比它更允许应该是。
但我想知道这是否可以通过引用来完成。
我 认为 我知道问题出在哪里:当我删除引用时它起作用了,我认为那是因为 "casting" a shared_ptr<X>
在技术上是不允许;它只能通过创建 derived/base 类型的新 shared_ptr
对象来 "casted"。当使用引用时,人们试图将一个 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
?
一个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 引用可以绑定到临时对象,这将隐式执行转换:
std::shared_ptr<Base> const& pb = pd;
问题是您在构造函数中使用了非常量左值引用。您应该采用 const 左值引用或仅按值采用它们。