简体   繁体   English

从shared_ptr到weak_ptr多态性的转换

[英]Conversion from shared_ptr to weak_ptr polymorphism

I am having trouble getting around this one. 我在解决这一问题时遇到了麻烦。 Let's say I have this vector 假设我有这个向量

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

Car is an abstract class. 汽车是一个抽象类。 I want to be able to return weak pointers of different types so I do the following. 我希望能够返回不同类型的弱指针,因此我要执行以下操作。

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>();
    }

I get the following error though when I try to use the function with a class that inherits from Car. 但是,当我尝试将函数与从Car继承的类一起使用时,出现以下错误。 Error C2440 'initializing': cannot convert from 'std::shared_ptr<Car>' to 'std::weak_ptr<Saab>' There might not be a valid car when asked for it. Error C2440 'initializing': cannot convert from 'std::shared_ptr<Car>' to 'std::weak_ptr<Saab>'当询问它时,可能没有有效的汽车。 I tried using boost::optional but it does not handle polymorphism . 我尝试使用boost :: optional但它不能处理多态。 I might go with raw pointers if I can't get this to work. 如果我无法使用它,我可能会使用原始指针。

You can't construct directly your weak_ptr<Saab> from the shared_ptr<Car> because the template parameter Car must implicitly be convertible to Saab in order to work. 您不能直接从shared_ptr<Car>构造weak_ptr<Saab> ,因为模板参数Car必须隐式转换为Saab才能正常工作。

But you can first convert your shared_ptr<Car> to shared_ptr<Saab> at first then construct your weak_ptr afterward. 但是您可以先将您的shared_ptr<Car>转换为shared_ptr<Saab> ,然后再构造您的weak_ptr In my example below, I used the std::dynamic_pointer_cast to do it. 在下面的示例中,我使用了std::dynamic_pointer_cast来执行此操作。

Here is what I came up with : 这是我想出的:

#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();
    }

}

It prints out : 它输出:

Saab 萨博

Renault 雷诺

Coliru link : http://coliru.stacked-crooked.com/a/9dbb85b556b83597 Coliru链接: http ://coliru.stacked-crooked.com/a/9dbb85b556b83597

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM