2012-12-14 39 views
153

Theo tôi hiểu, việc giới thiệu từ khóa override trong C++ 11 không là gì ngoài kiểm tra để đảm bảo rằng hàm đang được triển khai là hàm override ing của hàm cơ sở trong hàm cơ sở.Từ khoá 'ghi đè' chỉ là một kiểm tra cho một phương thức ảo bị ghi đè?

Có phải không?

+42

Có.⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣ –

+11

Tuy nhiên, đây không phải là séc kép. Đó là kiểm tra duy nhất. –

+0

@Nikos tốt điểm;), cố định – aiao

Trả lời

183

Đó thực sự là ý tưởng. Vấn đề là bạn có rõ ràng về những gì bạn có ý nghĩa, vì vậy mà một lỗi khác im lặng có thể được chẩn đoán:

struct Base 
{ 
    virtual int foo() const; 
}; 

struct Derived : Base 
{ 
    virtual int foo() // whoops! 
    { 
     // ... 
    } 
}; 

Đoạn mã trên biên dịch, nhưng không phải là những gì bạn có thể có nghĩa là (chú ý thiếu const). Nếu bạn nói thay vào đó, virtual int foo() override, sau đó bạn sẽ nhận được một lỗi trình biên dịch rằng chức năng của bạn không thực sự ghi đè bất cứ điều gì.

+51

+1: Mặc dù, thật không may, đó là một chút của một cá trích đỏ khi mọi người cho rằng tính năng mới 'ghi đè' sửa lỗi" này; bạn phải nhớ sử dụng nó, cũng giống như bạn nên nhớ để viết 'const';) –

+0

Tôi vừa nhận ra các định nghĩa lớp' tường minh' không làm cho nó thành C++ 11. Huh. – aschepler

+1

@aschepler Và định nghĩa lớp 'tường minh' sẽ làm gì? Chưa bao giờ nghe về điều đó. –

23

Wikipedia quote:

Các override nhận dạng đặc biệt có nghĩa là trình biên dịch sẽ kiểm tra các lớp cơ sở (es) để xem liệu có một hàm ảo với chữ ký chính xác này không. Và nếu không có, trình biên dịch sẽ lỗi.

http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final

Chỉnh sửa (cố gắng để cải thiện một chút câu trả lời):

Khai báo một phương pháp là "ghi đè" có nghĩa là rằng phương pháp dành để viết lại một phương pháp (ảo) trên lớp cơ sở. Phương thức ghi đè phải có cùng một chữ ký (ít nhất là cho các tham số đầu vào) làm phương thức mà nó dự định viết lại.

Tại sao điều này lại cần thiết? Vâng, hai trường hợp lỗi phổ biến sau đây được ngăn chặn:

  1. một loại mờ theo kiểu mới. Trình biên dịch, không biết rằng nó có ý định viết một phương thức trước đó, chỉ cần thêm nó vào lớp như một phương thức mới. Vấn đề là phương pháp cũ vẫn còn đó, phương thức mới được thêm vào chỉ là quá tải. Trong trường hợp này, tất cả các cuộc gọi hướng tới phương thức cũ sẽ hoạt động giống như trước, mà không có bất kỳ thay đổi nào về hành vi (mà có thể là mục đích của việc viết lại).

  2. một lần quên khai báo phương thức trong siêu lớp là "ảo", nhưng vẫn cố gắng viết lại nó trong lớp con. Trong khi điều này sẽ được chấp nhận, hành vi sẽ không chính xác như dự định: phương thức không phải là ảo, do đó truy cập thông qua con trỏ tới lớp cha sẽ kết thúc gọi phương thức cũ (superclass ') thay vì phương thức mới (lớp con).

Thêm "override" rõ ràng disambiguates này: qua chuyện này, người ta đang nói với trình biên dịch rằng ba điều đang mong đợi:

  1. có một phương pháp có cùng tên trong lớp cha
  2. này phương thức trong siêu lớp được khai báo là "ảo" (có nghĩa là, dự định được viết lại)
  3. phương thức trong lớp cha có cùng chữ ký (đầu vào *) làm phương thức trong lớp con (phương pháp viết lại)

Nếu bất kỳ điều nào trong số này là sai, thì lỗi được báo hiệu.

* lưu ý: thông số đầu ra đôi khi khác, nhưng loại có liên quan. Đọc về biến đổi covariant và contravariant nếu quan tâm.

18

Tìm thấy "ghi đè" rất hữu ích khi ai đó cập nhật chữ ký phương thức ảo cơ sở lớp như thêm tham số tùy chọn nhưng quên cập nhật chữ ký phương thức lớp dẫn xuất. Trong trường hợp đó, các phương thức giữa cơ sở và lớp dẫn xuất không còn quan hệ đa hình nữa. Nếu không có tuyên bố ghi đè, thật khó để tìm ra loại lỗi này.

+0

+1. Mặc dù trong khi 'override' là một cách tuyệt vời để khám phá những vấn đề như vậy, thì việc kiểm tra đơn vị tốt cũng nên giúp đỡ. –

+0

Đó chính là lý do tại sao tôi rất vui mừng về thông số mới đó. Vấn đề duy nhất là tính năng này phải được áp dụng để ngăn chặn các lỗi gây ra bởi những thay đổi trong các lớp cơ sở. ;-) – Wolf

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