Разоблачение класса из статической библиотеки - PullRequest
1 голос
/ 13 октября 2011

Я занимаюсь разработкой библиотеки синтаксического анализатора, в которой я анализирую данные и сохраняю их в разных структурах данных.Конструкция библиотеки такова, что она будет иметь классы DataProvider, Parser и DataStore.DataStore - это элемент класса DataProvider.Потребитель должен вызвать функции в DataProvider для анализа файла и получения данных из библиотеки.

Теперь, если я предоставляю класс DataProvider, мне нужно также предоставить класс DataStore, который предоставляет детали реализации потребителю.Каков альтернативный способ представления функций класса DataProvider?Должен ли я предоставить такие функции, как LoadFile, GetRecords и создать объект DataProvider глобально внутри cpp?

Ответы [ 3 ]

1 голос
/ 13 октября 2011

Если пользователь не должен использовать DataStore напрямую, его лучше не подвергать воздействию. Вы можете добиться этого, создав «интерфейс» - абстрактный DataProvider только с общедоступными чисто виртуальными функциями. Внутренне, иметь DataProviderImp, который будет наследоваться от DataProvider, и содержать все необходимые определения и члены, которые являются частью фактической реализации.

Разрешить пользователю работать только с абстрактным классом. Таким образом, вы перетаскиваете в API только минимальные зависимости.

0 голосов
/ 13 октября 2011

Если проблема заключается в том, что внешние пользователи могут создавать свои собственные DataStore объекты, используйте их вне контекста DataProvider, и они жалуются, что ваша библиотека не работает, есть простое решение, а некоторые нет.Простые решения.

Простое решение: Документируйте, что DataProvider - это внешний интерфейс вашей библиотеки.Это решение используется в стандартной библиотеке C ++ и в Boost.Интерфейс для std::map является заголовочным файлом <map>.Файлы реализации, которые этот заголовок #includes, и базовые типы данных, создаваемые <map> и его вспомогательные заголовки, не относятся к вашему бизнесу.Вам следует использовать только общедоступные интерфейсы std::map.Используйте внутренние типы данных, и вы попадете в мир неопределенного поведения.Такие комментарии, как // The class DataStore is for internal use only. Use it and you will be fired., могут быть довольно мощным сдерживающим фактором.

Решение, которое не опирается на вышеприведенное: отгородите эти вспомогательные классы, определив их внутри DataProvider (например, вы получите класс DataProvider::DataStore) и сделать эти определения классов приватными / защищенными для DataProvider.Другой подход состоит в том, чтобы сделать все в DataStore приватным / защищенным и сделать DataProvider классом друга.

Поскольку вы предоставляете статическую библиотеку и заголовки, всегда найдутся некоторые неприятные хакерские средства, чтобы добраться доваши основные данные и методы, независимо от того, как сильно вы пытаетесь оградить их.В какой-то момент подход «» предназначен только для внутреннего использования. Держите грязные руки подальше! »имеет немало достоинств.

0 голосов
/ 13 октября 2011

Во-первых, сведите к минимуму информацию, которая должна быть раскрыта в заголовках, поэтому по возможности используйте предварительные объявления, ссылки и указатели (поэтому требуется только предварительное объявление) и попробуйте использовать идиому PIMPL, чтобы скрыть реализацию.

Затем вы можете создать другой класс, который является фасадом системы, который оборачивает точки входа в функции и использует косвенные методы для доступа к содержащимся элементам (таким как элементы данных, доступные извне), таким как дескрипторы и индексы..

...