C++ - unique_ptr 的 Cast/Change-type
C++ - Cast/Change-type of an unique_ptr
编辑:谢谢,一如既往的帮助:)
我找不到这个问题的解决方案,我有一个 unique_ptr 到一个基 class,它有一个派生 class 的数据,我想设置它是派生 class 的类型,因此我可以访问派生成员。请参阅此代码:
#include <memory>
#include <iostream>
class Base
{
public:
int v1 = 0xAAAAAAAA;
};
class Derived : public Base
{
public:
int v2 = 0xBBBBBBBB;
};
int main()
{
std::unique_ptr<Base> b1(new Derived); //How to access b1->v2 ?
std::unique_ptr<Base> b2(new Base);
std::getchar();
return 0;
}
b1的类型是Base,但是它的数据包含了Derived的数据。
参见:
很难得到吗?我考虑过操纵内存字节,比如说 [b1+4](伪想法)并访问它,但我考虑复杂的对象,因为我正在为游戏做一个实体系统,我不能这样做:(
谢谢!
正如 Sneftel 所建议的,您可以简单地转换包含在 unique_ptr
中的指针以访问其他方法。
static_cast<Derived*>(b1.get())->v2
请记住,这看起来很奇怪。通常,如果您可以访问给定类型的指针,则不应强制转换它以希望它具有您想要的类型。相反,如果您需要访问给定 subclass 的方法,您应该要求您的输入是该 subclass 的指针。在智能指针中存储基数 classes 通常是为了利用多态性,除此之外别无其他。
如果您不使用多态性,请考虑在模板中使用带有派生 class 的 unique_ptr
,然后在只有基 class 接口时将其向下转换为基指针需要。
另一种选择是将同一个指针存储在两个位置:一个作为 Base
,一个作为 Derived
- 请记住,您只能使用一个智能指针其中之一!
您的选择是:
1) Cast C-like 指针(推荐)
std::unique_ptr<Base> b2(new Base);
Derived * p = static_cast<Derived *>(b2.get());
2) 实施您自己的 static_unique_ptr_cast
,其中删除 b1
并创建新的 std::unique_ptr
:
template<typename Derived, typename Base, typename Del>
std::unique_ptr<Derived, Del>
static_unique_ptr_cast(std::unique_ptr<Base, Del> && p)
{
auto d = static_cast<Derived *>(p.release());
return std::unique_ptr<Derived, Del>(d, std::move(p.get_deleter()));
}
该函数采用右值引用以确保您不会从左值窃取资源。用法:
std::unique_ptr<Base> b1(new Derived);
std::unique_ptr<Derived> p = static_unique_ptr_cast<Derived>(std::move(b1));
注意:如果您认为需要使用 2),我会认为您的设计存在缺陷。由于某种原因演员表不在 STL 中。
编辑: static_unique_ptr_cast
现在保留删除器。
如果使用 shared_ptr
,则可以使用共享指针转换
std::static_pointer_cast<Derived>(b1)->v2;
您的整个问题在 cppreference 网站上都有解释:http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast
我会注意其他建议,标准确实考虑到了这个问题并实施了一个干净的解决方案。
我不确定我是否理解您正在尝试做的事情,但它看起来更像是一个设计问题。
如果您有指向 Base 的指针,则实际对象可能是 Base 或派生对象 class(不一定是派生对象)。也就是说,如果不做一些危险的假设,就不能将其转换为 Derived。
class B{public:virtual ~B(){}};
class D : public B{};
class DD : public B{};
int main()
{
std::unique_ptr< B > pb( new D );
D* pd = dynamic_cast< D* >( pb.get() );
DD* pdd = dynamic_cast< DD* >( pb.get() ); // null
return 0;
}
编辑:谢谢,一如既往的帮助:)
我找不到这个问题的解决方案,我有一个 unique_ptr 到一个基 class,它有一个派生 class 的数据,我想设置它是派生 class 的类型,因此我可以访问派生成员。请参阅此代码:
#include <memory>
#include <iostream>
class Base
{
public:
int v1 = 0xAAAAAAAA;
};
class Derived : public Base
{
public:
int v2 = 0xBBBBBBBB;
};
int main()
{
std::unique_ptr<Base> b1(new Derived); //How to access b1->v2 ?
std::unique_ptr<Base> b2(new Base);
std::getchar();
return 0;
}
b1的类型是Base,但是它的数据包含了Derived的数据。 参见:
很难得到吗?我考虑过操纵内存字节,比如说 [b1+4](伪想法)并访问它,但我考虑复杂的对象,因为我正在为游戏做一个实体系统,我不能这样做:(
谢谢!
正如 Sneftel 所建议的,您可以简单地转换包含在 unique_ptr
中的指针以访问其他方法。
static_cast<Derived*>(b1.get())->v2
请记住,这看起来很奇怪。通常,如果您可以访问给定类型的指针,则不应强制转换它以希望它具有您想要的类型。相反,如果您需要访问给定 subclass 的方法,您应该要求您的输入是该 subclass 的指针。在智能指针中存储基数 classes 通常是为了利用多态性,除此之外别无其他。
如果您不使用多态性,请考虑在模板中使用带有派生 class 的 unique_ptr
,然后在只有基 class 接口时将其向下转换为基指针需要。
另一种选择是将同一个指针存储在两个位置:一个作为 Base
,一个作为 Derived
- 请记住,您只能使用一个智能指针其中之一!
您的选择是:
1) Cast C-like 指针(推荐)
std::unique_ptr<Base> b2(new Base);
Derived * p = static_cast<Derived *>(b2.get());
2) 实施您自己的 static_unique_ptr_cast
,其中删除 b1
并创建新的 std::unique_ptr
:
template<typename Derived, typename Base, typename Del>
std::unique_ptr<Derived, Del>
static_unique_ptr_cast(std::unique_ptr<Base, Del> && p)
{
auto d = static_cast<Derived *>(p.release());
return std::unique_ptr<Derived, Del>(d, std::move(p.get_deleter()));
}
该函数采用右值引用以确保您不会从左值窃取资源。用法:
std::unique_ptr<Base> b1(new Derived);
std::unique_ptr<Derived> p = static_unique_ptr_cast<Derived>(std::move(b1));
注意:如果您认为需要使用 2),我会认为您的设计存在缺陷。由于某种原因演员表不在 STL 中。
编辑: static_unique_ptr_cast
现在保留删除器。
如果使用 shared_ptr
,则可以使用共享指针转换std::static_pointer_cast<Derived>(b1)->v2;
您的整个问题在 cppreference 网站上都有解释:http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast
我会注意其他建议,标准确实考虑到了这个问题并实施了一个干净的解决方案。
我不确定我是否理解您正在尝试做的事情,但它看起来更像是一个设计问题。
如果您有指向 Base 的指针,则实际对象可能是 Base 或派生对象 class(不一定是派生对象)。也就是说,如果不做一些危险的假设,就不能将其转换为 Derived。
class B{public:virtual ~B(){}};
class D : public B{};
class DD : public B{};
int main()
{
std::unique_ptr< B > pb( new D );
D* pd = dynamic_cast< D* >( pb.get() );
DD* pdd = dynamic_cast< DD* >( pb.get() ); // null
return 0;
}