2011-08-12 42 views
5
class Base 
{ 
    virtual void foo() = 0; 
    //~Base();  <-- No destructor! 
}; 

Rõ ràng, Base sẽ được bắt nguồn. Vì vậy, không C + + nói rằng trình biên dịch tạo ra destructor của Base phải được ảo?Trình phá hủy trình biên dịch tạo ra của lớp cơ sở trừu tượng có phải là ảo không?

Cảm ơn!

+3

No. Nhưng tôi không thể cung cấp cho bạn một tài liệu tham khảo cho một cái gì đó tiêu chuẩn * không * nói ... –

+2

Nếu chỉ trình biên dịch có thể trả lời câu hỏi trên stackoverflow;) – MerickOWA

Trả lời

6

Không, trình hủy sẽ không là virtual trừ khi bạn đánh dấu nó như vậy. Lý do là đơn giản - các cuộc gọi có thể được thực hiện hầu như thông qua con trỏ và thông qua tài liệu tham khảo và làm thế nào và cho dù bạn thực hiện cuộc gọi hầu như không liên quan đến việc bạn tạo các đối tượng với new. Nếu bạn không tạo các đối tượng với new, bạn không cần phải delete chúng và do đó bạn không cần các trình phá hủy ảo.

1

Không, dtor không được bảo đảm là ảo.

Khi khai báo các lớp được thiết kế đặc biệt để bắt nguồn từ, thực hành tốt của nó để khai báo một cách rõ ràng một dtor ảo. Nó thường là một lỗi thiết kế hoàn toàn không. Trong thực tế, tôi không thể nghĩ về một trường hợp mà nó không phải là một lỗ hổng thiết kế để bỏ qua dtor ảo từ lớp cơ sở.

+2

Một số lớp học có thể được thiết kế để có nguồn gốc từ nhưng không được sử dụng đa hình (ví dụ: 'boost :: noncopyable'). Trong trường hợp này, không có điểm trong việc cung cấp một destructor ảo. –

+0

@Luc: trong trường hợp đó, đó là một ý tưởng hay để bảo vệ lớp hủy cơ sở, để ngăn chặn việc xóa đa hình không hợp lệ. –

+0

Điều đó đúng là tất nhiên. Tôi đã suy nghĩ về bối cảnh của câu hỏi, đó là một ABC. –

2

Nó không. Đây là gần một bằng chứng cho thấy các destructor không tự động làm ảo: Hành vi

#include <iostream> 

struct BaseBase { 
    ~BaseBase() { 
     std::cout << "~BaseBase\n"; 
    } 
}; 

struct Base : BaseBase 
{ 
    virtual void foo() = 0; 
    //~Base();  <-- No destructor! 
}; 

struct Derived : Base { 
    void foo() { std::cout << "foo\n"; } 
    ~Derived() { 
     std::cout << "~Derived\n"; 
    } 
}; 

int main() { 
    Base *p = new Derived(); 
    delete p; 
} 

Chương trình này thực sự đã không xác định, nhưng tôi mạnh nghi ngờ rằng tình hình thực hiện của bạn nó không in "~ Xuất phát". Nếu Base có một destructor ảo, sau đó nó sẽ không có hành vi không xác định, và nó sẽ in "~ Derived".

Tất nhiên nó không thực sự chứng minh bất cứ điều gì về tiêu chuẩn. Bất kỳ triển khai nào bạn chạy nó có thể sau khi tất cả đều không phù hợp. Nhưng một khi bạn đã thử nó trên một vài, bạn sẽ nhận được ý tưởng rằng bất cứ điều gì tiêu chuẩn có thể nói, bạn cần phải xác định một destructor ảo.

+0

Tôi đã thử nghiệm trong codepad: http://codepad.org/oMs4Kuye (g ++ 4.1.2) và nó không in "~ Derived" như bạn mong đợi. Không có trên MSVC2008 của tôi. Cảm ơn ví dụ. –

1

Không. Lớp học có thể có thành viên ảo, có thể được bắt nguồn và thậm chí có thể được phân bổ với new và bị xóa với delete mà không có trình phá hủy ảo.

Điều bất hợp pháp (UB) cần thực hiện là hủy một cá thể có nguồn gốc với deletebằng cách sử dụng con trỏ tới cơ sở nếu hủy không được khai báo ảo.

Tất nhiên không có lý do gì để không khai báo một destructor ảo nếu lớp của bạn có nghĩa là để được bắt nguồn.

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