2010-09-20 2 views
14

Есть ли такой шаблон зависимостей, что невозможно хранить все только в заголовочных файлах? Что делать, если мы применяем правило только одного класса для каждого заголовка?Невозможно ли написать библиотеку только для заголовков?

Для целей этого вопроса, давайте игнорировать статические вещи :)

+0

Что делать, если библиотека без заголовков A зависит от библиотеки DLL? Или это исключено из последнего предложения? Конечно, вы всегда можете переопределить его как заголовки, так что, возможно, это невозможно. – Skurmedel

+0

вам нужно поговорить с другими языками? – Anycorn

+0

@Skurmedel: C++ не содержит DLL-подобных объектов, поэтому все, что будет реализовано, будет реализовано. Я сомневаюсь, что это имеет какое-то значение. –

ответ

7

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

+4

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

+4

Хотя он делает библиотеку тривиальной для использования и помогает компилятору при его оптимизации. – GManNickG

+2

@GMan: зависит от компилятора. IIRC, как GCC, так и MSVC, теперь имеют средства генерации временного кода связи для создания релизов, что устраняет большинство (если не все) потенциальных различий в производительности. –

2

Правило одного класса в заголовке не имеет смысла. Если это не работает:

#include <header1> 
#include <header2> 

тогда некоторые вариации этой воли:

#include <header1a> 
#include <header2> 
#include <header1b> 

Это может привести к менее одного класса в заголовке, но вы всегда можете использовать (недействительными *) и слепков и встроенные функции (в этом случае «inline», вероятно, будет должным образом проигнорирован компилятором). Таким образом, вопрос, как мне кажется, может быть уменьшены до:

class A 
{ 
// ... 
void *pimpl; 
} 

Возможно ли, что частная реализация, Pimpl, зависит от объявления? Если это так, то pimpl.cpp (как заголовок) должен предшествовать и следовать A.h. Но так как вы всегда можете использовать (void *) и casts и встроенные функции в предыдущих заголовках, это можно сделать.

Конечно, я мог ошибаться. В любом случае: Ick.

+2

Я не понимаю, почему кто-то будет использовать какой-либо класс pimpl в библиотеке только заголовка, учитывая, что идея, что идиома pimpl заключается в том, чтобы разбить вещи на отдельные единицы перевода ... –

+0

Согласен, нет смысла пытаться делая библиотеку только заголовка, когда реализация явно не подходит для нее. Возможно, это не то, что вы имели в виду;) Я поднял pimpl как инструмент, чтобы доказать, что это можно сделать (используя слово «доказать» очень свободно). – paul

5

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

Для этого может потребоваться несколько трюков, но они могут быть пересмотрены.

  1. Вам нужно будет сохранить разницу заголовков и источников, когда вам нужно сломать цикл зависимостей, даже несмотря на то, что эти два файла будут на практике заготавливаться.
  2. Свободные функции (не шаблоны) должны быть объявлены встроенными, компилятор не может их встраивать, но если они объявлены, они не будут жаловаться на то, что они были переопределены, когда клиент построил свою библиотеку/исполняемый файл.
  3. Данные общего доступа (глобальные переменные и статические атрибуты класса) должны эмулироваться с использованием локального статического атрибута в методах функций/классов. На практике это имеет мало значения для вызывающего абонента (просто добавляет ()). Обратите внимание, что в C++ 0x это становится предпочтительным, потому что он гарантированно защищен потоком, сохраняя при этом защиту от фиаско порядка инициализации, до тех пор ... он не является потокобезопасным;)

Уважение к ним 3 точки, я считаю, что вы сможете написать полноценную библиотеку только для заголовков (кто-нибудь видит что-то еще, что я пропустил?)

Ряд библиотек Boost использовали подобные трюки только для заголовков, хотя их код был не полностью шаблон.Например Asio делает очень сознательно и предлагает альтернативу с помощью флагов (см release notes for Asio 1.4.6):

  • клиентов, которые нуждаются только пару функций не нужно беспокоиться о строительстве/ссылки, они просто захватить то, что они нуждаются в
  • клиентов, которые полагаются на нем немного больше или хотят сократить время компиляции, предлагается возможность создавать собственную библиотеку Asio (с их собственными наборами флагов), а затем включать «легкие» заголовки

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

Примечание: Я задаюсь вопросом, может ли быть встраиваемыми static функции, я предпочитаю использовать анонимные пространства имен я так никогда не смотрел на него ...

+0

re # 1: Вы можете набросать сценарий, где это необходимо? Я попытался представить один, но не мог придумать ничего, что не может быть решено путем перемещения встроенных определений функций за всеми необходимыми определениями. – sbi

1

В моей долгой карьеры я не попадались зависимости шаблон, который запрещает реализацию только заголовка.

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

Это не означает, что вы ДОЛЖНЫ всегда стремиться к библиотекам только для заголовков. Хорошо, как и они, они должны быть зарезервированы для шаблона и встроенного кода. Они НЕ ДОЛЖНЫ включать существенные сложные вычисления.

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