Công cụ phá hủy ảo thuần túy trong C ++


163

Có sai không khi viết:

class A {
public:
    virtual ~A() = 0;
};

cho một lớp cơ sở trừu tượng?

Ít nhất là nó biên dịch trong MSVC ... Nó có bị sập khi chạy không?


9
Nó có thể biên dịch, nhưng nó liên kết?
Vịt Mooing

Câu trả lời:


218

Đúng. Bạn cũng cần thực hiện hàm hủy:

class A {
public:
    virtual ~A() = 0;
};

inline A::~A() { }

nên đủ.

Và vì điều này đã bỏ phiếu, tôi nên làm rõ: Nếu bạn lấy được bất cứ thứ gì từ A và sau đó cố gắng xóa hoặc phá hủy nó, thì Akẻ hủy diệt cuối cùng sẽ được gọi. Vì nó là thuần túy và không có triển khai, hành vi không xác định sẽ xảy ra. Trên một nền tảng phổ biến, điều đó sẽ gọi trình xử lý purecall và sự cố.

Chỉnh sửa: sửa lỗi khai báo để phù hợp hơn, được biên dịch với http://www.comeaucomputing.com/tryitout/


16
Ừm, đúng vậy. Pure chỉ có nghĩa là một lớp dẫn xuất cũng cần cung cấp một triển khai.
MSN

72
Thực hiện các chức năng ảo thuần túy là trên thực tế hợp pháp. Rất hữu ích để cung cấp một triển khai mặc định nhưng buộc các lớp con phải gọi nó một cách rõ ràng.
jmucchiello

6
MSN và lưu ý nếu bạn có định nghĩa đó trong tiêu đề, bạn cần đặt "nội tuyến" trước nó để tránh vi phạm ODR (quy tắc một định nghĩa)
Johannes Schaub - litb

2
Tại sao A :: ~ A () phải được xác định rõ ràng, vì, tôi nghĩ rằng có một hàm hủy mặc định cho mọi đối tượng? Như trong bất kỳ kiểu thừa kế nào, chuỗi các hàm hủy luôn được gọi và hàm hủy của lớp cơ sở không phải luôn luôn được xác định.
jeffD

11
Một cách tốt hơn để đặt nó là một khi bạn khai báo một hàm hủy, nó không tự động được thực hiện cho bạn.
MSN

49

Các hàm hủy riêng tư: chúng sẽ báo lỗi cho bạn khi bạn tạo một đối tượng của lớp dẫn xuất - không phải khác. Một chẩn đoán có thể xuất hiện mặc dù.

12.4 Phá hủy

6 Một hàm hủy có thể được khai báo là ảo (10.3) hoặc ảo thuần (10,4); nếu bất kỳ đối tượng nào của lớp đó hoặc bất kỳ lớp dẫn xuất nào được tạo trong chương trình, hàm hủy sẽ được xác định.

Một lớp với một hàm hủy ảo thuần túy là một lớp trừu tượng. Tôi sẽ lưu ý:

10,4 lớp trừu tượng

2 Chỉ cần xác định một hàm ảo thuần túy nếu được gọi bằng hoặc như với (12.4), cú pháp id đủ điều kiện (5.1).

[ Lưu ý : một khai báo hàm không thể cung cấp cả hàm xác định thuần túy và ghi chú Định nghĩa]

Lấy thẳng từ dự thảo:

struct C {
   virtual void f() = 0 { }; // ill-formed
};

14
+1. Tôi nghĩ Herb Sutter cũng có một số thông tin tốt về điều này: gotw.ca/gotw/031.htm . Thật thú vị khi lưu ý rằng bất kỳ chức năng ảo thuần túy nào cũng có thể có một triển khai được cung cấp, không chỉ các hàm hủy.
Fred Larson

6
Vâng, đó là điều bạn làm trong một cuộc phỏng vấn để làm bối rối những người phỏng vấn bạn;)
dirkgently

1
Theo kinh nghiệm của tôi, đó thực sự không phải là hiếm.

@Neil Butterworth: Cái nào?
dirkgently

@Dirk - kịch bản "bất kỳ chức năng". Không có gì lạ khi thấy nó được sử dụng để thực hiện một số hành vi phổ biến.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.