c++类,用于存储类层次结构中的任何类

c++ class for storing any class from class hierarchy

本文关键字:任何类 层次结构 存储 用于 c++      更新时间:2023-10-16

让我们假设我有类层次结构。A.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>将返回正确的指针。

您的问题归结为一个非常简单的事实。

在您的示例中,B1源自A。CCD_ 7是CCD_。

然而,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> 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>。它不需要模板类。

CCD_ 18将尝试将所存储的指向所请求类型的指针CCD_。如果std::dynamic_pointer_cast成功,您就拥有了共享指针。如果不是,则会得到一个空std::shared_ptr