2016-11-29 2 views
1

Ich versuche unten Code zum Erstellen eines Vektors der Basisklasse und dynamische Zuordnung der abgeleiteten Klasse.Vektor der Base unique_ptr zum Ableiten

#include <memory> 
#include <vector> 
#include <iostream> 
#include <algorithm> 

class Base { 

public: 
    Base(int value) : item(value) {} 
    int item; 
}; 

class Derived : public Base { 

public: 
    Derived() : Base(0) {} 
}; 

class Fac { 
public: 
    int count; 
    std::vector<std::unique_ptr<Base>> m_BaseObj; 

    void add(int data) { 
    count++; 
    m_BaseObj.push_back(std::unique_ptr<Base>(new Derived())); 
    int index = (m_BaseObj.size() - 1); 
    std::cout << "Index=" << index << std::endl; 
    m_BaseObj[index].get()->item = data; 
    } 

    void display() { 
    for (auto &Obj : m_BaseObj) { 
     std::cout << Obj.get()->item << " "; 
    } 
    std::cout << std::endl; 
    } 
    void deleteList() { 
    int it; 
    std::cout << "Enter item to delete:"; 
    std::cin >> it; 
    int index = 0; 
    m_BaseObj.erase(std::remove_if(m_BaseObj.begin(), m_BaseObj.end(), 
            [it](const std::unique_ptr<Derived> &e) { 
            return it == e->item; 
            }), 
        m_BaseObj.end()); 
    } 
}; 

int main() { 
    Fac obj; 
    int ch; 
    obj.count = 0; 
    while (1) { 
    std::cout << "1. Add 2. Remove 3. Display\n"; 
    std::cin >> ch; 
    switch (ch) { 
    case 1: 
     int data; 
     std::cout << "Data: "; 
     std::cin >> data; 
     obj.add(data); 
     obj.display(); 
     break; 
    case 2: 
     obj.deleteList(); 
     obj.display(); 
     break; 
    case 3: 
     obj.display(); 
     break; 
    default: 
     std::cout << "Invalid choice\n"; 
     exit(0); 
    } 
    } 
} 

Hier ist der Kompilierfehler beim Zuweisen für die Klasse abzuleiten. Wenn ich für Derivat erstellen, scheint der Code korrekt zu funktionieren.

In file included from /usr/include/c++/4.8/algorithm:62:0, 
       from vector.cpp:4: 
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of â_FIter std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = __gnu_cxx::__normal_iterator<std::unique_ptr<Base>*, std::vector<std::unique_ptr<Base> > >; _Predicate = Fac::deleteList()::__lambda0]â: 
vector.cpp:53:64: required from here 
/usr/include/c++/4.8/bits/stl_algo.h:1150:33: error: no match for call to â(Fac::deleteList()::__lambda0) (std::unique_ptr<Base>&)â 
     if(!bool(__pred(*__first))) 
           ^
vector.cpp:52:48: note: candidate is: 
     m_BaseObj.begin(), m_BaseObj.end(), [it](const std::unique_ptr<Derived>& e) 
               ^
vector.cpp:52:83: note: Fac::deleteList()::__lambda0 
     m_BaseObj.begin(), m_BaseObj.end(), [it](const std::unique_ptr<Derived>& e) 
+1

Als Randnotiz können alle Aufrufe von 'unique_ptr.get() ->' durch 'unique_ptr->' ersetzt werden, zB: 'm_BaseObj [index] .get() -> item' sollte' sein m_BaseObj [index] -> item', 'Obj.get() -> item' sollte' Obj-> item' usw. sein. 'std :: unique_ptr' überschreibt' operator-> 'für diesen Zweck. –

+1

Vergessen Sie auch nicht, einen virtuellen Destruktor zu "Base" hinzuzufügen, sonst werden abgeleitete Klassen nicht korrekt zerstört, wenn 'unique_ptr'' delete' auf seinem 'Base *' -Zeiger aufruft. Nicht so wichtig in Ihrem speziellen Beispiel, aber es ist wichtig, wenn eine abgeleitete Klasse Datenelemente hat, die eine Zerstörung erfordern. –

Antwort

2

Ihr Prädikat remove_if muss Zeiger auf Base akzeptieren, nicht Derived. Sie können das Casting darin durchführen.

Compiler-Fehler ist eigentlich ziemlich klar.

+0

Korrigiert. Danke für die schnelle Antwort. – neo

2

std::remove_if muss den Elementtyp std::unique_ptr<Base> an sein Prädikat übergeben. Das von Ihnen angegebene Prädikat Lambda erwartet jedoch ein const std::unique_ptr<Derived>& Argument. Dies sind verschiedene Typen und unique_ptr<Base> ist nicht in unique_ptr<Derived> umwandelbar.

Fixieren Sie Ihr Lambda, um const std::unique_ptr<Base>& als Argument zu nehmen.

+1

Und wenn Sie darüber nachdenken, werden Sie sehen, warum 'std :: unique_ptr ' nicht in 'std :: unique_ptr ' konvertiert werden kann. Denken Sie darüber nach, was passieren würde, wenn Sie mehrere abgeleitete Klassen im selben 'std :: vector' hätten. Das Prädikat 'std :: remove_if()' konnte kein 'std :: unique ' akzeptieren, weil es stattdessen an 'std :: unique_ptr ' übergeben werden könnte. Es kann also nur ein 'std :: unique_ptr ' akzeptieren, und dann muss das Prädikat andere Mittel verwenden, um zu bestimmen, ob die 'Basis' wirklich eine 'Abgeleitete' oder eine 'EtwasEsel' ist. –

Verwandte Themen