2011-11-20 32 views
6

Tôi có một lớp resource_manager duy trì một số std::vector<boost::shared_ptr<resource> > trong nội bộ. resource_manager là một lớp bạn của resource. Tôi muốn resource s chỉ được tạo/xóa bởi resource_manager, vì vậy tôi đã tạo các hàm tạo riêng tư (hoạt động tốt).Làm thế nào tôi có thể gọi một destructor tư nhân từ một shared_ptr?

Tuy nhiên, nếu tôi làm cho hàm hủy riêng, mã không biên dịch vì hàm hủy được gọi bởi boost::shared_ptr, không phải là bạn của resource. Tôi đang nghĩ đến việc thực thi quy tắc "không xóa bởi khách hàng" bằng cách chỉ trả về const resource* từ resource_manager, nhưng bằng cách nào đó tôi không hài lòng với bảo mật mà phương pháp này cung cấp (điều gì sẽ xảy ra nếu một khách hàng nào đó xảy ra trên con trỏ tới không phải là const?)

Ngoài giải pháp rõ ràng khi không sử dụng shared_ptr, bạn có giải pháp nào tốt hơn cho vấn đề của mình không?

+0

"khách hàng bằng cách nào đó xảy ra trên một con trỏ để không const" cách duy nhất họ có thể làm điều đó là nếu họ sử dụng const_cast. Từ quan điểm "bảo mật", không có sự khác biệt giữa con trỏ thô và shared_ptr, sự khác biệt nằm trong quản lý thời gian sống, trong đó tôi không chắc chắn cách bạn xử lý mà không có shared_ptr. – ronag

+4

Một 'const resource *' không có nghĩa là bạn không thể xóa nó. – UncleBens

+0

@UncleBens: Nó không? Tôi nghĩ rằng trình biên dịch không nên cho phép bạn gọi một hàm không const trên một const! Tôi có nhầm không? Hay quy tắc này không áp dụng cho destructor? –

Trả lời

11

Bạn có thể chuyển dấu tùy chỉnh cho con trỏ được chia sẻ. Vì vậy, chỉ cần tạo một functor deleter hoặc chức năng (tùy thuộc vào bạn) do đó là một friend của lớp học của bạn:

class Secret 
{ 
    ~Secret() { } 
    friend class SecretDeleter; 
    friend void SecretDelFunc(Secret *); 
}; 

class SecretDeleter 
{ 
public: 
    void operator()(Secret * p) { delete p; } 
}; 

void SecretDelFunc(Secret * p) { delete p; } 

std::shared_ptr<Secret> sp1(new Secret, SecretDeleter()); 
std::shared_ptr<Secret> sp2(new Secret, SecretDelFunc); 
+0

Tại sao bạn luôn nhanh hơn tôi với cùng một ý tưởng? Dừng lại! :( – Xeo

+0

@Xeo: Tốt hơn nên chọn một miếng bánh khác - Tôi có đôi mắt vững chắc trên 'shared_ptr'! ;-) –

+1

Btw, bạn nên khởi tạo' SecretDeleter'. – Xeo

1

Có lẽ khai báo shared_ptr<resource> làm bạn? shared_ptr không gọi hàm tạo và chỉ nên hủy nếu trình quản lý tài nguyên của bạn giải phóng con trỏ trước khi tất cả các máy khách đã hủy shared_ptrs của chúng. Điều này sẽ không cho phép khách hàng phá vỡ sự bảo vệ, nhưng sẽ cho phép các khách hàng giữ một nguồn tài nguyên còn sống dựa vào "ý chí" của resource_manager.

+0

Nó có vẻ không hoạt động khi tôi thử –

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