2008-11-19 122 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; 


}