2008-11-19 38 views
9

Tôi có một lớp cơ sở trừu tượng được gọi là hình dạng mà từ đó cả hai hình tròn và hình chữ nhật có nguồn gốc, nhưng khi tôi thực thi mã sau trong VS 2005 tôi nhận được lỗi Debug khẳng định thất bại. Đồng thời tôi đã không quá tải toán tử == trong bất kỳ lớp nàoVector iterator không dereferencable

Biểu thức: Vector iterator không dereferencable, lý do cho việc này là gì.

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

Trả lời

12

đơn giản:

  • tìm thất bại kể từ khi bạn mới được tạo ra mạng kết nối không thể được tìm thấy trong các vector với so sánh Shape *
  • một phát hiện thất bại trả về iterator cuối mà không phải là deferencable như bắt bởi một sự khẳng định gỡ lỗi

Đối với nó để làm việc như bạn muốn, bạn không cần phải so sánh Shape, không Shape *

Như đã chỉ ra trong các câu trả lời khác, boost::ptr_vector là một cách dễ dàng để đạt được điều này.

+0

Và để so sánh Đối tượng hình dạng thay vì sử dụng Hình dạng con trỏ tăng :: ptr_vector. Điều này cho phép bạn sử dụng các thuật toán thông thường tự nhiên hơn nhiều. –

6

Giống như @David Pierre đề xuất: tìm dựa trên giá trị: nó tìm trong phạm vi của trình lặp cho con trỏ (ví dụ: 0x0F234420) bằng con trỏ đến new Circle(point(1,2),3) bạn vừa tạo. Vì đó là một vật thể mới, nó sẽ không ở đó.

Bạn có thể thực hiện việc này bằng cách sử dụng find_if với toán tử so sánh các đối tượng được con trỏ tham chiếu.

Tuy nhiên, Criterium sẽ có thể phân biệt giữa các loại hình dạng.

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

Liệu bind1st có xóa tham số thứ hai khi thực hiện xong không? Nếu không, bạn bị rò rỉ bộ nhớ. Tôi nghĩ bạn chỉ muốn một địa phương tạm thời ở đó. –

+0

Bạn hoàn toàn đúng. – xtofl

2

Đây là lý do chính đáng để sử dụng tăng :: ptr_vector.

Nó không chỉ xử lý thực tế rằng các đối tượng của bạn cần phải được tiêu huỷ.
xtofl @: Bạn đã quên trình phá hủy ảo.

Nhưng nó cũng làm cho các thành viên trông giống như các đối tượng bằng cách trả về tài liệu tham khảo chứ không phải là con trỏ. Điều này cho phép bạn sử dụng các thuật toán chuẩn tự nhiên hơn là chơi xung quanh với con trỏ trong hàm 'bằng' của bạn (rất giống với 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; 


} 
+0

Có vẻ như một chút nguy hiểm khi dựa vào toán tử == để xác nhận rằng các hình dạng là cùng loại trước khi gọi isEqual. Tôi muốn thấy rằng kiểm tra bên trong isEqual chính nó, như xtofl đã làm. –

+0

Tôi thích nó trong 'operator ==' theo cách này mã không được lặp lại. Tại sao bạn muốn nó trong isEqual? Lưu ý Hình dạng là một ảo tinh khiết có thể không có trường hợp. Tôi không hiểu tại sao bạn nghĩ nó là dangrorus? –

+0

Tôi có một nghi ngờ về việc kiểm tra typeids trong các lớp cơ sở. Tại sao điều này thực sự là cần thiết? Bởi vì lời gọi để sửa hàm isEqual được giải quyết trong thời gian chạy vì Đa hình. – Poorna

Các vấn đề liên quan