Зачем ставить объявление класса и определение в двух отдельных файлах на С++?
Мне просто интересно, в чем смысл разделения классов на файлы .h и .cpp? Это затрудняет редактирование, и если ваш класс не будет скомпилирован в .lib или .dll для внешнего использования, какая точка?
Изменить:
Причина, по которой я спрашиваю, заключается в том, что библиотеки Boost помещают все в файл .hpp(в любом случае, большинство библиотек), и я хотел знать, почему он разделен в большинстве других кодов, которые я вижу.
Ответы
Ответ 1
С++ имеет что-то, называемое Правилом одного определения. Это означает, что (исключая встроенные функции) определения могут появляться только в одном блоке компиляции. Поскольку файлы заголовков С++ просто "копируются и вставляются" в каждый включенный файл, теперь вы помещаете определения в несколько мест, если вы просто поместите определения в файлы заголовков.
Конечно, вы можете сказать, почему бы не сделать все встроенным. Ну, если компилятор уважает ваше встроенное предложение, код для длинных функций будет реплицироваться на каждом сайте вызова, делая ваш код чрезмерно большим и, возможно, вызывая проблемы с кешем, и всевозможные ненужные вещи.
С другой стороны, если компилятор не прослушивает вас и ничего не делает, теперь у вас есть 2 проблемы: 1) вы не знаете, какая единица перевода получила определения ваших классов, и 2) компилятор все равно приходится пробираться через свои определения каждый раз, когда вы # включаете их. Более того, нет простого способа убедиться, что вы случайно не определили один и тот же метод дважды, в двух разных заголовках, по-разному.
Вы также получаете проблему с круговой зависимостью. Чтобы класс вызывал другой метод класса, этот класс должен быть объявлен первым. Поэтому, если 2 классам необходимо вызывать методы друг друга, каждый из них должен быть объявлен до того, как он будет определен. Невозможно сделать это с помощью деклараций и определений в одном файле.
Действительно, это как язык и парсер были построены. Это боль, но вам просто нужно иметь дело с ней.
Ответ 2
Boost не строит весь код; он встраивает определения шаблонов для классов, которые он ожидает от своих пользователей, например, shared_ptr. Во многих библиотеках есть разделы, которые необходимо скомпилировать отдельно, например boost:: serialization и program_options.
Вложение может иметь серьезные негативные последствия по мере увеличения размера вашей базы кода. Это увеличивает связь между вашими компонентами, не говоря уже о том, чтобы укусить время компиляции (что усиливается по многим другим причинам:). Фактически, у всех ваших переводческих единиц была бы почти полная копия программы, и небольшое изменение заставило бы вас перестроить/повторить все. В некоторых проектах это может занять много-много часов.
Я никогда не замечал, что это труднее редактировать; по моему опыту, это облегчает из-за четкого разделения интерфейса и реализации, и я знаю, какой файл искать, чтобы найти то, что я ищу.
Ответ 3
Хорошо, одним из преимуществ наличия кода является то, что он сокращает время компиляции.
Скажем, у вас есть эти файлы в вашем проекте:
Если у вас уже есть a.cpp, скомпилированный в файл объекта ao, то если вы включите ah в b.cpp, компиляция должна Быстрее, потому что парсеру не придется иметь дело со всем объявлением/определением a.
Ответ 4
Потому что даже внутри вашей DLL другие классы будут использовать ваш класс. Эти файлы должны видеть объявление класса во время компиляции, включая .h. Они не должны видеть это определение или будут несколько определений функций класса.
Ответ 5
Ваше редактирование re: Boost делает важное различие. Классы шаблонов почти всегда определяются в заголовках из-за того, как компилятор и компоновщик работают в текущем стандарте С++. Вы найдете, что большинство библиотек шаблонов (а не только Boost) реализованы в заголовочных файлах по той же причине.
Ответ 6
Потому что в большинстве случаев вы захотите использовать класс где-то помимо файла, в котором вы его реализуете. Если вы делаете всю программу в одном файле, вам не требуется разделение.
Вы почти никогда не хотите писать программу на С++ в одном файле.
Ответ 7
В С++ отдельная компиляция модулей кода (.c или .cpp) требует, чтобы прототипы функций были определены до использования. Если вы хотите использовать классы или методы, определенные где-то в другом месте, вам нужно импортировать файлы .h, чтобы получить их определение. В конце, компоновщик гарантирует, что все promises, сделанные в файлах .h, могут быть выполнены всеми файлами c/cpp.
Кроме того, он позволяет создавать целые фреймворки, такие как boost только путем определения файлов .h.
Ответ 8
См. http://www.gnu.org/software/m68hc11/examples/stdio_8h-source.html
Обратите внимание на шаблон:
#ifndef _STDIO_H_
....
#define _STDIO_H_
....
#endif /* _STDIO_H_ */
Приветствия. Кит.