Грокаем C++
@grokaemcpp
Designated initialization
#новичкам
В продолжение предыдущего поста, почему бы нам не поговорить о том, что такое designated initialization в контексте С++ и какие особенности она имеет в языке.
Эта фича С++20, которая позволяет явно указывать поля, которым присваиваются значения, при создании объекта.
Пусть у нас есть заказ, который состоит из данных о человеке, который заказал товар, и самого заказанного товара. Мы хотим распарсить входящий запрос от клиента и сформировать структуру Order для дальнейшей обработки. Теперь мы можем сделать это очень просто и почти играючи.
То, как мы указываем каждый член структуры и присваиваем ему значение - и есть designated initialization. Собственно пример показывает всю прелесть фичи. Теперь по коду явно видно, каким полям какое значение присваивается. И даже вложенность поддерживается. Это сильно повышает читаемость и понимание происходящего.
Если хотите использовать наследование, то синтаксис такой:
Так как у полей родителького класса нет какого-то имени, то используются просто вложенные скобки.
А еще вы можете пропускать любые поля и они будут инициализированны по умолчанию! Давно не хватало такой возможности:
Хоть
Правда у фичи есть определенные ограничения:
👉🏿 Поля должны идти по порядку их объявления в классе. out-of-order инициализация, как в сишке, запрещена. То есть нельзя делать так:
Почему бы не сделать так же, как в С? Дело в том, что в С нет деструкторов. А в С++ есть. И поля класса инициализируются в порядке их появления в объявлении класса, а уничтожаются - в обратном.
Программист может подумать, что раз я указываю какое-то поле первым в инициализации, то и значение ему будет присвоено в первую очередь. Но это не так. А учитывая, что инициализаторы могут иметь какие-то спецэффекты, например, как-то зависеть друг от друга, это может приводить к путанице.
👉🏿 Структуры должны быть POD типами, то есть вот такими же структурами без каких-либо конструкторов и специальных методов. Объекты с конструкторами должны создаваться через онные, а не напрямую. Ну это собственно просто ограничения аггрегированной инициализации, через которую и реализованы designated инициализаторы.
👉🏿 Если используете designated инициализаторы для одних полей, то нужно в этом же формате задавать значения другим полям. Смешанный формат запрещен:
Несмотря на все ограничения, они мне кажутся вполне оправданными, а сама фича вообще супергуд. Пользуйтесь, это сильно повысит читаемость кода.
Have a clear intentions. Stay cool.
#cpp20 #cppcore
#новичкам
В продолжение предыдущего поста, почему бы нам не поговорить о том, что такое designated initialization в контексте С++ и какие особенности она имеет в языке.
Эта фича С++20, которая позволяет явно указывать поля, которым присваиваются значения, при создании объекта.
struct Person {
std::string name;
std::string surname;
std::string id;
};
struct Item {
std::string name;
double price;
std::string id;
};
struct Order {
Person person;
Item purchase;
std::string pick_up_address;
};Пусть у нас есть заказ, который состоит из данных о человеке, который заказал товар, и самого заказанного товара. Мы хотим распарсить входящий запрос от клиента и сформировать структуру Order для дальнейшей обработки. Теперь мы можем сделать это очень просто и почти играючи.
Order order{.person = {.name = "Golum",
.surname = "Iz shira",
.id = "666"},
.purchase = {.name = "Precious",
.price = 9999999.9,
.id = "13"},
.pick_up_address = "Mordor"};То, как мы указываем каждый член структуры и присваиваем ему значение - и есть designated initialization. Собственно пример показывает всю прелесть фичи. Теперь по коду явно видно, каким полям какое значение присваивается. И даже вложенность поддерживается. Это сильно повышает читаемость и понимание происходящего.
Если хотите использовать наследование, то синтаксис такой:
struct Person
{
std::string name;
std::string surname;
unsigned age;
};
struct Employee : Person
{
unsigned salary;
};
Employee e1{ { .name{"John"}, .surname{"Wick"}, .age{40} }, 50000 };Так как у полей родителького класса нет какого-то имени, то используются просто вложенные скобки.
А еще вы можете пропускать любые поля и они будут инициализированны по умолчанию! Давно не хватало такой возможности:
struct Point{
int x, y, z;
};
Point p{.x = 2, .z = 3}; // y is not mentioned, but it will have value of 0Хоть
y строит в середине, но это не мешает нам не указывать его при создании класса и это поле гарантированно будет равно 0.Правда у фичи есть определенные ограничения:
👉🏿 Поля должны идти по порядку их объявления в классе. out-of-order инициализация, как в сишке, запрещена. То есть нельзя делать так:
struct Point{
int x, y;
};
Point p{.y = 2, .x = 3}; // not valid in C++!Почему бы не сделать так же, как в С? Дело в том, что в С нет деструкторов. А в С++ есть. И поля класса инициализируются в порядке их появления в объявлении класса, а уничтожаются - в обратном.
Программист может подумать, что раз я указываю какое-то поле первым в инициализации, то и значение ему будет присвоено в первую очередь. Но это не так. А учитывая, что инициализаторы могут иметь какие-то спецэффекты, например, как-то зависеть друг от друга, это может приводить к путанице.
👉🏿 Структуры должны быть POD типами, то есть вот такими же структурами без каких-либо конструкторов и специальных методов. Объекты с конструкторами должны создаваться через онные, а не напрямую. Ну это собственно просто ограничения аггрегированной инициализации, через которую и реализованы designated инициализаторы.
👉🏿 Если используете designated инициализаторы для одних полей, то нужно в этом же формате задавать значения другим полям. Смешанный формат запрещен:
struct Point{
int x, y;
};
Point p{2, .y = 3}; // Not allowedНесмотря на все ограничения, они мне кажутся вполне оправданными, а сама фича вообще супергуд. Пользуйтесь, это сильно повысит читаемость кода.
Have a clear intentions. Stay cool.
#cpp20 #cppcore
🔥 34
👍 16
❤ 10
47 30 5.5K
Обсуждение 47
Обсуждение не доступно в веб-версии. Чтобы написать комментарий, перейдите в приложение Telegram.
Обсудить в Telegram