Мешает ли вам компиляция шаблона проектирования pimpl?

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

В нем говорится, что: «Существует проблема с приведенным ниже дизайном (которая может быть серьезной или нет, в зависимости от того, сколько клиентов у Fridge). Поскольку Fridge.h #includes Engine.h, любой клиент класса Fridge будет косвенно включать класс 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? если нет, можете ли вы привести пример косвенности, объясняющий эту проблему?

Шаблон проектирования pimpl, правильно реализованный (который этот код явно не пытается сделать), решает проблему перекомпиляции любого потребитель для Fridge.h при изменении на Engine.h. Правильный pimpl не будет включать Engine.h в Fridge.h, поэтому изменения в Engine.h не повлияют на потребителей Fridge.h, за исключением один : Fridge.cpp.

WhozCraig 31.05.2019 17:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

In other words, If Engine get modified, then Fridge should be recompiled.

Это правильно, но если быть более точным: функции, зависящие от Engine, необходимо перекомпилировать.

and according to that, Client also will be recompiled.

Нет. Тот факт, что модуль трансляции, реализующий функции-члены Fridges, перекомпилируется, не означает, что клиенты Fridges должны быть перекомпилированы. Только в случае изменения Fridge.h единицы перевода, включая этот заголовок, необходимо перекомпилировать.

But, i see that if Engine is modified, Fridge should modify according. And since Fridge will modify, the Client which uses Fridge will also get modified.

Это проблема показанной реализации. Если бы вместо этого 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_;
};

Can you give me example how NOT recompiling Client translation unit after modifying Engine.h will cause issue?

Если одна единица перевода использует другое определение Engine, чем другая единица перевода, то программа нарушает одно правило определения, и поведение будет неопределенным.

С PIMPL единицы перевода, которые включают Fridge.h, вообще не используют ODR-класс Engine, поэтому вероятность нарушения ODR отсутствует.

Можете ли вы привести пример того, как НЕ перекомпилировать единицу перевода Client после изменения Engine.h вызовет проблему? Я думаю, что если мы не перекомпилируем Client после изменения Engine.h, это не приведет к нежелательному поведению.

Islam Abdeen 01.06.2019 02:31

Другие вопросы по теме