请考虑以下事项:
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
才能调用编译?
答案 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)
您可以将班级拆分为界面部分和实现部分。 接口部分是公共的,实现部分可以有公共构造函数。 但是,这意味着您必须使用虚拟继承。