2013-05-29 53 views
19

Tôi đã đọc comments trên Guru Herb Sutter của Redux Tuần về virtual chức năng, và cuối cùng nhìn thấy anh nhắc đến điều này:Sử dụng trường hợp cho các lớp học chính thức

[...] “sử dụng của thức là hiếm” - tốt, họ là loại. Tôi không biết nhiều, và trong quá trình chuẩn hóa, Bjarne liên tục hỏi những ví dụ về các vấn đề mà nó đã giải quyết và các mẫu mà nó nên được sử dụng, và tôi không nhớ lại bất kỳ vấn đề lớn nào nổi bật. Người duy nhất mà tôi biết là nếu bạn định nghĩa một mô-đun thư viện (không phải là một khái niệm chuẩn) thì việc tạo các lớp lá cuối cùng có thể cung cấp cho trình biên dịch nhiều thông tin hơn để thực hiện các cuộc gọi ảo vì biết mã bên ngoài thư viện đã giành được ' t tiếp tục lấy được, nhưng tôi không chắc chắn làm thế nào quan trọng đó là những ngày này trong sự hiện diện của toàn bộ chương trình tối ưu hóa bao gồm cả devirtualization tích cực.

Câu trả lời đó không cung cấp nhiều ví dụ về trường hợp sử dụng cho final trên lớp học và tôi muốn biết những vấn đề nào thực sự có thể giải quyết được. Bạn có biết bất kỳ, hoặc sẽ final trên lớp học chỉ trở thành một số tính năng tối nghĩa và gần như không sử dụng?

+4

Bài đăng blog liên quan [ở đây] (http://akrzemi1.wordpress.com/2012/09/30/why-make-your-classes -sau cùng/). – juanchopanza

+0

câu hỏi liên quan: http://stackoverflow.com/questions/8824587/purpose-of-the-final-keyword – Alex

+0

cũng liên quan: http://stackoverflow.com/questions/11704406/whats-the-point-of-a -final-virtual-function? rq = 1 – Alex

Trả lời

6

Một trường hợp sử dụng bất thường thú vị mà tôi đã tìm thấy tôi đã mô tả here. Tóm lại, bằng cách ngăn chặn sự kế thừa từ lớp int của bạn, bạn tự mua cho mình một khả năng thay thế nó bằng kiểu tích hợp trong các bản phát hành trong tương lai của thư viện của bạn, mà không có nguy cơ phá vỡ mã của người dùng của bạn.

Nhưng một ví dụ phổ biến hơn là devirtualization. Nếu bạn đánh dấu lớp của bạn là cuối cùng, trình biên dịch có thể áp dụng tối ưu hóa thời gian chạy nhất định. Ví dụ,

struct Object { 
    virtual void run() = 0; 
    virtual ~Object() {} 
}; 

struct Impl final : Object 
{ 
    void run() override {} 
}; 

void fun(Impl & i) 
{ 
    i.run(); // inlined! 
} 

Các cuộc gọi đến i.run() giờ đây có thể inlined do final specifier. Trình biên dịch biết rằng tìm kiếm vtable sẽ không cần thiết.

+0

Vâng, tôi sắp sửa nói liên kết nói trên đã được chia sẻ trong các bình luận, nhưng tôi đã không nhận ra nó cũng là bài viết của riêng bạn. – Morwenn

0

final có thể hữu ích khi bạn cung cấp mặt tiền (loại) cho giao diện ban đầu, dễ sử dụng hơn bởi các lớp con. xem xét:

class IMovable { 
    public: 
    void GoTo(unsigned position) = 0; 
} 

class Stepper : public IMovable { 
    public: 
    void GoTo(unsigned position) final; 
    protected: 
    virtual void MoveLeft() = 0; 
    virtual void MoveRight() = 0; 
} 

void Stepper::GoTo(unsigned position) { 
    for(;current_pos < position; current_pos++) { 
    MoveRight(); 
    } 
    for(;current_pos > position; current_pos--) { 
    MoveLeft(); 
    } 
}  

Bây giờ nếu bạn muốn lấy được từ stepper bạn thấy rằng bạn nên ghi đè MoveRightMoveLeft, nhưng bạn không nên ghi đè GoTo. Nó là hiển nhiên trong ví dụ nhỏ này, nhưng nếu IMovable có 20 phương pháp và Stepper có 25, và có triển khai mặc định, hơn bạn có thể gặp khó khăn trong việc tìm ra những gì bạn nên và những gì bạn không nên ghi đè. Tôi đã gặp một tình huống như thế này trong một thư viện liên quan đến phần cứng. Nhưng tôi sẽ không gọi đây là vấn đề lớn đáng ngưỡng mộ theo tiêu chuẩn;)

+1

thats không tuyên bố một 'lớp' cuối cùng! – Alex

+0

@ Alex, bạn nói đúng. Mắt tôi bắt gặp một cụm từ về các chức năng ảo, vì vậy tôi đã bỏ lỡ sự nhấn mạnh vào việc làm cho lớp cuối cùng, không phải là chức năng. Kính gửi OP, tôi có nên rút lại câu trả lời hoặc bạn cũng quan tâm đến các chức năng cuối cùng không? – Steed

+0

@Steed Tôi xin lỗi, nhưng tôi không quan tâm đến tất cả các chức năng 'cuối cùng '; Tôi đã biết tại sao họ tồn tại ngay cả trước khi hỏi câu hỏi ^^ ” – Morwenn

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