2010-07-14 29 views
24

Có sự khác biệt nào giữa trình phá hoại được bảo vệ và riêng tư trong C++ không? Nếu một lớp cơ sở destructor là riêng tư, tôi tưởng tượng rằng nó vẫn được gọi là khi xóa đối tượng lớp dẫn xuất.Được bảo vệ và hủy riêng tư

+4

Bạn sẽ gặp một số vấn đề phát sinh từ lớp học với destructor riêng =) – SadSido

+0

Trùng lặp cho http://stackoverflow.com/questions/631783/what-is-the-use-of-having-destructor-as-private ? – SadSido

+1

Câu hỏi tương tự ở đây: http://stackoverflow.com/questions/224966/private-and-protected-members-c – Jordan

Trả lời

12

Taken từ here:

Nếu constructor/destructor được khai báo là private thì lớp có thể không được khởi tạo.

Điều này đúng, tuy nhiên nó có thể được khởi tạo từ một phương pháp khác trong lớp học. Tương tự, nếu destructor là private, thì đối tượng chỉ có thể bị xóa khỏi bên trong lớp đó. Ngoài ra, nó ngăn cản các lớp được thừa hưởng (hoặc ít nhất, ngăn chặn các lớp kế thừa từ được instantiated/phá hủy ở tất cả).

+4

public class A {private A() {} public A getA() {return new A(); }} Không chính xác. –

+2

Điều đó không đúng. Đối tượng với riêng destructor * có thể * được instantiated, (trên một ngăn xếp bên trong một chức năng người bạn, ví dụ). – SadSido

+2

Không thể ngăn xếp được phân bổ nhưng có thể được cấp phát heap và cũng từ các chức năng của bạn bè ... –

22

Nếu trình phá hủy lớp cơ sở là private hoặc protected thì bạn không thể gọi delete thông qua con trỏ cấp cơ sở.

Sử dụng trình phá hủy được bảo vệ để ngăn chặn sự phá hủy đối tượng có nguồn gốc thông qua một con trỏ cơ sở. Nó hạn chế quyền truy cập vào destuctor đến các lớp dẫn xuất. Và nó ngăn chặn các đối tượng tự động (stack) của cơ sở lớp.

Trong thực tế nó được sử dụng cho phép bất kỳ khác sử dụng đa hình của nguồn gốc lớp thông qua con trỏ đến cơ sở, nhưng không cho phép người dùng xóa bằng cách sử như một con trỏ . Ví dụ: - Lớp cơ sở trừu tượng/Giao diện.

Nhưng một số protected, non-virtual destructor có vẻ là lỗi đang chờ xảy ra. Giả sử bạn không cung cấp chức năng destroy(), bạn phải cuối cùng biến dtor thành công khai. Ngay sau khi bạn làm điều đó, bạn không có quyền kiểm soát nhiều hơn lớp, và chạy nguy cơ xóa đa hình với một dtor phi ảo, nếu ai đó xuất phát xa hơn từ lớp của bạn.

6

Các đoạn mã sau đây sẽ dẫn đến lỗi biên dịch (VC2010): C2248: 'cơ sở :: ~ cơ sở': không thể truy cập thành viên tin khai báo trong lớp 'cơ sở'

class base 
{ 
    ~base(){} 
}; 

class derived : public base 
{ 
}; 

int main() 
{ 
    derived* d = new derived; 

    delete d; 
} 

Tuy nhiên, nếu bạn thay đổi destructor cơ sở để được bảo vệ, mọi thứ hoạt động tốt.

+0

Nhưng ngay cả khi bạn thay đổi nó thành 'protected', bạn không thể phá hủy các đối tượng thông qua một con trỏ lớp cơ sở. (Trong trường hợp đó nó cũng phải là 'virtual', BTW.) Mà phần nào đánh bại nhiều mục đích của derivation ... – sbi

6

Câu trả lời là giả định của bạn sai. Trình phá hủy lớp cơ sở không thể được gọi khi nó là riêng tư.

+0

Vậy lớp của tôi bị phá hủy như thế nào? – doron

+0

@ deus-ex-machina399: Không thể. Do đó bạn không thể lấy được từ nó. Và bạn không thể tạo ra các đối tượng tự động của nó. Và các đối tượng động không bao giờ có thể bị xóa (trừ khi bạn cung cấp một hàm thành viên làm như vậy). – sbi

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