2009-11-08 2 views
11

Что лучше всего подходит для открытого API C++?Что лучше всего подходит для C++ Public API?

Я работаю над проектом C++, который имеет несколько пространств имен, каждый с несколькими объектами. Некоторые объекты имеют одинаковые имена, но находятся в разных пространствах имен. В настоящее время каждый объект имеет свой собственный .cpp-файл и .h-файл. Я не уверен, как это сказать ... Было бы целесообразным создать второй файл .h, чтобы открыть только публичный API? Должны ли они быть .h-файлом для пространства имен или для объекта или какой-либо другой области? Что может быть лучшей практикой для создания публичных API для библиотек C++?

Спасибо за любую помощь, Chenz

ответ

2

Иногда удобно иметь один класс во всех файлах .cpp и .h и иметь иерархию пространства имен в качестве иерархии каталогов.
Например, если у вас есть этот класс:

namespace stuff { 
    namespace important { 
    class SecretPassword 
    { 
     ... 
    }; 
    } 
} 

, то он будет в двух файлах:

/stuff/important/SecretPassword.cpp 
/stuff/important/SecretPassword.h 

другой возможный макет может быть:

/src/stuff/important/SecretPassword.cpp 
/include/stuff/important/SecretPassword.h 
+0

Но когда все вместе складывается в одной .so-библиотеке, я могу распространять структуру каталогов с глубоким включением? Chenz –

+0

Я имею в виду .so или .dll –

+0

@Crazy Chenz, да, это возможность. Вот как это делается в ядре Linux, например, и в некоторой степени. – shoosh

1

Я бы сказал, что это лучше всего решать вам, и тип «библиотеки» это.

Ваш API предоставляет одно «действие»? или обрабатывает только один абстрактный «Тип данных»? примерами для этого были бы zlib и libpng. Оба имеют только один заголовок, который дает все, что необходимо для выполнения функций библиотек.

Если ваша библиотека представляет собой коллекцию несвязанных (или даже связанных) классов, которые делают или нет, та же самая цель, то предоставляйте каждому подмножеству свой собственный заголовок. Основным примером этого будет повышение.

0

Большой отклик LiraNuna.

Предоставляете ли вы API для приложения или библиотеки?

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

Библиотека, как правило, раскрывает объекты, которые могут быть повторно использованы. В этом случае, вообще говоря, ваш API - это просто общедоступные методы в файле заголовка.

+0

«Отличный ответ LiraNuna». Так проголосуйте? :( – LiraNuna

+0

Ха-ха, я вообще отвечаю, тогда голосую;) – Josh

+0

У меня есть основная библиотека, которую нужно повторно использовать, а затем несколько пространств имен, содержащих все объекты и помощники для приложений, которые используют ядро. Ядро - это то, что я хочу «разоблачить» публичный API. –

2

G'day,

Одно предложение взглянуть на С ++ идиомы Handle-Body, иногда известный как Чеширский кот. Вот James Coplien's original paper, содержащий идиому.

Это хорошо известный метод развязки общедоступных API-интерфейсов от реализаций.

НТН

+3

Другое название этой идиомы (которое, я думаю, стало более популярным, но, возможно, я ошибаюсь) - это «pimpl idiom» - указатель на реализацию. –

+0

@michael, ты прав. это имя также добавлено, но довольно недавно iirc. ручкой/телом было оригинальное имя, которое Коуп дал в своей книге 1991 года «Расширенные стили и идиомы программирования на С ++»

1

Вот что я привык делать:

«Некоторые объекты имеют одинаковые имена, но находятся в разных пространствах имен»

Вот почему существует пространство имен.

«было бы целесообразно создать второй файл .h выставить только открытый API?»

Вы всегда должны подвергать только открытый API. Но что значит публиковать открытый API? Если бы тогда были только заголовки, поскольку публичный API полагался на частный API, частный API был бы включен публичным API в любом случае. Чтобы публиковать общедоступные API-метки публичных функций/классов с макросом (который в случае Windows экспортирует публичные функции в таблицу символов и, вероятно, вскоре будет принят системами Unix). Поэтому вы должны определить макрос, например MYLIB_API или MYLIB_DECLSPEC, просто проверьте некоторые существующие библиотеки и документацию MS declspec. Достаточно, обычно непубличный API будет храниться в подкаталогах, чтобы он не посещал пользователя библиотеки.

«Должны ли они быть файлом .h для пространства имен или для какого-либо объекта или какой-либо другой области?»

Я предпочитаю Java-стиль, один public класс за заголовок. Я обнаружил, что листы, написанные таким образом, намного чище и читабельны, чем те, которые смешивают имена файлов и структуры. Но бывают случаи, когда я торможу это правило, особенно когда дело касается шаблонов. В таких случаях я даю сообщение #warning, чтобы не включать заголовок напрямую и тщательно объяснять в комментариях, что происходит.

+0

«Но что значит публиковать открытый API?» Я думал о том, как воспроизводить все заголовки для распространения без их личных методов и варсов. –

+0

Я имею в виду ... без их личных прототипов методов и частных объявлений переменных. –

+0

Это не имеет смысла ИМО. На самом деле это сделало бы вашу библиотеку сложнее понять и поддерживать. Если кто-то должен продлить ваш класс, он, вероятно, захочет увидеть всю структуру класса, а не только общественные и защищенные члены. Определение класса должно быть обязательно сохранено в одном заголовке. – doc

0

Я согласен с тем, что сказал doc - один класс в файле. 99,9% времени!

Также рассмотрите, какие имена файлов использовать. Как правило, плохая идея иметь несколько заголовков с одинаковыми именами в разных каталогах, хотя классы, которые они содержат, вполне могут находиться в разных пространствах имен.

Особенно, если это общедоступный API, вы, вероятно, не можете контролировать то, что включает в себя пути, определенные пользователем вашей библиотеки, поэтому сборка может оказаться неправильной. Тонкая настройка включенных дорожек определенно не быть решением, которое я бы рекомендовал!

Мы используем соглашение об именах Namespace-Class.h, чтобы явно идентифицировать классы в файлах.

+0

Могу ли я спросить, что вы делаете с длинными пространствами имен? Допустим, у вас есть класс mylib :: graphics :: formats :: JpegLoader. Заголовок заголовка Mylib_Graphics_Formats-JpegLoader.h? Это несколько разочаровывает использование таких заголовков. ИМО - лучший способ избежать случайных включений - заставить ваше имя библиотеки быть частью пути включения, в нашем примере включение будет выглядеть так: #include . Пока у вас «mylib» в <> все будет хорошо. – doc

+0

К счастью, наши пространства имен не вложены настолько глубоко; только одно пространство имен, редко 2, так что это не так уж плохо. Каким образом это расстраивает - и в чем разница между '#include 'Mylib-Graphics-Formats-JpegLoader.h" или '#include" mylib/graphics/formats/JpegLoader.h "? Вам все равно придется набирать полный «путь»? –

+0

Возможно, у вас есть #include если вы сохраняете структуру каталогов в отношении пространств имен, а на моей стороне это будет . Если вы храните все в одном каталоге, то ОК. – doc

Смежные вопросы