2011-02-07 28 views
14

Tại sao tôi có thể tạo một đối tượng của một lớp với destructor riêng trên cửa hàng miễn phí nhưng không phải trên ngăn xếp?Private destructor

Ví dụ này là bất hợp pháp:

class Foo 
{ 
public: 
    explicit Foo(int); 
    static void delete_foo(Foo* foo) { delete foo; } 
private: 
    int x; 
    ~Foo(); 
    Foo(const Foo&); 
    Foo& operator=(const Foo&); 
}; 

int main() 
{ 
    Foo * fooptr = new Foo(5); // legal 
    Foo::delete_foo(fooptr); // legal 
    Foo foo(5); // illegal 
} 
+0

Bạn có thể vui lòng cung cấp mẫu mã ngắn để minh họa không? – sharptooth

+0

Tôi có thể làm điều đó cho bạn – CashCow

Trả lời

18

Khi bạn tạo ra nó trên stack, nó phải bị tiêu diệt trước khi chức năng có thể trở lại. Giả sử hàm trong câu hỏi không có quyền truy cập vào hàm hủy, điều này không được phép.

Khi bạn tạo nó trên cửa hàng miễn phí, nó còn lại cho mã khác, có quyền truy cập vào destructor, để tiêu diệt nó.

Chức năng thành viên của một lớp học với một destructor riêng có thể tạo một thể hiện trên ngăn xếp. Một hàm thành viên tĩnh thậm chí có thể được gọi mà không có một cá thể từ trước. Có lẽ không có lý do tốt để viết một điều như vậy, mặc dù.

+0

+1 cho sắc thái chức năng của thành viên. – GManNickG

+1

@Potatoswatter: nó có thể hữu ích để buộc người dùng truy cập vào đối tượng thông qua proxy 'friend'. Mặc dù có vẻ hạn chế. –

+1

@Matthieu: Vâng, tôi nên đề cập đến điều đó. Có những lý do tốt để viết một destructor riêng.Tôi chỉ có nghĩa là hiếm khi một hàm thành viên tĩnh tạo ra một cá thể tạm thời, hoặc một đối tượng như vậy sẽ được đặt trên stack. – Potatoswatter

2

Vì việc tạo đối tượng trên cửa hàng miễn phí không yêu cầu hủy công cộng, nhưng việc tạo đối tượng trên ngăn xếp sẽ do các đối tượng sẽ bị hủy khi nó nằm ngoài phạm vi. Bạn có thể tạo đối tượng trên cửa hàng miễn phí, nhưng bạn không thể xóa nó, vì vậy bạn sẽ bị rò rỉ bộ nhớ trừ khi đối tượng hoặc chức năng của bạn bè phá hủy nó.

9

Vì đối tượng có bộ nhớ tự động * cần phải được, tốt, tự động bị hủy. Vì vậy, destructor cần phải có sẵn để gọi; nếu không, bạn không thể có loại đó trong bộ nhớ tự động.

Ngược lại, bạn có thể xóa nó khi bạn phân bổ động một cách tự động. Bạn có thể, tất nhiên, không làm như vậy.

* Đối tượng ở đây, trên nền tảng "điển hình", thường được phân bổ trên ngăn xếp.

1

Bạn chỉ có thể tạo một trên ngăn xếp trong phạm vi có quyền truy cập vào trình phá hủy. Do đó bạn có thể làm như vậy trong một hàm người bạn hoặc hàm thành viên tĩnh của lớp (hoặc thậm chí là một thành viên lớp thông thường).

Kết thúc hàm cho biến cục bộ chịu trách nhiệm xóa do đó phải có khả năng gọi hàm hủy, mặc dù ngầm.

Bạn có thể tạo một tài khoản mới từ bất kỳ đâu nếu bạn có quyền truy cập vào hàm tạo thích hợp.

Nếu bạn sử dụng nó trong một con trỏ thông minh, bạn phải đảm bảo nơi nó bị xóa có quyền truy cập. Điều này có thể khác nhau đối với các con trỏ thông minh khác nhau, và đối với một số bạn có thể cung cấp một destructor tùy chỉnh mà có thể là một thành viên tĩnh của lớp.

0

Vì sau đó bạn có thể thực thi một đối tượng luôn được phân bổ động, tức là với toán tử mới. Để thực hiện công việc đó, bạn sẽ cần phải thực hiện một phương thức dispose() gọi là "delete this" trước khi nó trả về. Điều này làm cho nó có thể tạo ra các phương thức hoàn thiện được gọi trước khi một đối tượng hoặc một phần của một đối tượng bị phá hủy và do đó có thể xóa hoặc ngắt kết nối một cách an toàn các thành viên instance trước khi chuỗi destructor ảo được gọi.