Ho un set di classi che ereditano tutte da una classe base responsabile di diverse funzioni (una specie di gruppo di "operatori"). Funzionano tutte sullo stesso input e producono lo stesso tipo di output, solo diverse operazioni sono eseguite internamente con qualche altro stato. Devono essere serializzati su JSON e resi effettivi da un'interfaccia utente.
I miei requisiti sono che le persone debbano essere in grado di lavorare su questo senza faticare a capirlo. Speravo che qualcun altro l'avesse utilizzato in un progetto diverso con altre persone e potrebbe dirmi se questa è una cattiva idea per esperienza e perché.
Per fare ciò ho utilizzato mappe che associano il nome della classe al costruttore e il metodo per serializzare la classe. All'inizio stavo inserendo manualmente le informazioni di classe in un file separato che conteneva queste mappe, poi ho trovato un metodo da fare quindi utilizzando oggetti di classe statici , dove si aggiungono automaticamente alla mappa statica delle classi astratte padre. Perché questo era necessario per ogni classe, non importa cosa, e aveva lo stesso formato esatto tranne il nome della classe utilizzata, ho creato due macro per aiutare con questo (quindi avresti bisogno solo di fare MACRO_TAG_CLASS(classname)
dentro la dichiarazione della classe e MACRO_REGISTER_CLASS(classname)
dopo la dichiarazione).
Ora sono arrivato a rifattorizzare il modo in cui stavo facendo la serializzazione e la visualizzazione GUI, consentendo un minor lavoro per le persone che creano nuove classi di questo tipo e rendendole più versatili per come ora voglio usarle. Alla fine ho dovuto usare le proprietà QT allo stesso modo con ogni classe, quindi ho deciso di fare una macro per gestire anche questo (Nota che sto usando il pre-processore boost per dare una mano)
Ora ho classi che sembrano tutte così:
class MyClass :
public AbstractBase {
Q_OBJECT
private:
TypeA m_foo;
TypeB m_bar;
public:
MACRO_TAG_CLASS(MyClass)
MACRO_ADD_PROPERTIES((TypeA, foo), (TypeB, bar))
//adds qt properties, signals, and adds the strings of the properties to a list for the class
//other class functions...
//constructor that is different per class
//function every class in this heirarchy has, sort of operator(),
//but class is doesn't correspond 1:1 with the concept of an operator, so not a functor.
AbstractBase *baz(X *x) override;
virtual ~MyClass() = default;
};
MACRO_REGISTER_CLASS(MyClass)
e stavo pensando di cambiarli in qualcosa di simile a questo:
#define START_CLASS_OF_BASE(CLASS_NAME, ...)\
class CLASS_NAME : public AbstractBase { \
Q_OBJECT \
public: \
MACRO_TAG_CLASS(CLASS_NAME) \
MACRO_ADD_PROPERTIES(__VA_ARGS__) \
private:
#define END_CLASS_OF_BASE(CLASS_NAME) \
}; \
MACRO_REGISTER_CLASS(CLASS_NAME)
START_CLASS_OF_BASE(MyClass, (TypeA, foo), (TypeB, bar))
private:
TypeA m_foo;
TypeB m_bar;
public:
//other class functions...
//constructor that is different per class
AbstractBase *baz(X *x) override;
virtual ~MyClass() = default;
END_CLASS_OF_BASE(MyClass)
Nota che questo modello appare solo in questa particolare gerarchia di classi, altre persone dovranno mantenere questo codice alla fine, e ci sono circa 20 classi che si adattano a questo modello.