Разве невозможно написать библиотеку только для заголовков? - PullRequest
14 голосов
/ 20 сентября 2010

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

Для целей этого вопроса давайте проигнорируем статичные вещи:)

Ответы [ 4 ]

7 голосов
/ 20 сентября 2010

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

5 голосов
/ 20 сентября 2010

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

Может потребоваться несколько уловок, но их можно просмотреть.

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

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

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

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

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

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

2 голосов
/ 20 сентября 2010

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

#include <header1>
#include <header2>

тогда некоторые варианты этого будут:

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

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

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

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

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

1 голос
/ 08 сентября 2014

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

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

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

...