У C ++ ініціалізатори стилю C були замінені конструкторами, які за час компіляції можуть забезпечити виконання тільки дійсних ініціалізацій (тобто після ініціалізації члени об'єкта є послідовними).
Це хороша практика, але іноді попередня ініціалізація зручна, як у вашому прикладі. OOP вирішує це за допомогою абстрактних класів або креативних моделей дизайну .
На мою думку, використання цього безпечного способу вбиває простоту, а іноді компроміс із безпекою може бути надто дорогим, оскільки для простого коду не потрібен складний дизайн, щоб залишатися ремонтом.
Як альтернативне рішення, я пропоную визначити макроси за допомогою лямбда для спрощення ініціалізації, щоб виглядати майже як C-стиль:
struct address {
int street_no;
const char *street_name;
const char *city;
const char *prov;
const char *postal_code;
};
#define ADDRESS_OPEN [] { address _={};
#define ADDRESS_CLOSE ; return _; }()
#define ADDRESS(x) ADDRESS_OPEN x ADDRESS_CLOSE
Макрос АДРЕС розширюється до
[] { address _={}; /* definition... */ ; return _; }()
що творить і називає лямбда. Параметри макросу також розділені комами, тому потрібно поставити ініціалізатор в дужки і викликати подібні
address temp_address = ADDRESS(( _.city = "Hamilton", _.prov = "Ontario" ));
Ви також можете написати генералізований ініціалізатор макросів
#define INIT_OPEN(type) [] { type _={};
#define INIT_CLOSE ; return _; }()
#define INIT(type,x) INIT_OPEN(type) x INIT_CLOSE
але тоді дзвінок трохи менш гарний
address temp_address = INIT(address,( _.city = "Hamilton", _.prov = "Ontario" ));
однак ви можете визначити макрос АДРЕС за допомогою загального макроса INIT легко
#define ADDRESS(x) INIT(address,x)