Отже, мені цікаво, що ця методика справді використовується на практиці? Чи варто використовувати його скрізь або з обережністю?
Звичайно, використовується. Я використовую це у своєму проекті, майже в кожному класі.
Причини використання ідіоми PIMPL:
Бінарна сумісність
Коли ви розробляєте бібліотеку, ви можете додавати / змінювати поля, XImplне порушуючи бінарної сумісності з вашим клієнтом (це може означати збої!). Оскільки двійковий макет Xкласу не змінюється, коли ви додаєте нові поля до Ximplкласу, безпечно додавати нову функціональність у бібліотеку в оновленнях незначних версій.
Звичайно, ви можете також додати нові публічні / приватні невіртуальні методи до X/ XImplбез порушення бінарної сумісності, але це нарівні зі стандартною технікою заголовка / реалізації.
Приховування даних
Якщо ви розробляєте бібліотеку, особливо фірмову, може бути бажано не розкривати, які інші бібліотеки / методи реалізації використовувались для реалізації публічного інтерфейсу вашої бібліотеки. Або через проблеми інтелектуальної власності, або через те, що ви вважаєте, що користувачі можуть спокусити зробити небезпечні припущення щодо впровадження або просто порушити інкапсуляцію, використовуючи жахливі прийоми кастингу. PIMPL це вирішує / пом’якшує.
Час компіляції
Час компіляції скорочується, оскільки потрібно лише Xперебудовувати вихідний (імплементаційний) файл, коли ви додаєте / видаляєте поля та / або методи до XImplкласу (який відображає додавання приватних полів / методів у стандартній техніці). На практиці це звичайна операція.
За допомогою стандартної техніки заголовка / реалізації (без PIMPL), коли ви додаєте нове поле до Xкожного клієнта, який коли-небудь виділяє X(або в стеці, або в купі), потрібно перекомпілювати, оскільки він повинен регулювати розмір розподілу. Ну, і кожен клієнт, який ніколи не виділяє X, також повинен бути перекомпільований, але це просто накладні витрати (результат коду на стороні клієнта буде однаковим).
Більше того, стандартне розділення заголовка / реалізації XClient1.cppпотрібно перекомпілювати навіть тоді, коли приватний метод X::foo()був доданий Xта X.hзмінений, хоча, XClient1.cppможливо, не можна викликати цей метод з причини інкапсуляції! Як і вище, вона чиста накладні витрати і пов'язана з тим, як працюють системи побудови C ++ у реальному житті.
Звичайно, рекомпіляція не потрібна, коли ви просто змінюєте реалізацію методів (оскільки ви не торкаєтесь заголовка), але це нарівні зі стандартною технікою заголовка / реалізації.
Чи рекомендується цей прийом використовувати у вбудованих системах (де продуктивність дуже важлива)?
Це залежить від того, наскільки потужна ваша мета. Однак єдина відповідь на це питання: вимірюйте та оцінюйте те, що ви отримуєте та втрачаєте. Також врахуйте, що якщо ви не публікуєте бібліотеку, яку клієнти повинні використовувати у вбудованих системах, застосовується лише перевага часу компіляції!
struct XImpl : public X. Мені це здається більш природним. Чи є якась інша проблема, яку я пропустив?