In C++ wurden die Initialisierer im C-Stil durch Konstruktoren ersetzt, die zur Kompilierzeit sicherstellen können, dass nur gültige Initialisierungen durchgeführt werden (d.h. nach der Initialisierung sind die Objektmitglieder konsistent).
Das ist eine gute Praxis, aber manchmal ist eine Vorinitialisierung praktisch, wie in Ihrem Beispiel. OOP löst dieses Problem durch abstrakte Klassen oder gestalterische Entwurfsmuster .
Meiner Meinung nach wird durch diesen sicheren Weg die Einfachheit zunichte gemacht, und manchmal könnte der Kompromiss bei der Sicherheit zu teuer sein, da einfacher Code kein ausgeklügeltes Design benötigt, um wartbar zu bleiben.
Als alternative Lösung schlage ich vor, Makros mit Lambdas zu definieren, um die Initialisierung so zu vereinfachen, dass sie fast wie in C aussieht:
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
Das Makro ADDRESS wird erweitert zu
[] { address _={}; /* definition... */ ; return _; }()
der das Lambda erzeugt und aufruft. Makro-Parameter sind ebenfalls durch Kommata getrennt, daher müssen Sie den Initialisierer in Klammern setzen und wie folgt aufrufen
address temp_address = ADDRESS(( _.city = "Hamilton", _.prov = "Ontario" ));
Sie könnten auch einen verallgemeinerten Makroinitialisierer schreiben
#define INIT_OPEN(type) [] { type _={};
#define INIT_CLOSE ; return _; }()
#define INIT(type,x) INIT_OPEN(type) x INIT_CLOSE
aber dann ist der Anruf etwas weniger schön
address temp_address = INIT(address,( _.city = "Hamilton", _.prov = "Ontario" ));
Sie können das ADDRESS-Makro jedoch problemlos mit dem allgemeinen INIT-Makro definieren
#define ADDRESS(x) INIT(address,x)