2016-07-07 191 views
5

我無法繞過此問題。 比方說,我有這個載體將shared_ptr轉換爲weak_ptr多態性

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 :: optional,但它不處理多態性。如果我無法得到這個工作,我可能會使用原始指針。

+1

「shared_ptr」和「weak_ptr」指向的類型必須相同。我會在三個步驟中執行此操作:返回'weak_ptr ',然後將其轉換爲'shared_ptr ',然後轉換爲'T *'。 –

+0

感謝您快速回答@MarkRansom嗯。這是一個庫的用戶函數,所以我寧願不給可能使用它的開發者更多的工作。應該這樣說,我的壞。你會建議只使用原始指針,所以我可以返回一個?或者返回衍生的偶數, – miniconco

+0

你當然可以有一個函數執行所有三個步驟,但是將'weak_ptr'轉換爲'shared_ptr'的目的是在你使用它的同時保持對象存活;把'shared_ptr'放到臨時位置就會失敗。 –

回答

5

你不能直接在您的weak_ptr<Saab>shared_ptr<Car>構造,因爲模板參數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(); 
    } 

} 

它打印出:

薩博

雷諾

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

+0

哇!正是我在找什麼!先生,祝你有美好的一天。 – miniconco