2010-04-07 32 views
7

xem xét như sau:Tôi có thể sử dụng boost :: make_shared với một hàm tạo riêng không?

class DirectoryIterator; 

namespace detail { 
    class FileDataProxy; 

    class DirectoryIteratorImpl 
    { 
     friend class DirectoryIterator; 
     friend class FileDataProxy; 

     WIN32_FIND_DATAW currentData; 
     HANDLE hFind; 
     std::wstring root; 

     DirectoryIteratorImpl(); 
     explicit DirectoryIteratorImpl(const std::wstring& pathSpec); 
     void increment(); 
     bool equal(const DirectoryIteratorImpl& other) const; 
    public: 
     ~DirectoryIteratorImpl() {}; 
    }; 

    class FileDataProxy //Serves as a proxy to the WIN32_FIND_DATA struture inside the iterator. 
    { 
     friend class DirectoryIterator; 
     boost::shared_ptr<DirectoryIteratorImpl> iteratorSource; 
     FileDataProxy(boost::shared_ptr<DirectoryIteratorImpl> parent) : iteratorSource(parent) {}; 
    public: 
     std::wstring GetFolderPath() const { 
      return iteratorSource->root; 
     } 
    }; 
} 

class DirectoryIterator : public boost::iterator_facade<DirectoryIterator, detail::FileDataProxy, std::input_iterator_tag> 
{ 
    friend class boost::iterator_core_access; 
    boost::shared_ptr<detail::DirectoryIteratorImpl> impl; 
    void increment() { 
     impl->increment(); 
    }; 
    bool equal(const DirectoryIterator& other) const { 
     return impl->equal(*other.impl); 
    }; 
    detail::FileDataProxy dereference() const { 
     return detail::FileDataProxy(impl); 
    }; 
public: 
    DirectoryIterator() { 
     impl = boost::make_shared<detail::DirectoryIteratorImpl>(); 
    }; 
}; 

Nó có vẻ như DirectoryIterator nên có thể gọi boost::make_shared<DirectoryIteratorImpl>, bởi vì nó là một người bạn của DirectoryIteratorImpl. Tuy nhiên, mã này không biên dịch được vì hàm tạo cho DirectoryIteratorImpl là riêng tư.

Vì lớp này là chi tiết triển khai nội bộ mà khách hàng của DirectoryIterator không bao giờ nên chạm vào, sẽ rất tuyệt nếu tôi có thể giữ riêng hàm tạo.

Đây có phải là sự hiểu lầm cơ bản của tôi xung quanh make_shared hoặc tôi có cần đánh dấu một số loại tăng giá như friend để gọi điện để biên dịch không?

+0

Bạn có chắc chắn cần shared_ptr cho con trỏ impl của mình không? boost :: scoped_ptr thường thích hợp hơn và làm cho mọi thứ trở nên đơn giản hơn nhiều. Shared_ptr thường sẽ chỉ được sử dụng trong trường hợp này nếu bạn muốn DirectoryIterator được sao chép và các bản sao nên chia sẻ một cá thể impl duy nhất. Trong mã bạn đăng, có vẻ như các bản sao chia sẻ một impl sẽ là một lỗi. Shared_ptr là khi nhiều con trỏ chia sẻ quyền sở hữu một cá thể. – Alan

Trả lời

5

Bạn thực sự sẽ cần phải làm cho một số người bạn tăng phần cho việc này. Về cơ bản, make_shared đang gọi hàm tạo và thực tế là việc này được thực hiện từ bên trong một hàm người bạn không quan trọng đối với trình biên dịch.

Tin vui là mặc dù make_shared đang gọi hàm tạo, không phải bất kỳ phần nào khác. Vì vậy, chỉ cần làm cho make_shared bạn bè sẽ hoạt động ... Tuy nhiên, điều đó có nghĩa là bất kỳ ai cũng có thể tạo một shared_ptr<DirectoryIteratorImpl> ...

+1

Hmm ... thật khó chịu như địa ngục :) Cảm ơn! –

+0

Vấn đề 'make_shared' là nó phân bổ một khối bộ nhớ và sau đó sử dụng vị trí' mới', đó là lý do tại sao nó phải tự gọi hàm tạo. Tôi đồng ý rằng nó gây phiền nhiễu liên quan đến vấn đề của bạn. –

+1

Vấn đề với việc này là nếu bạn di chuyển đến TR1 hoặc C++ 0x, hoặc thậm chí nếu tăng phát hành bản cập nhật, bạn không có đảm bảo rằng nó sẽ vẫn hoạt động. – dvide

4

Có lý do chính đáng để không sử dụng công cụ xây dựng cũ shared_ptr không? (Nếu có một, bạn có thể muốn xem xét việc thực hiện make_shared và làm điều đó)

DirectoryIterator() 
    : impl(new detail::DirectoryIteratorImpl()) 
{} 

Bằng cách này, cuộc gọi đến constructor được làm từ lớp DirectoryIterator rằng đã là một người bạn của DirectoryIteratorImpl mà không cần mở cửa cho tất cả các mã khác.

+0

Không, không có gì sai với nó. Nhưng tôi được yêu cầu sử dụng 'make_shared' trên http://stackoverflow.com/questions/2569046/is-there-a-way-to-increase-the-efficiency-of-shared-ptr-by-storing-the- tham chiếu/2569211 # 2569211. Những gì tôi đã làm cho bây giờ chỉ đơn giản là thực hiện chính xác như bạn đề nghị. +1 –

+1

'make_shared' là hiệu quả hơn trong phân bổ bộ nhớ của nó ... (ít phân mảnh hơn, tốc độ lớn hơn) –

+1

Tôi biết về phân mảnh bộ nhớ (bạn thực sự nên meassure), nhưng tôi đọc đôi khi (thực sự ở đây trong SO): * Ông người hy sinh tính chính xác cho hiệu suất xứng đáng không *, đó là một phương châm tốt đẹp. Và trong câu hỏi được liên kết ban đầu, Billy thừa nhận rằng anh không cần buổi biểu diễn. Nếu hàm tạo là riêng tư, 'make_shared' không phải là một người bạn (thực sự gần như phá vỡ đóng gói bằng cách cho phép bất cứ ai xây dựng đối tượng thông qua' make_shared') –

0

Bạn có thể chia lớp thành phần giao diện và phần triển khai. Phần giao diện được đặt ở chế độ công khai và phần triển khai có thể có các hàm tạo công khai. Tuy nhiên, điều đó có nghĩa là bạn phải sử dụng thừa kế ảo.

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