Представьте, что вы создаете класс Robot. Чтобы робот функционировал, ему нужен очень сложный двигатель. В контексте кода нам необходимо подключить огромный заголовочный файл SuperComplexEngine.h, который, например, тянет за собой Windows.h или что-то другое массивное:
#pragma once
// тяжёлый заголовок
#include "SuperComplexEngine.h"
class Robot
{
public:
void run();
private:
// деталь реализации (двигатель) видна всем, кто подключит Robot.h
SuperComplexEngine m_engine;
int m_voltage;
};
SuperComplexEngine.h, то перекомпилируется Robot, а за ним и все классы, в которых используется данный робот.Robot в другом месте.private новую переменную, бинарный размер класса Robot изменится — все зависимые файлы снова нужно пересобирать.Первый шаг оптимизации — использовать предварительное объявление (forward declaration). Мы можем убрать тяжелый include, но обязаны превратить соответствующие поля в указатели.
Попытка оптимизации (Robot.h):
#pragma once
// forward declaration
class SuperComplexEngine;
class Robot
{
public:
void run();
private:
// pointer
SuperComplexEngine* m_engine;
int m_voltage;
};
header файле. Добавление любого дополнительного члена класса меняет его размер, вызывая перекомпиляцию зависимостей. Все файлы, использующие Robot , уйдут на пересборку.m_engine, m_voltage. Это лишний визуальный шум.<aside> 💡
pImpl (Pointer to Implementation) — это идиома проектирования в C++, которая скрывает детали реализации класса путем выноса их в отдельную структуру в единицу трансляции, скрытую за указателем. В заголовочном файле остается только указатель на эту структуру.
</aside>