ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
18 июля
636219 Топик полностью
fk0, легенда (05.12.2015 15:52, просмотров: 91) ответил SciFi на Прекомпилированные заголовки имеют смысл только в цэ++, так как там в моде инклудить мегабайты всякой хрени, которые действительно грузят компилятор. В цэ ничего подобного не бывает, инклуды пролетают за миллисекунды.
Проблема не в моде, проблема в C++. C++ не позволяет отделить интерфейс от реализации: ты должен класс описать в одном месте -- значит в хедере, чтоб его могли использовать другие. И в описании класса должны быть перечислены все его члены (функции, переменные) -- потому, что иначе sizeof не вычислить и память не аллоцировать под автоматическую переменную экземпляра класса. А так же в классе нужно сразу определить все вложенные в его namespace типы (что они есть, сами определения типов потребуются только при их использовании в реализации). Нельзя как в pascal определить интерфейс в .h файле, и отдельно определить класс его реализующий со своими внутренностями в отдельном .cpp файле (можно через абстрактный базовый класс, но это отдельная история). Это всё ведёт к тому, что при компиляции каждого c++ файла почти все .h файлы программы включаются друг в друга. Это реально большая беда языка C++. Как из этого выкручиваются: как сказано выше, абстрактный базовый класс, определяющий только интерфейс, и унаследованный класс определяющий его реализацию со своими подробностями спрятанными в .cpp файле. Нужна таблица виртуальных функций (ссылка на неё) спрятанная в каждый объект класса. И sizeof унаследованного класса не вычислим, нужна фабрика классов (функция аллоцирующая объект в куче и возвращающая указатель) вместо прямого использования конструктора -- нельзя аллоцировать на стеке, что большой минус. Или используют "pimpl-идиому", что по-моему являет пример жуткого говнокода и нужно только в случае, когда использование виртуальных функций неприменимо (например, если нужно объекты передавать между процессами -- ссылка на таблицу функций при этом для второго процесса окажется не валидной, т.к. в нём по другим адресам код загружен). Опять же нужна фабрика классов, и ещё промежуточный класс идиотского вида (google pimpl) в котором легко налажать и выглядит глупо. Есть ещё разные полумеры, как отделить интерфейс от реализации, смотреть в литературе или интернете. Мне кажется странным, что не широко используется такой метод (он, конечно, не такой универсальный, но кажется проще в реализации): в .h файле определяется интерфейс (класс), опять же фабрика классов, но ни виртуальных функций не используется, ни pimpl -- а попросту .cpp файл содержащий реализацию включается на стадии линковки (в Makefile) только один из нескольких (нужный для данной аппаратной платформы, например). По сути то же, что и pimpl, но нет нужды писать основной класс, перенаправляющий все методы в реализацию. Конечно это не годится для случая, когда нужно иметь несколько разных реализаций (разными классами) интерфейса одновременно, потому не так универсально. И если класс может принципиально существовать только в одном экземпляре, или более того, состоит только из статических функций, я честно говоря не понимаю, почему не предпочитают использовать namespaces вместо класса. По-моему это какое-то тяжёлое наследие java-программирования. Да, конечно namespace не даёт возможность ограничить доступ к внутренним функциям и переменным, что потенциально позволяет наговнокодить в обход определённого интерфейса. Но по-моему это не является принципиальной проблемой (а то и с классом нахитрить можно, если очень неймётся). И если код не размазан по нескольким файлам, то анонимный namespace решает вопрос изоляции капитально (как static в C). Ещё шаблоны с namespace нельзя использовать, но я так же не уверен, зачем это нужно, чтоб всё было в шаблонах. Да, но возвращаясь к топику, предкомпилированные хидеры здесь сильно не помогут (их перекомпилировать часто придётся).
[ZX]