从静态库中公开一个类

发布于 2024-12-09 18:37:46 字数 313 浏览 0 评论 0原文

我正在开发一个解析器库,在其中解析数据并将其存储在不同的数据结构中。该库的设计是这样的,它将具有 DataProvider、Parser 和 DataStore 类。 DataStore 是DataProvider 类的成员。消费者需要调用DataProvider中的函数来解析文件并从库中检索数据。

现在,如果我公开 DataProvider 类,那么我还需要公开 DataStore 类,该类向消费者提供实现细节。公开 DataProvider 类的函数的替代方法是什么?我是否应该公开 LoadFile、GetRecords 等函数并在 cpp 内全局创建 DataProvider 对象?

I am developing a parser library where i parse data and store it in different data structures. The design of the library is such that it will have a DataProvider, Parser and DataStore class. The DataStore is a memebr of DataProvider class. The consumer needs to call the functions in the DataProvider to parse the file and to retrieve the data from the library.

Now if i expose the DataProvider class then i need to expose the DataStore class also which gives the implementation details to the consumer. What is the alternative way of exposing the functions of the DataProvider class? Should i expose functions like LoadFile, GetRecords and create the DataProvider object globally inside the cpp?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

唔猫 2024-12-16 18:37:46

如果用户不必直接使用DataStore,则最好不要公开它。您可以通过创建一个“接口”来实现这一点 - 抽象 DataProvider 仅包含公共纯虚函数。在内部,有一个 DataProviderImp ,它将继承自 DataProvider,并包含实际实现中所需的所有定义和成员。

让用户只使用抽象类。这样,您只需将最少的依赖项拖到 API 中。

If the user doesn't have to use the DataStore directly, it should better not be exposed. You can achieve that by creating an "interface" - abstract DataProvider with only public pure virtual functions. Internally, have a DataProviderImp which will inherit from DataProvider, and contain all the required definitions and members that are part of the actual implementation.

Let the user work only with the abstract class. This way, you drag only the minimal dependencies into your API.

挽袖吟 2024-12-16 18:37:46

首先尽量减少需要在标头中公开的信息,因此尽可能使用前向声明、引用和指针(因此只需要前向声明),并尝试使用 PIMPL 习惯用法来隐藏实现。

接下来,您可以构建另一个类,它是系统的外观,它包装了函数的入口点,并使用间接方法来访问包含的元素(例如可从外部访问的数据元素),例如句柄和索引。

Firstly minimize the information that needs to be disclosed in the headers, so use forward declarations, references and pointers where possible (so only a forward declaration is needed), and try to use a PIMPL idiom to hide the implementation.

Next you could build another class that is a facade to the system, which wraps up the entry points to the functions, and use indirect methods to access contained elements (such as data elements accessible externally), such as handles and indexes.

猫性小仙女 2024-12-16 18:37:46

如果担心外部用户可能创建自己的 DataStore 对象,并在 DataProvider 上下文之外使用它们,并且他们抱怨您的库不起作用,那么有一个简单的解决方案和一些不太容易的解决方案。

简单的解决方案:记录 DataProvider 是您的库的外部接口。这是 C++ 标准库和 Boost 中采用的解决方案。 std::map 的接口是头文件

。该标头 #includes 的实现文件以及

及其附属标头创建的基础数据类型与您无关。您应该只使用 std::map 公共接口。使用内部数据类型,您就会进入未定义行为的世界。像 // 类 DataStore 仅供内部使用的注释。使用它,你就会被解雇。可以起到相当强大的威慑作用。

不依赖上述内容的解决方案:通过在 DataProvider 中定义这些子类(例如,您将拥有类 DataProvider::DataStore)并创建这些类来隔离这些子类定义私有/受 DataProvider 保护。另一种方法是将 DataStore 中的所有内容设为私有/受保护,并使 DataProvider 成为友元类。

由于您正在提供静态库和标头,因此无论您多么努力地尝试将它们隔离开来,总会有一些令人讨厌的黑客手段来获取您的底层数据和方法。在某些时候,“这仅供内部使用。别戴脏手套!”方法有相当多的优点。

If the concern is that external users might create their own DataStore objects, use them outside the context of a DataProvider, and them complain that your library doesn't work, there is an easy solution and some not so easy solutions.

The easy solution: Document that DataProvider is the external interface to your library. This is the solution employed in the C++ standard library, and in Boost. The interface to std::map is the header file <map>. The implementation files that that header #includes, and the underlying data types that <map> and its subsidiary headers create are none of your business. You should only use the std::map public interfaces. Use internal data types and you're off into the world of undefined behavior. Comments like // The class DataStore is for internal use only. Use it and you will be fired. can be quite a powerful deterrent.

A solution that does not rely on the above: Wall off those subsidiary classes by defining them inside DataProvider (e.g., you will have class DataProvider::DataStore) and making those class definitions private/protected to DataProvider. Another approach is to make everything in DataStore private/protected, and make DataProvider a friend class.

Since you are delivering a static library and headers, there will always be some nasty hackish means to get at your underlying data and methods no matter how hard you try to wall them off. At some point, the "This is for internal use only. Keep your dirty mitts off!" approach has quite a bit of merit.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文