2013-05-24 32 views
7

Trong variousexplanations của C++ 11's final từ khóa, tôi thấy các ví dụ như thế này.Có ý nghĩa nào trong việc đánh dấu một hàm lớp cơ sở như cả ảo và cuối cùng không?

class base 
{ 
public: 
    virtual void f() final; 
}; 

class derived : public base 
{ 
public: 
    virtual void f(); // Illegal due to base::f() declared final. 
}; 

Đây có phải là sử dụng hữu ích của final không? Tại sao bạn khai báo một hàm ảo trong một lớp cơ sở (ngụ ý rằng nó sẽ được overrideable một cách hữu ích trong các lớp dẫn xuất) và sau đó ngay lập tức đánh dấu nó là final (phủ nhận hàm ý đó)? Tiện ích của virtual void f() final là gì?

Tôi có thể thấy giá trị của việc đánh dấu derived::f() cuối cùng thay vì base::f(). Trong trường hợp này, base::f() có lẽ có lý do thiết kế tốt cho lý do tại sao f() phải là ảo và derived::f() riêng biệt có lý do thiết kế tốt cho lý do tại sao không có lớp nào có nguồn gốc cao hơn.

Nếu bạn không muốn hàm bị ghi đè đa hình, tại sao không chỉ để lại từ khóa ảo? Tất nhiên, các lớp dẫn xuất có thể vẫn ghi đè lên hàm không đa hình. Là mục đích của virtual void f() final trong lớp cơ sở do đó để làm cho base::f() vững chắc không thể ghi đè theo bất kỳ cách nào — hoặc là một hàm ảo hoặc không ảo? Nếu có, thì có vẻ hơi tiếc khi chúng tôi phải thêm từ khóa virtual trong trường hợp này chỉ để cho phép sử dụng final. Tôi nghĩ rằng sau đó nó sẽ là hợp pháp để đánh dấu các chức năng không phải ảo là cuối cùng.

Tại sao sử dụng virtual void f() final cho hàm có nguồn gốc trong lớp cơ sở khi ý nghĩa của virtual và ý nghĩa của final có vẻ mâu thuẫn?

+3

Ví dụ là * ví dụ *; họ dự định thể hiện tính năng của nó, không nhất thiết phải sử dụng nó như thế nào. Cách này chỉ sử dụng hai lớp để hiển thị 'final' có nghĩa là gì. Để sử dụng một ví dụ thế giới thực sẽ yêu cầu * ba *: một để bắt đầu ảo, một để lấy được từ nó và là 'final', và một phần ba để cố gắng lấy ra từ nó và quá tải nó. Cách này ngắn hơn. –

+0

@NicolBolas Tôi hiểu mục đích của các ví dụ. Nhưng loại ví dụ cụ thể này cũng thể hiện một mô hình hữu ích để sử dụng? Đó là câu hỏi. – OldPeculier

Trả lời

4

Bạn có thể đánh dấu nó virtual để cho biết rằng đó là 'ảo' trong lớp bạn đang kế thừa từ (mặc dù bạn không phải làm điều này) và đánh dấu nó final để cho biết rằng không có lớp nào xuất phát từ lớp học của bạn có thể ghi đè thêm. Điều này có thể xảy ra khi bạn đang thực hiện một lớp cơ sở trừu tượng, ví dụ. Đây là C++ 11, vì vậy nó không hữu ích; override là một dấu hiệu tốt hơn nhiều, vì nó được thực thi bởi trình biên dịch.

Một khả năng khác: bạn muốn phương pháp này không bị ghi đè, nhưng bạn muốn có thể thay đổi điều đó mà không cần biên dịch lại. Hãy nhớ rằng virtual có nghĩa là nó nằm trong bảng ảo. ngay cả khi trình biên dịch sẽ không cho phép bạn ghi đè lên nó.

Tôi nghĩ rằng mục đích của ví dụ bạn đã thể hiện là để chứng minh các ưu tiên giữa virtual và cuối cùng và không có gì khác. Đây là một số tối thiểu sử dụng final, không phải là hữu ích.

Đánh dấu phương thức không phải ảo là final không có ý nghĩa vì bạn không thể ghi đè lên chúng. Nếu bạn muốn trình biên dịch để ngăn chặn ẩn, đó là một vấn đề hoàn toàn khác nhau, mà không có gì để làm với phương pháp là final. Trong một nghĩa nào đó, các phương pháp phi ảo là cuối cùng đã được, nhưng hidable.

+0

Đánh dấu một hàm là 'virtual' không chỉ ra rằng nó là' virtual' trong cơ sở. Nó chỉ ra rằng nó là 'virtual' trong lớp đang được định nghĩa, bất kể những gì một lớp cơ sở có thể hoặc có thể không thực hiện được. –

+0

@Pete Becker: Tôi nghĩ anh ấy có ý định tự viết mã. Thực hành phổ biến để respecify từ khóa ảo khi ghi đè lên một base (đặc biệt là trước khi C++ 11 thêm vào override specifier) ​​chỉ vì vậy lập trình viên đọc định nghĩa clasd bị ẩn biết rằng một phương thức cụ thể là ảo. –

+0

@SeanMiddleditch - đó rõ ràng ** không ** những gì anh ta nói. –

0

Cách thay thế là chức năng không phải ảo. Nhưng chức năng phi ảo có thể bị ẩn bởi một lớp dẫn xuất. Vì vậy, nếu bạn muốn ngăn chặn một chức năng ẩn, nó có thể được chỉ định là một trong những cuối cùng ảo.

17

Có ý nghĩa nào trong việc đánh dấu một hàm lớp cơ sở là cả ảo và cuối cùng không?

Có, ít nhất là tạm thời.

Tôi thấy mình trong một cơ sở mã nguồn C++ tương đối lớn và không quen thuộc. Phần lớn mã được viết trước C++ 11. Tôi thấy rằng tôi muốn đảm bảo rằng tất cả các ghi đè của một hàm ảo trong một lớp cơ sở được đánh dấu bằng override. Phần khó xác định tất cả những phần ghi đè đó.

Tôi đã đánh dấu hàm ảo trong lớp cơ sở với final và trình biên dịch nhanh chóng cho tôi biết vị trí mỗi ghi đè đơn lẻ được khai báo. Sau đó nó rất dễ dàng để trang trí các ghi đè như thế nào tôi muốn, và loại bỏ các final từ ảo trong lớp cơ sở.

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