2010-02-11 40 views
19

Tôi đã thấy mã trong lớp dẫn xuất gần đây trong đó lập trình viên đặt virtual trước các hàm được ghi đè. Điều này có phổ biến không? Tôi nghĩ nó rất kỳ quặc và nó khiến tôi mất cảnh giác.Sử dụng 'ảo' trong lớp dẫn xuất

Chỉnh sửa: Tôi không hỏi những gì ảo làm, tôi hỏi lý do tại sao một người nào đó đặt ảo trong lớp dẫn xuất đã ghi đè các hàm ảo trong lớp cơ sở của nó.

EX:

class B { 
public: 
    virtual void foo(); 
    .... 
}; 

class D : public B { 
public: 
    virtual void foo(); // could have just put void foo(); 
    ... 
}; 
+4

Tôi luôn làm điều này, chỉ để ghi lại mã của mình. –

+3

Đây là điều mà tôi nghĩ C# là tốt hơn, bằng cách buộc các lớp dẫn xuất sử dụng từ khóa 'override'. – dalle

+0

Đây là câu hỏi hoàn hảo, trả lời nhiều câu hỏi của tôi về cách hoạt động của ảo. Thanks @Person –

Trả lời

25

virtual là cần thiết cho các chức năng ghi đè ở cấp (có nguồn gốc ít nhất) cao nhất. Nó là tùy chọn, nhưng vô hại ở mức thấp hơn (có nguồn gốc). Thật tốt cho việc tự viết mã.

+3

Chính xác. Trình biên dịch đã biết, nhưng những người khác đọc mã của bạn có thể phải theo dõi lại qua nhiều tệp tiêu đề để tìm hiểu. –

3

Tôi giả sử rằng bạn biết mục đích của từ khóa ảo nhưng tự hỏi tại sao nó đột nhiên xuất hiện trong một loại phụ. Nếu tôi nhầm, câu trả lời của tôi có lẽ sẽ không có ý nghĩa nhiều nhưng bất kỳ tham chiếu C++ nào cũng sẽ làm.

Hoàn toàn hợp pháp khi đặt ảo trong lớp dẫn xuất. Kết quả là, nếu bạn có một tham chiếu hoặc con trỏ đến lớp đó hoặc bất kỳ lớp con nào của nó, các lời gọi của hàm này sẽ bị ràng buộc động dựa trên kiểu thời gian chạy.

Mặc dù hợp pháp, nó không được coi là thiết kế tốt để có phương thức không ảo trong lớp cơ sở và ảo trong phiên bản ghi đè.

Một lý do là bạn có thể có một thể hiện của lớp dẫn xuất, và sau đó một con trỏ đến cơ sở và một con trỏ đến nguồn gốc, và có cả hai con trỏ nhằm vào trường hợp này. Gọi hàm giống nhau trên mỗi con trỏ sau đó sẽ có một kết quả khác nhau, vì việc gọi trên con trỏ được khai báo với lớp cơ sở sẽ nhắm mục tiêu định nghĩa trong lớp cơ sở.

4

Tôi không thấy gì lạ trong đó. Trong nhiều trường hợp (nếu không phải hầu hết thời gian) các lập trình viên tạo ra khai báo hàm overriding trong lớp dẫn xuất bằng cách sao chép nó từ lớp cơ sở. Không có vấn đề gì khi chi tiêu thêm nỗ lực để xóa thủ công thông số virtual dư thừa. Hơn nữa, rõ ràng virtual làm cho nó dễ dàng hơn để xem những chức năng nào là ảo.

8

Điều này rất phổ biến. Nhiều hướng dẫn phong cách giới thiệu nó, ví dụ: Google. Mục đích là để tăng cường khả năng đọc của mã.

+1

Liên kết không hoạt động –

+0

Liên kết mới tại đây http://google.github.io/styleguide/cppguide.html#Inheritance Liên kết nói để sử dụng 'ghi đè' hoặc' ảo' * nhưng không phải cả hai *. –

1

Điều này cũng sẽ giúp ích cho các dẫn xuất trong tương lai. Nếu ai đó muốn lấy được lớp D và có chức năng ảo, sau đó nó dễ hiểu

4

Một cách khác để tăng cường khả năng đọc là sử dụng một cái gì đó như thế này:

class B { 
public: 
    virtual void foo(); 
    .... 
}; 

class D : public B { 
public: 
    /*override*/ void foo(); 
    ... 
}; 
3

Những câu trả lời (và thực tế điều này) là lỗi thời . Kể từ C++ 11, bạn nên sử dụng override keyword để chỉ rõ một hàm ảo ghi đè một hàm ảo khác. Trình biên dịch của bạn sẽ ném một lỗi nếu bạn cố gắng để override cái gì đó không phải là một chức năng ảo trong lớp cơ sở!

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