2016-07-07 33 views
5

Ich habe Probleme, um diese zu bekommen. Lassen Sie uns sagen, ich habe dieses VektorUmwandlung von shared_ptr zu weak_ptr Polymorphismus

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

Car ist eine abstrakte Klasse. Ich möchte schwache Zeiger verschiedener Typen zurückgeben, also mache ich folgendes.

Ich bekomme den folgenden Fehler obwohl ich versuche, die Funktion mit einer Klasse zu verwenden, die von Auto erbt. Error C2440 'initializing': cannot convert from 'std::shared_ptr<Car>' to 'std::weak_ptr<Saab>' Es gibt möglicherweise kein gültiges Auto, wenn es darum gebeten wird. Ich habe versucht, boost :: optional, aber es behandelt nicht Polymorphie. Ich könnte mit rohen Zeigern gehen, wenn ich das nicht zur Arbeit bringen kann.

+1

Der Typ, auf den "shared_ptr" und "weak_ptr" zeigen, muss identisch sein. Ich würde das in drei Schritten tun: gebe ein 'weak_ptr ' zurück und konvertiere es in ein 'shared_ptr ', dann in ein 'T *'. –

+0

Danke für die schnelle Antwort @MarkRansom Mmm. Dies ist für eine Benutzerfunktion einer Bibliothek, so dass ich dem Entwickler, der es verwenden könnte, mehr Arbeit lieber nicht geben würde. Sollte gesagt haben, mein Schlechter. Würdest du empfehlen, nur mit rohen Zeigern zu arbeiten, damit ich einen zurückgeben kann? Oder zurückgegeben abgeleitet even, – miniconco

+0

Sie können sicherlich eine einzige Funktion haben, die alle drei Schritte ausführt, aber der Zweck der Umwandlung eines 'weak_ptr' in ein' shared_ptr' besteht darin, das Objekt am Leben zu erhalten, während Sie damit arbeiten; Setzen Sie das 'shared_ptr' in eine temporäre Niederlagen diesen Zweck. –

Antwort

5

können Sie nicht direkt Ihre weak_ptr<Saab> vom shared_ptr<Car> konstruieren, weil der Template-Parameter Car implizit Saab zu arbeiten, um konvertierbar sein muss.

Aber zuerst können Sie zuerst Ihre shared_ptr<Car> in shared_ptr<Saab> umwandeln und dann Ihre weak_ptr danach erstellen. In meinem Beispiel unten verwendete ich die std::dynamic_pointer_cast, um es zu tun. Hier

ist, was ich kam mit:

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

} 

Es druckt:

Saab

Renault

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

+0

Wow! Genau das, was ich gesucht habe! Einen schönen Tag noch, Sir. – miniconco