2010-04-16 71 views
144

thể trùng lặp:
C++ Virtual/Pure Virtual ExplainedSự khác nhau giữa một hàm ảo và một hàm ảo thuần túy

sự khác biệt giữa một hàm ảo thuần khiết và một hàm ảo là gì?

Tôi biết "Pure Virtual Chức năng là một hàm ảo không có cơ thể", nhưng những gì hiện này có nghĩa là và những gì đang thực sự thực hiện bởi các dòng dưới đây:

virtual void virtualfunctioname() = 0 
+1

"một chức năng ảo không có nội dung"> không chính xác. họ có thể có rất nhiều cơ thể. –

Trả lời

189

Hàm ảo làm cho lớp của nó là lớp cơ sở đa hình . Các lớp có nguồn gốc có thể ghi đè lên các chức năng ảo. Các hàm ảo được gọi thông qua các con trỏ/tham chiếu lớp cơ sở sẽ được giải quyết trong thời gian chạy. Đó là, động loại của đối tượng được sử dụng thay vì tĩnh loại của nó:

Derived d; 
Base& rb = d; 
// if Base::f() is virtual and Derived overrides it, Derived::f() will be called 
rb.f(); 

Một hàm ảo thuần tuý là một hàm ảo mà tuyên bố kết thúc bằng =0:

class Base { 
    // ... 
    virtual void f() = 0; 
    // ... 

Một hàm ảo thuần túy làm cho lớp đó được định nghĩa cho trừu tượng (không giống như trong Java, nơi bạn có một từ khóa để khai báo rõ ràng lớp trừu tượng). Các lớp trừu tượng không thể được khởi tạo. Các lớp bắt nguồn cần phải ghi đè/triển khai tất cả các hàm ảo thuần túy được kế thừa. Nếu họ không, họ cũng sẽ trở nên trừu tượng.

Một 'tính năng' thú vị của C++ là một lớp có thể định nghĩa một hàm ảo thuần túy có triển khai thực hiện. (What that's good for is debatable.)


Lưu ý rằng C++ 11 mang một công dụng mới của các từ khóa deletedefault trông tương tự như cú pháp của hàm ảo thuần túy:

my_class(my_class const &) = delete; 
my_class& operator=(const my_class&) = default; 

Xem this questionthis one để biết thêm thông tin về việc sử dụng số điện thoại deletedefault này.

+2

Ồ, do đó, một chức năng ảo thuần túy gần giống như một phương thức trong giao diện Java/C#. Khéo léo. –

+2

@Nick: Thật vậy. Chỉ có C++ cho bạn tự do hơn về nó. (Bạn có thể thực hiện các hàm ảo thuần túy trong C++ và bạn có thể trộn các hàm thuần túy, không thuần khiết và không ảo trong cùng một lớp. (Thông thường, bạn không nên làm điều đó, nhưng nếu bạn cần nó, bạn có thể.) – sbi

+0

@Sbi Tôi nghĩ điểm surmising của "use = 0 cho các hàm ảo thuần túy" đáng để lại. Có lẽ thậm chí chỉ cần thêm vào cuối "Tóm lại, nếu bạn muốn hàm ảo thuần túy, sử dụng' = 0' " – thecoshman

13

Một hàm ảo thuần tuý thường không (nhưng có thể được) thực hiện trong một lớp cơ sở và phải được thực hiện trong một lớp con lá.

Bạn biểu thực tế là bằng cách thêm dấu "= 0" để việc kê khai, như thế này:

class AbstractBase 
{ 
    virtual void PureVirtualFunction() = 0; 
} 

Sau đó, bạn không thể khai báo và khởi tạo một lớp con mà không có nó thực hiện các chức năng ảo tinh khiết:

class Derived : public AbstractBase 
{ 
    virtual void PureVirtualFunction() override { } 
} 

Bằng cách thêm từ khóa override, trình biên dịch sẽ đảm bảo rằng có một hàm lớp cơ sở ảo có cùng chữ ký.

+3

Trong C++, một hàm ảo thuần túy có thể được thực thi. – sbi

+2

có, và cho destructor ảo tinh khiết, nó phải được thực hiện. – daramarak

+0

@daramarak: constructor ảo thuần túy? trong C++? – Naveen

23

Đối với hàm ảo bạn cần cung cấp triển khai trong lớp cơ sở. Tuy nhiên lớp dẫn xuất có thể ghi đè việc triển khai này bằng cách thực hiện riêng của nó.Thông thường, để thực hiện chức năng ảo tinh khiết không được cung cấp. Bạn có thể tạo một hàm thuần ảo với =0 ở cuối khai báo hàm. Ngoài ra, một lớp có chứa hàm ảo thuần túy là trừu tượng tức là bạn không thể tạo đối tượng của lớp này.

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