2016-11-29 4 views
1

Baseクラスのベクトルを作成し、派生クラスを動的に割り当てるには、以下のコードを試しています。Base unique_ptrのベクトル

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

ここでは、派生クラスの割り当て中にコンパイルエラーが発生します。 Deriveのコードを作成すると、コードが正しく動作するように見えます。 remove_if

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

'unique_ptr.get() - >'への呼び出しはすべて、 'unique_ptr->'と置き換えることができます。例えば 'm_BaseObj [index] .get() - > item'は' m_BaseObj [index] - > item'、 'Obj.get() - > item'は' Obj-> item'などでなければなりません。 'std :: unique_ptr'は' operator-> 'をオーバーライドします。 –

+1

また、 'Base'に仮想デストラクタを追加することを忘れないでください。そうしないと、' unique_ptr'が 'Base'ポインタで' delete'を呼び出したときに派生クラスが正しく破壊されません。特定の例であまり重要ではありませんが、破棄を必要とするデータメンバーが派生クラスにある場合は重要です。 –

答えて

2

あなたの述語Base、ないDerivedへのポインタを受け入れる必要があります。あなたはその中でキャスティングをすることができます。

実際にはコンパイラのエラーはかなり明確です。

+0

が修正されました。早速のご返事ありがとうございます。 – neo

2

std::remove_ifは、要素タイプがstd::unique_ptr<Base>で、述語に渡す必要があります。しかし、あなたが提供した述語lambdaはconst std::unique_ptr<Derived>&引数を期待しています。これらは異なるタイプで、unique_ptr<Base>unique_ptr<Derived>に変換できません。

const std::unique_ptr<Base>&を引数としてラムダを修正しました。

+1

これについて考えると、 'std :: unique_ptr 'が 'std :: unique_ptr 'に変換できない理由が分かります。同じ 'std :: vector'に複数の派生クラスが格納されていればどうなるか考えてみましょう。代わりに 'std :: unique_ptr 'を渡すかもしれないので、' std :: remove_if() '述部は' std :: unique 'を受け入れることができませんでした。だから、 'std :: unique_ptr 'しか受け入れることができず、述語は 'Base'が本当に' Derived'か 'SomethingElse'かを判断するために他の手段を使わなければなりません。 –