2013-01-31 41 views
13

Tôi có một lớp cơ sởLớp trừu tượng C++ không có chức năng ảo thuần túy?

class ShapeF 
{ 
public: 
    ShapeF(); 
    virtual ~ShapeF(); 

    inline void SetPosition(const Vector2& inPosition) { mPosition.Set(inPosition); } 

protected: 
    Vector2 mPosition; 
} 

Rõ ràng với một số mã ommitied, nhưng bạn sẽ có được điểm. tôi sử dụng điều này như một mẫu, và với một số thú vị enums (Bỏ qua phần), một cách để xác định loại hình tôi đang sử dụng

class RotatedRectangleF : public ShapeF 
{ 
public: 
    RotatedRectangleF(); 
    virtual ~RotatedRectangleF(); 
protected: 
    float mWidth; 
    float mHeight; 
    float mRotation; 
} 

ShapeF làm công việc của mình với vị trí, và một enum định nghĩa những gì loại là. Nó có accessors và mutators, nhưng không có phương pháp.

Tôi có thể tạo cho ShapeF một lớp trừu tượng, để đảm bảo không ai cố gắng và khởi tạo một đối tượng thuộc loại ShapeF?

Thông thường, đây là doable bằng việc có một hàm ảo thuần tuý trong ShapeF

//ShapeF.h 
virtual void Collides(const ShapeF& inShape) = 0; 

Tuy nhiên, Tôi hiện đang làm việc với các va chạm trong một lớp riêng biệt. Tôi có thể di chuyển mọi thứ, nhưng tôi tự hỏi liệu có cách nào để tạo một lớp trừu tượng .. mà không có các hàm ảo thuần túy.

+0

Bạn đang cố gắng thực hiện lại công văn động với gắn thẻ (enum) và truyền ... sẽ sớm trở thành cơn đau trong tương lai. Tôi sẽ xem xét lại thiết kế. –

+0

@ DavidRodríguez-dribeas Tôi đã tìm ra đây là cách tiếp cận dễ nhất, static_casting mọi thứ. Nếu tôi muốn thiết kế lại, tôi sẽ loại bỏ ShapeF() hoàn toàn, với tất cả tính đa hình, và có mỗi hình dạng là người của chính nó. Trừ khi bạn có một đề nghị khác? – MintyAnt

Trả lời

39

Bạn có thể tuyên bố, và thực hiện, một destructor ảo tinh khiết:

class ShapeF 
{ 
public: 
    virtual ~ShapeF() = 0; 
    ... 
}; 

ShapeF::~ShapeF() {} 

Đó là một bước nhỏ so với những gì bạn đã có, và sẽ ngăn chặn ShapeF khỏi bị khởi trực tiếp. Các lớp dẫn xuất sẽ không cần phải thay đổi.

+3

Câu hỏi nhanh - tại sao '~ ShapeF' cần phải được triển khai khi nó được khai báo là' pure virtual'? –

+0

Cảm ơn, điều này hoạt động hoàn hảo. Bất kỳ ý tưởng tại sao điều này hoạt động? Một ảo tinh khiết không thể được định nghĩa, tôi nghĩ. – MintyAnt

+4

Nó phải được xác định, hoặc các lớp dẫn xuất không thể phá hủy lớp cơ sở của chúng. Bất kỳ hàm ảo thuần túy nào cũng có thể được định nghĩa, cho phép các lớp dẫn xuất ủy nhiệm cho chúng. –

18

Hãy thử sử dụng một nhà xây dựng được bảo vệ

+0

+1, trình phá hủy phải được 'bảo vệ' và không phải là ảo. Có một trường hợp góc mà điều này không giải quyết vấn đề, nếu 'ShapeF' là' new'-ed và không bao giờ 'xóa'-d (nhưng đó là một lỗi trong chính nó) –

+0

@ DavidRodríguez-dribeas Tại sao destructor nên được bảo vệ ? Nếu nó được bảo vệ, bạn không thể xóa đối tượng. –

+0

@JamesKanze: Tôi đoán * nên * là một từ ngữ mạnh mẽ. Tôi có cảm giác rằng lý do duy nhất mà destructor là 'virtual' là tuân theo lời khuyên của * always * làm cho destructor virtual nếu kiểu đó có nghĩa là được bắt nguồn.Làm cho destructor 'protected' giải quyết cùng một vấn đề cơ bản và cung cấp một giải pháp cho vấn đề không instantiating (ít nhất là trong stack, và trong heap trừ khi bạn hài lòng với rò rỉ bộ nhớ :) Ở mức nào, cảm giác của tôi là toàn bộ thiết kế nên được xem xét lại (như tôi đã đề cập trong phần bình luận cho câu hỏi) –

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