2010-03-07 28 views
7

Tôi đang làm việc trên một ứng dụng đồ họa đang sử dụng các lớp ảo khá rộng rãi. Nó có:Lớp học ảo tinh khiết và bộ sưu tập (vector?)

  • Lớp ảnh, về cơ bản là tập hợp các hình dạng.

  • Một lớp hình dạng, mà hoàn toàn là ảo và có một vài lớp kế thừa từ nó:

    • Vòng
    • Polygon
    • Rectangle
  • Một hình hình dạng, mà là bất kỳ hình đồ họa (cũng ảo), hình dạng kế thừa từ này.

Về cơ bản, vấn đề của tôi là sử dụng để lưu trữ bộ sưu tập hình dạng. Tôi hiện đang sử dụng Vector để lưu trữ các hình dạng, tuy nhiên, rõ ràng đây là quyết định sai kể từ khi Vector khởi tạo các hình dạng này, điều này không tốt vì chúng hoàn toàn là ảo.

Dưới đây là cơ sở mã hiện tại của tôi (tóm tắt một chút):

class Figure { 
public: 
... 
    virtual ~Figure(); 
... 
}; 

class Shape: public Figure 
{ 
public: 
... 
    virtual ~Shape() {} 
    virtual Shape* clone() const = 0; 
... 
}; 

class Polygon : public Shape 
{ 
public: 
... 
virtual Shape* clone() const {return new Polygon(*this);} 
... 
private: 
std::vector<Point> points; 

}; 

class Picture: public Figure { 
public: 
... 
    Picture(Graphics& gd); 
    Picture (const Picture&); 
    ~Picture(); 
    void clear(); 
    void add (const Shape&); 
... 
private: 
std::vector<Shape> shapes; 
Graphics* gfx; 
}; 

//Picture implementation: 
... 
Picture::Picture(Graphics& gd) 
{ 
gfx = &gd; 
} 


Picture::Picture(const Picture& a) 
{ 
shapes = a.shapes; 
} 

Picture::~Picture() 
{ 
clear(); 
} 

void Picture::clear() 
{ 
shapes.clear(); 
} 

void Picture::add (const Shape& shp) 
{ 
Shape* nshp = shp.clone(); 
shapes.push_back(*nshp); 
} 
... 

Các thông báo lỗi tôi nhận được chỉ là một bó của những:

picture.cpp:33: instantiated from here /opt/local/bin/../lib/gcc/sparc-sun-solaris2.10/4.4.1/../../../../include/c++/4.4.1/ext/new_allocator.h:105: error: cannot allocate an object of abstract type 'Shape' shape.h:12: note: because the following virtual functions are pure within 'Shape': shape.h:58: note: virtual void Shape::get(std::istream&) shape.h:31: note: virtual void Shape::put(std::ostream&) const shape.h:36: note: virtual void Shape::scale(const Point&, double) shape.h:40: note: virtual void Shape::translate(double, double) shape.h:45: note: virtual void Shape::reflectHorizontally(double) shape.h:49: note: virtual void Shape::reflectVertically(double) shape.h:52: note: virtual RectangularArea Shape::boundingBox() const shape.h:21: note: virtual Shape* Shape::clone() const shape.h:55: note: virtual void Shape::draw(Graphics&) const

Vì vậy, cách lý tưởng là gì để lưu trữ những hình dạng này. Tôi nên sử dụng loại bộ sưu tập nào để lưu trữ những thứ này?

Cảm ơn

Trả lời

14

Khi bạn cần đa hình, bạn cần sử dụng con trỏ hoặc tham chiếu. Vì các vùng chứa (hoặc mảng) không thể lưu trữ các tham chiếu, bạn phải sử dụng con trỏ.

Về cơ bản thay đổi vector lớp hình ảnh của bạn để:

std::vector<Shape*> 

và thích hợp thay đổi chức năng thành viên khác.

Lý do tại sao bạn không thể lưu trữ chúng dưới dạng loại giá trị vì vector là một vùng chứa đồng nhất, chỉ lưu trữ dữ liệu của một loại (và chỉ một loại - lớp con không được phép!) . Lý do là vì vector lưu trữ dữ liệu của nó trong một mảng, cần biết kích thước của các đối tượng mà nó lưu trữ. Nếu kích thước của các đối tượng này là khác nhau (mà chúng có thể cho các hình dạng khác nhau) thì nó không thể lưu trữ chúng trong một mảng.

Nếu bạn lưu trữ chúng dưới dạng con trỏ thì tất cả chúng đều có cùng kích thước (sizeof(Shape*)) và cũng có quyền truy cập vào vtable của hình dạng, đó là những gì cho phép hành vi đa hình.

+3

Với các tính năng C++ 0x như con trỏ thông minh được cải thiện và ngữ nghĩa di chuyển, thậm chí có thể tạo phiên bản an toàn cho bộ nhớ này ('vector >'). – bobbymcr

+0

Nếu bạn không sử dụng con trỏ thông minh, hãy nhớ vùng chứa sẽ không tự động dọn sạch dữ liệu được trỏ tới. Nó gọi destructors trên con trỏ - nhưng những destructors không làm bất cứ điều gì. Bạn nên thêm một destructor vào lớp hình ảnh của bạn mà iterates thông qua các hình dạng xóa chúng. Sử dụng một lớp con trỏ thông minh, như bobbymcr gợi ý, tránh vấn đề này. – Steve314

+0

Bạn là người đàn ông! Cảm ơn bạn rất nhiều. Điều đó là vậy đó. –

1

Sử dụng các loại trả về biến đổi. Xem FAQ 20.8 cho các phương thức clone của bạn. Bạn cũng có thể dựa vào phương pháp nhà máy để tạo các đối tượng Shape.

Ngoài ra, bạn không thể có vùng chứa đối tượng lớp trừu tượng, lớp trừu tượng không thể được khởi tạo. Thay vào đó, hãy tạo một container con trỏ/tham chiếu đến các đối tượng cụ thể có nguồn gốc. Lưu ý, nếu bạn đang sử dụng con trỏ, nó trở thành trách nhiệm của bạn để xóa chúng. Vùng chứa sẽ không phân bổ bộ nhớ đúng cách. Bạn có thể sử dụng con trỏ thông minh thay vì con trỏ thô để xử lý điều này hiệu quả hơn. Tra cứu scoped_ptrshared_ptr từ Tăng cường.

+0

Khi đọc lướt đầu tiên, tôi thấy "loại trả về biến đổi" và giả định nó trả lời sai câu hỏi. Đưa ra rằng sau khi câu trả lời chính có thể đã kiếm được bạn upvotes hơn. Bạn đã nhận được +1 của tôi ngay bây giờ. – Steve314

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