用于存储类层次结构中的任何类的 c++ 类
Posted
技术标签:
【中文标题】用于存储类层次结构中的任何类的 c++ 类【英文标题】:c++ class for storing any class from class hierarchy 【发布时间】:2016-07-29 11:26:38 【问题描述】:假设我有类层次结构。 一种; B1、B2、B3-Bn 都派生自 A,还有一些 C 类派生自不同的 B。 我想要一个类“UnifiedStorage”来存储A派生类,它不应该被模板化,但它本身应该有std::shared_ptr并且有两个功能:
template <typename T>
setData(std::shared_ptr<T> data/* A's derived class */)
template <typename T>
std::weak_ptr<T> getData()
我发现唯一可能的实现是像 Keeper 一样创建 smth:
class UnifiedStorage
class Keeper
public:
virtual ~Keeper ()
;
template <typename DataType>
class SpecificKeeper : public Keeper
public:
SpecificKeeper (std::shared_ptr<DataType> data): data(data)
~SpecificKeeper() = default;
std::shared_ptr<DataType> data;
;
template <typename SpecificDataType>
void setData (std::shared_ptr <SpecificDataType> d)
keeper.reset( new SpecificKeeper <SpecificDataType> (d) );
template <typename RequestedDataType>
std::shared_ptr <RequestedDataType> getData ()
SpecificKeeper <RequestedDataType>* specificKeeper = dynamic_cast <SpecificKeeper <RequestedDataType> * > (keeper.data());
if (specificKeeper == nullptr)
return std::shared_ptr <RequestedDataType> ();
else
return specificKeeper->data;
private:
std::unique_ptr<Keeper> keeper;
但这种认识有很强的负面影响。我只能让 shared_ptr 输入我在 setData 中设置的类型。
例如,如果我调用了 setData<B>(std::shared_ptr<B>)
我不能 getData<A>
它返回 null,但如果我调用 setData<A>(std::shared_ptr<B>)
getData<A>
将返回正确的指针。
【问题讨论】:
你不能用:void setData(std::shared_ptr<A> ptr) m_data = ptr; template <typename T> std::weak_ptr<T> getData() return std::static_pointer_cast<T>(m_data);
,成为会员std::shared_ptr<A> m_data;
吗?
我有一个邪恶的:拥有std::function<void()>
并存储 throw *this
。不用于实际代码,仅用于完整性和下一个 IOCCC。
【参考方案1】:
您的问题归结为一个非常简单的事实。
在您的示例中,B1
派生自 A
。 B1
是 A
的子类。
但是,std::shared_ptr<B1>
不是std::shared_ptr<A>
的子类。 SpecificKeeper<B1>
也不是 SpecificKeeper<A>
的子类。这不是 C++ 的工作方式。因此你不能dynamic_cast
从一个到另一个。
解决方案是完全摆脱模板,只需将std::shared_ptr<A>
存储在keeper 类中,然后在检索时执行std::dynamic_pointer_cast
。
一个简短的例子应该清楚:
#include <memory>
#include <iostream>
class A public: virtual ~A() ;
class B : public A ;
class C : public A ;
int main()
std::shared_ptr<B> bnew B;
std::shared_ptr<A> a=b;
std::shared_ptr<C> c=std::dynamic_pointer_cast<C>(a);
std::cout << a.get() << std::endl; // Stored base pointer
std::cout << c.get() << std::endl; // This will be nullptr, conversion failed
所以,您的UnifiedStorage
只需要存储std::shared_ptr<A>
。它不需要模板类。
GetData()
将尝试将std::dynamic_pointer_cast
存储的指针指向请求的类型。如果std::dynamic_pointer_cast
成功,您就有了共享指针。如果没有,你会得到一个空的std::shared_ptr
。
【讨论】:
对不起,也许你也可以帮助我。如果我不仅要存储 A 派生类怎么办?如果没有像“任何类型”实现(通常基于 void*)这样的解决方案,我该如何解决这个问题以上是关于用于存储类层次结构中的任何类的 c++ 类的主要内容,如果未能解决你的问题,请参考以下文章