2008-11-19 125 views
9

我有一個稱爲形從中既Circle和Rectangle派生的抽象基類,但是當我執行在VS 2005下面的代碼我得到的錯誤調試斷言失敗。同時,我還沒有重載==操作符在任何類矢量迭代器不dereferencable

表達:矢量迭代器不dereferencable,究竟是什麼原因。

vector<Shape*> s1; 
    s1.push_back(new Circle(point(1,2),3)); 
    s1.push_back(new Circle(point(4,3),5)); 
    s1.push_back(new Rectangle(point(1,1),4,5)); 

    vector<Shape*> s2(s1); 
    reverse(s1.begin(),s1.end()); 

    (*find(s1.begin(),s1.end(),new Circle(point(1,2),3)))->move(point(10,20)); 

回答

12

簡單:因爲

  • 查找失敗新建的圓不能在該載體發現*
  • 故障查找返回結束迭代爲抓住這不是deferencable比較形狀通過調試斷言

對於它的工作像你想,你就需要比較形狀,沒有形狀*

正如在其他答案中指出的那樣,boost::ptr_vector是實現這一點的簡單方法。

+0

並且比較形狀對象而不是形狀指針使用boost :: ptr_vector。這使您可以更自然地使用常規算法。 – 2008-11-19 20:00:11

6

像@David Pierre建議:find是基於值的:它在指針的迭代器範圍(例如0x0F234420)中查找,該指針等於指向剛剛創建的new Circle(point(1,2),3)的指針。由於這是一個新的對象,它不會在那裏。

您可以通過使用find_if與指針所引用的對象比較運營商解決這個問題。

但是,Criterium應該能夠區分形狀類型。

class Shape { 
public: 
    //amongst other functions 
    virtual bool equal(const Shape*) const = 0; 
}; 

class Circle : public Shape { 
public: 
    bool equal(const Shape* pOther) const { 
     const Circle* pOtherCircle = dynamic_cast<const Circle*>(pOther); 
     if(pOtherCircle == NULL) return false; 
     // compare circle members 
    } 
}; 

class Rectangle : public Shape { 
public: 
    bool equal(const Shape* pOther) const { 
     const Rectangle* pOtherR = dynamic_cast<const Rectangle*>(pOther); 
     if(pOtherR == NULL) return false; 
     // compare rectangle members 
    } 
}; 



Shape* pFindThis = new Circle(point(1,2),3); 
vector<Shape*>::const_iterator itFound = find_if(s1.begin(),s1.end(), 
    bind1st(mem_fun(&Shape::equal), pFindThis))); 
delete pFindThis; //leak resolved by Mark Ransom - tx! 

if(itFound != s1.end()) { 
    (*itFound)->move(point(10,20)); 
} 
+0

bind1st完成後刪除第二個參數嗎?如果沒有,你有內存泄漏。我想你只是想在那裏有一個當地的臨時工。 – 2008-11-19 15:08:38

+0

你是對的。 – xtofl 2008-11-19 16:02:10

2

這是使用boost :: ptr_vector的一個很好的理由。

它不僅處理你的對象需要被銷燬的事實。
xtofl @:你忘了虛擬析構函數。

但它也使成員看起來像對象通過返回引用而不是指針。這使您可以更自然地使用標準算法,而不是在「平等」函數中使用指針(這非常類似於C++)。

#include <boost/ptr_container/ptr_vector.hpp> 
#include <iostream> 

class Shape 
{ 
    public: 
     ~Shape() {} 
     bool operator==(Shape const& rhs) const 
     { 
      if (typeid(*this) != typeid(rhs)) 
      { 
       return false; 
      } 

      return this->isEqual(rhs); 
     } 
    private: 
     virtual bool isEqual(Shape const& rhs) const = 0; 
}; 

class Circle: public Shape 
{ 
    public: 
     Circle(int r) 
      :radius(r) 
     {} 
    private: 
     virtual bool isEqual(Shape const& r) const 
     { 
      Circle const& rhs = dynamic_cast<Circle const&>(r); 
      return radius == rhs.radius; 
     } 
     int radius; 
}; 
class Rectangle: public Shape 
{ 
    public: 
     Rectangle(int h,int w) 
      :height(h) 
      ,width(w) 
     {} 
    private: 
     virtual bool isEqual(Shape const& r) const 
     { 
      Rectangle const& rhs = dynamic_cast<Rectangle const&>(r); 
      return (height == rhs.height) && (width == rhs.width); 
     } 
     int height; 
     int width; 
}; 


int main() 
{ 

    boost::ptr_vector<Shape> data; 

    data.push_back(new Circle(5)); 
    data.push_back(new Circle(6)); 
    data.push_back(new Rectangle(7,4)); 

    boost::ptr_vector<Shape>::iterator f; 
    f = find(data.begin(),data.end(),Circle(6)); 

    std::cout << "Find(" << (f - data.begin()) << ")" << std::endl; 


}