Помогает ли шаблон дизайна pimpl компиляции? - PullRequest
0 голосов
/ 31 мая 2019

Согласно этой статье , он пытается объяснить проблему, которую pimpl решает, но я вижу, что в примере, который он показал, нет никаких проблем.

В нем говорится, что: «есть проблема с нижеуказанным дизайном (которая может быть серьезной или нет, в зависимости от того, сколько клиентов у Fridge). Поскольку Fridge.h #include Engine.h, любой клиент Fridgeкласс косвенно #include класс Engine. Таким образом, когда класс Engine изменяется, все клиенты Fridge должны перекомпилировать, даже если они не используют Engine напрямую. "

#include "Engine.h"

class Fridge
{
public:
   void coolDown();
private:
   Engine engine_;
};
#include "Fridge.h"

void Fridge::coolDown()
{
   /* ... */
}

Но, я вижу, что если Engine изменен, Fridge должен измениться в соответствии с.И поскольку Fridge изменится, Client, который использует Fridge, также будет изменен.
Другими словами, если Engine будет изменен, то Fridge следует перекомпилировать и в соответствии с этим, Client также будет перекомпилирован.В этом случае Client изменено, потому что Fridge изменено НЕ, потому что Engine изменено.
Таким образом, в этой ситуации нет проблемы косвенного обращения.

Я прав?если да, то, что на самом деле проблема решает pimpl?если нет, можете ли вы привести пример косвенного объяснения, который объясняет эту проблему?

1 Ответ

3 голосов
/ 31 мая 2019

Другими словами, если 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 отсутствует.нарушение.

...