2010-07-26 43 views
8

Tôi códesctructor ảo trên tinh khiết trừu tượng lớp cơ sở

struct IMyInterface 
{ 
    virtual method1() = 0; 
    virtual method2() = 0; 
}; 

GCC khẳng định rằng tôi có

struct IMyInterface 
{ 
    virtual method1() = 0; 
    virtual method2() = 0; 
    virtual ~IMyInterface(){}; 
}; 

Tôi không hiểu tại sao. Một giao diện thuần túy là tất cả về giao diện (duh). Destructor là một phần của các chi tiết thực hiện nội bộ của một người triển khai cụ thể của giao diện; nó không tạo thành một phần của giao diện. Tôi hiểu toàn bộ vấn đề cắt lát (hoặc ít nhất là tôi nghĩ mình làm)

Vì vậy, câu hỏi của tôi là - GCC có phải nhấn mạnh vào nó không và nếu có thì tại sao?

+0

Bạn đang nói về destructors, nhưng mã của bạn cho thấy một hàm tạo. Đó là câu hỏi về? –

+0

@mmyers, đã sửa nó. –

+1

Quy tắc 1 của Lập trình: Trình biên dịch luôn đúng. Quy tắc 2 của Lập trình: Nếu Trình biên dịch sai, Quy tắc 1 sẽ áp dụng. –

Trả lời

19

Theo thông số C++, có.

Bạn cần phải khai báo destructor ảo bởi vì nếu không, sau

IMyInterface * ptr = getARealOne(); 
    delete ptr; 

sẽ không gọi destructor trên lớp có nguồn gốc (vì destructor không nằm trong vtable)

Nó cần phải không thuần khiết bởi vì các lớp hủy cơ sở luôn được gọi bởi trình phá hủy lớp con.

Để giải thích thêm, C++ không có khái niệm về giao diện giống như cách Java hoặc C# thực hiện. Nó chỉ là một quy ước để chỉ sử dụng các phương thức thuần ảo, và nghĩ đó là một giao diện. Các quy tắc khác về C++ destructors làm cho nó không phải là không thuần túy, nó phá vỡ sự tương đồng với các giao diện trong các ngôn ngữ khác, nhưng những ngôn ngữ đó không tồn tại vào thời điểm các quy tắc này được tạo ra.

+4

Nitpick - Tôi nghĩ bạn có thể làm cho nó tinh khiết ảo nếu bạn muốn yêu cầu các lớp con thực hiện nó. Nhưng bạn vẫn phải cung cấp việc triển khai vì những lý do bạn đã nêu. –

+0

Tôi không nghĩ vậy - nó sẽ được gọi, vì vậy tốt hơn là nên định nghĩa. Tôi đã không thử nó, nhưng thường là một ảo tinh khiết được thực hiện bởi trình biên dịch như đặt một chức năng lỗi trong VTable để phàn nàn rằng nó đã được gọi. Có lẽ tôi có thể tưởng tượng một trường hợp đặc biệt cho destructors, nhưng tôi khá chắc chắn rằng đó không phải là những gì spec nói (Không 100% mặc dù) –

+0

@Lou Franco: Pure chức năng ảo có thể có định nghĩa. –

3

Nếu bạn không khai báo d'tor ảo trong lớp cơ sở, xóa đối tượng của lớp dẫn xuất thông qua con trỏ tới lớp cơ sở dẫn đến hàm hủy sai được gọi, và do đó không xác định hành vi và rò rỉ tài nguyên.

struct A { 

    virtual ~A() {} 

}; 

struct B : A { 

    std::string us_constitution; 
}; 


B* pb = new B(); 
A* pa = pb; 

delete pa; // without the virtual d'tor in the base class, 'B::us_constitution' would never be freed. 
+0

Nitpick: B :: us_constitution không thể được free'd bởi vì nó không bao giờ new'd.Các lưu trữ nó sử dụng, tuy nhiên, sẽ không được trả lại cho hệ thống mà không có destructor ảo. –

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