访问私有实现成员而不暴露它们(C ++)

时间:2015-12-01 16:11:13

标签: c++ design-patterns implementation friend

我有两个类,Repository和Search。存储库封装了用于存储和管理内容的逻辑,而搜索封装了用于搜索内容的逻辑,还需要访问存储库对象,以便读取内容。

通常,我想将Repository类的功能划分为public,该类的每个用户都可以访问,而private则只能在内部使用。我遇到的问题是Search类应该可以访问Repository的私有功能,但是因为Repository对象将从外部传递给Search对象,所以它只会公开公共功能。

我现在这样做的方式是,Repository使用pimpl习惯用法来隐藏实现细节,并且我将Search声明为朋友,因此它可以在实现代码中使用私有功能。

Repository.h:

// Forward declaration of implementation class
class RepositoryImpl;

// Forward declaration of friend class
class Search;

class Repository
{
public:
   // public interface

private:
   RepositoryImpl* pImpl;
};

Search.h

class Search
{
public:
   void searchRepository(Repository* repo);
};

Search.cpp

void Search::searchRepository(Repository* repo)
{
   repo->pImpl->someHiddenMethod();
}

这显然只是给予和想法,所以它在实际功能方面没有任何意义,但我希望它能很好地解释我正在努力解决的问题。 有些人可能会说在这里使用朋友非常好,但对我来说感觉有点“hacky”所以如果有更好的方式(一些设计模式)去做,我想用。

我也不想将这些类合并为一个(尽管它似乎是一个好主意),因为它引入了一些不可接受的限制。基本上我希望能够拥有一个搜索引擎,能够使用多个存储库。如果能够以干净的方式实现目标,我仍然可以完成对课程的重新设计。

非常感谢你。

2 个答案:

答案 0 :(得分:2)

您可以创建Searchable使用的SearchRepositoryImpl实施的界面。然后,向Repository添加一个公共接口,该接口返回pImpl成员但缩小到Searchable接口。

执行上述操作的优点是您不必将RepositoryImpl的所有实现细节公开到Search,这使您的方法感觉像是黑客。

// in Search.h
class Searchable
{
    friend class Search;
    virtual void internal_method () = 0;
    //...
protected:
    virtual ~Searchable () = default;
};

// in Repository.cpp
class RepositoryImpl : public Searchable //...
{
    //...
};

Searchable * Repository::searchable () { return pImpl; }

// in Search.cpp
void Search::searchRepository(Repository* repo)
{
   repo->searchable()->internal_method();
}

答案 1 :(得分:0)

可能您不需要访问存储库实现细节。

搜索应该能够在Repository上工作而不了解Repository的详细信息,例如,如果您正在使用STL容器和其元素的迭代器。

因此,您可能应该修改Repository接口以授予对底层元素的访问权限(例如将begin()和end()添加到公共接口)并让Search类使用这些“句柄”。 如果Search足够通用以便与其他类型的“迭代器”一起使用,那就更好了。

P.S。我本来希望将其添加为注释,因为这些信息不能准确得出明确的答案。但由于声誉不佳,我不被允许。