让我假设我有类层次结构。 一个; B1,B2,B3-Bn全部来自A,而一些C类来自不同的B&。 我想要一个班级" UnifiedStorage"存储一个派生类,它不应该是模板化的,但它本身应该有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中设置的类型。
例如,如果a已调用setData<B>(std::shared_ptr<B>)
我无法getData<A>
它返回null,但如果我将调用setData<A>(std::shared_ptr<B>)
getData<A>
将返回正确的指针。< / p>
答案 0 :(得分:2)
你的问题归结为一个非常简单的事实。
在您的示例中B1
派生自A
。 B1
是A
的子类。
但是,std::shared_ptr<B1>
不是std::shared_ptr<A>
的子类。 SpecificKeeper<B1>
也不是SpecificKeeper<A>
的子类。这不是C ++的工作原理。因此,你不能dynamic_cast
从一个到另一个。
解决方案是完全摆脱模板,只需将std::shared_ptr<A>
存储在守护者类中,然后在检索时执行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> b{new 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
。