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

boost::make_shared<DirectoryIteratorImpl>DirectoryIteratorは の友人であるため、を呼び出すことができるようです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 に答える