7

考虑以下:

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>();
    };
};

看起来 DirectoryIterator 应该可以调用boost::make_shared<DirectoryIteratorImpl>,因为它是DirectoryIteratorImpl. 但是,此代码无法编译,因为 DirectoryIteratorImpl 的构造函数是私有的。

因为这个类是一个内部实现细节,客户端DirectoryIterator永远不应该接触,如果我可以保持构造函数私有,那就太好了。

这是我的基本误解make_shared还是我需要标记某种增强片段friend以便编译调用?

4

3 回答 3

5

您确实需要为此结交一些助推器。基本上make_shared是调用构造函数,而这是从友元函数中完成的这一事实对编译器来说并不重要。

不过好消息make_shared是调用构造函数,而不是任何其他部分。所以只是交make_shared朋友就行了……但这意味着任何人都可以创建一个shared_ptr<DirectoryIteratorImpl>……

于 2010-04-07T07:46:48.010 回答
4

有充分的理由不使用旧的shared_ptr构造函数吗?(如果有的话,你可能想看看make_shared实现并去做)

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

这样,对构造函数的调用是从DirectoryIterator已经是它的朋友的类中进行的,DirectoryIteratorImpl而无需为所有其他代码打开大门。

于 2010-04-07T08:42:03.313 回答
0

您可以将类拆分为接口部分和实现部分。接口部分是公开的,实现部分可以有公开的构造函数。但是,这意味着您必须使用虚拟继承。

于 2013-07-19T04:00:50.777 回答