从shared_ptr到weak_ptr多态性的转换

Conversion from shared_ptr to weak_ptr polymorphism

本文关键字:ptr 转换 多态性 shared weak      更新时间:2023-10-16

我很难解决这个问题。假设我有这个向量

std::vector<std::shared_ptr<Car>> cars; 

汽车是一个抽象类。我希望能够返回不同类型的弱指针,因此我执行以下操作。

template<typename T>
    std::weak_ptr<T> GetCar()
    {
        for (std::vector<std::shared_ptr<Car>>::iterator it = cars.begin(); it != cars.end(); ++it)
        {
            T* derived = dynamic_cast<T*>((*it).get());
            if (derived != nullptr)
            {
                std::weak_ptr<T> carPointer = *it;
                return carPointer;
            }
        }
        return std::weak_ptr<T>();
    }

但是,当我尝试将该函数与从 Car 继承的类一起使用时,我收到以下错误。 Error C2440 'initializing': cannot convert from 'std::shared_ptr<Car>' to 'std::weak_ptr<Saab>' 当被要求时,可能没有有效的汽车。我尝试使用boost::可选,但它不处理多态性。如果我不能让它工作,我可能会使用原始指针。

不能

直接从shared_ptr<Car>构造weak_ptr<Saab>,因为模板参数Car必须隐式转换为Saab才能工作。

但是您可以先将shared_ptr<Car>转换为shared_ptr<Saab>,然后再构建weak_ptr。在下面的示例中,我使用了std::dynamic_pointer_cast来执行此操作。

这是我想到的:

#include <iostream>
#include <vector>
#include <memory>
struct Car
{
    virtual void name() = 0;
};
struct Saab : Car
{
    virtual void name() { std::cout << "Saab" << std::endl; }   
};
struct Renault : Car
{
    virtual void name() { std::cout << "Renault" << std::endl; }   
};
template<typename T>
std::weak_ptr<T> GetCar(std::vector<std::shared_ptr<Car>> cars)
{
    for (std::vector<std::shared_ptr<Car>>::iterator it = cars.begin(); it != cars.end(); ++it)
    {
        auto derived = std::dynamic_pointer_cast<T>(*it);
        if (derived != nullptr)
        {
            std::weak_ptr<T> carPointer(derived);
            return carPointer;
        }
    }
    return std::weak_ptr<T>();
}
int main()
{
    std::vector<std::shared_ptr<Car>> cars;
    cars.push_back(std::make_shared<Saab>());
    cars.push_back(std::make_shared<Renault>());
    auto wp = GetCar<Saab>(cars);
    auto sp = wp.lock();
    if (sp)
    {
        sp->name();
    }
    auto wp2 = GetCar<Renault>(cars);
    auto sp2 = wp2.lock();
    if (sp2)
    {
        sp2->name();
    }
}

它打印出来:

萨博

雷诺

科里鲁链接 : http://coliru.stacked-crooked.com/a/9dbb85b556b83597