Другими словами, если Engine
изменяется, то Fridge
следует перекомпилировать.
Это правильно, но если быть более точным: функции, которые зависят от Engine
, необходимо перекомпилировать.
, и в соответствии с этим, клиент также будетперекомпилировано.
Нет.Тот факт, что модуль перевода, реализующий функции-члены Fridges, перекомпилирован, не означает, что клиенты Fridges необходимо будет перекомпилировать.Только если Fridge.h изменен, нужно перекомпилировать единицы перевода, включая этот заголовок.
Но я вижу, что если Engine
изменен, Fridge
должен измениться соответственно.И поскольку Fridge
изменится, Client
, который использует Fridge
, также будет изменен.
Это проблема, которая есть в показанной реализации.Если вместо этого Engine
было скрыто с помощью PIMPL, то модификация Engine
не подразумевала бы модификацию класса Fridge
.Это подразумевает только модификацию реализации функций-членов Fridge
, которые зависят от Engine
, и эти реализации скрыты PIMPL.
Если вы посмотрите на версию PIMPL Fridge.h
,вы заметите, что он не использует класс Engine
напрямую и, следовательно, не включает Engine.h
.Поэтому изменение Engine.h
не вызывает изменений в Fridge.h
и, следовательно, не вызывает изменений в единицах перевода, которые включают Fridge.h
:
class Fridge
{
public:
Fridge();
~Fridge();
void coolDown();
private:
class FridgeImpl;
FridgeImpl* impl_;
};
Можете ли вы привести пример того, как НЕ перекомпиляция модуля перевода клиента после изменения Engine.h вызовет проблему?
Если один модуль перевода использует определение Engine
, отличное от другого модуля перевода, топрограмма нарушает одно правило определения, и поведение будет неопределенным.
В PIMPL единицы перевода, включающие Fridge.h
, вообще не используют класс ODR Engine
, поэтому вероятность ODR отсутствует.нарушение.