TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #307 4.39K
​Named Constructor Idiom

Конструкторы - вещь хорошая, но довольно ограниченная. Если вы хотите создать объект класса ТяжеленнаяФиговина, то логично было бы ввести разные конструкторы для разных систем измерения. Ну например, чтобы фиговина могла создаваться из киллограммов и из фунтов. Но это невозможно.

Дело в том, что конструктор класса - такая же функция, как и все остальные. У него есть имя(имя класса), список аргументов(включая неявный this) и пустое возвращаемое значение. В языке С++ конструкторы вообще ничего не возвращают, но они так или иначе реализованы на обычных ассемблерных функциях, а они имеют все эти обязательные характеристики.

А раз это функция и неизменяемым именем, то различать разные конструкторы мы можем только с помощью разного списка параметров.

И это становится проблемой, когда конструкторов много и их уже сложно отличать друг от друга, либо как в нашем примере с ТяжелойФиговиной мы просто не можем два конструктра с одинаковым списком параметров, но эти параметры будут иметь разное назначение.

Допустим, что с фиговиной помогут справиться strong typedefs. Но со сложностью различий конструкторов для пользователя они не помогут. А вот что может помочь.

Named Constructor Idiom. Давайте дадим имена конструкторам!

Точнее мы немного схитрим. Добавим именные статические функции-фабрики, которые и будут конструировать наши объекты, и переместим все конструкторы в private секцию.

Покажу на примере фиговины, чтобы было по-проще и по-короче

struct HeavyThing {
static HeavyThing ConstructFromKilos(float kilos) {
return HeavyThing(kilos);
}
static HeavyThing ConstructFromPounds(float pounds) {
return HeavyThing(0,453592 * pounds);
}
private:
HeavyThing(float kilos) : kilos_{kilos} {}

float kilos_;
};

int main() {
HeavyThing a = HeavyThing::ConstructFromKilos(100500.0);
HeavyThing b = HeavyThing::ConstructFromPounds(12345678.0);
}


Да, придется немного букав пописать, но для столкнувшихся с такой проблемой это - выход. Можно еще поиграться с возвращаемым значением. Например, сделать его уникальным указателем. Но это уже детали.

Make convenient interfaces. Stay cool.

#design
  • 👍 40
  • 🔥 11
  • ❤ 5
  • ⚡ 1
  • 👎 1
  • 🤩 1
More from @grokaemcpp
  1. Oct 14, 2026​​Что внутри std::condition_variable? #опытным Более менее все знакомы с примитивом синхро…
  2. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  3. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  4. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  5. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  6. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →