我可以将boost :: make_shared与私有构造函数一起使用吗?

时间:2010-04-07 06:00:12

标签: c++ boost shared-ptr make-shared

请考虑以下事项:

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才能调用编译?

3 个答案:

答案 0 :(得分:5)

你确实需要为此制作一些朋友。基本上make_shared正在调用构造函数,并且这是在友元函数中完成的事实对编译器无关紧要。

但好消息是make_shared正在调用构造函数,而不是任何其他部分。所以只需让make_shared朋友工作......但这意味着任何人都可以创建一个shared_ptr<DirectoryIteratorImpl> ......

答案 1 :(得分:4)

有没有充分的理由不使用好的旧shared_ptr构造函数? (如果有的话,您可能需要查看make_shared实现并执行此操作)

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

这样对构造函数的调用是从DirectoryIterator类开始的,该类已经是DirectoryIteratorImpl的朋友而没有打开所有其他代码的大门。

答案 2 :(得分:0)

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