Interessant, ich habe zwar von CRTP überhaupt keine Ahnung aber beim überfliegen (
https://www.grimm-jaud.de/index.php/blog/c-ist-doch-lazy) sieht es danach aus, als geht es um "Bedarfsauswertung". Bezogen darauf geht die Vermutung schon in die richtige Richtung und hat mit meiner folgenden Frage zu tun.
Ich öffne mal kein neuen Thread da es mit dem Bisherigen zu hat/darauf aufbaut.
Das Vorhaben ist am Ende so:
Zur Laufzeit wird anhand von Settings in einer csv entschieden, welche Objekte/dessen Methoden ausgeführt werden sollen. Ich nenne die mal Module. Die Module, die aktiv sein sollen, werden erzeugt und der Zeiger kommt in ein Vector und der Vector wird dann zu Ausführung iteriert. So werden alle Methoden der gewünschten Module ausgeführt. Damit der Vector die Zeiger auf verschiedene Objekte/Methoden schluckt, muss ich wohl mit einem Interface arbeiten. Das Interface mit rein virtueller Funktion wird an die eigentlichen Objekte mit Ihren Methoden vererbt. So der Plan verschiedene Objekte zur Laufzeit je nach csv Input auszuführen.
Das heißt es gibt: (ich benenne die Klassen jetzt mal ganz neu und habe anhand der Hinweise von @
RalphS das Design geändert damit es keine gegenseitigen Abhängigkeiten mehr gibt)
- Klasse "Data" welche die gemeinsamen Daten besitzt, die von allen "Modulen" sowie "Start" gebraucht wird.
- Klasse "Interface" mit rein virtueller Funktion
- unterschiedliche Klassen "Module" mit einer vom Interface abgeleiteten Methode. (CSV entscheidet über Aktivierung). Es werden später mal bis zu 50 Module.
- Klasse "Start" die das Objekt der Klasse Data anlegt und hier testweise die Module erstellt und in ein Vector packt und dann ausführt. Das Ausführen der Module also Iterieren des Vectors wird dann die Hauptbeschäftigung des Programms.
C++:
#include <iostream>
#include <vector>
#include <memory>
struct Data
{
int i = 0;
double d = 0;
};
struct Interface
{
virtual void Run(int index) = 0;
virtual ~Interface() {}
};
struct Modul_01 : Interface, Data
{
Modul_01(Data* d): data(d) {}
Data* data;
void Run(int index)
{
data->i += index;
std::cout << "Modul_01: " << i << std::endl;
}
};
struct Modul_02 : Interface, Data
{
Modul_02(Data* d): data(d) {}
Data* data;
void Run(int index)
{
data->d += 1.234+index;
std::cout << "Modul_02: " << d << std::endl;
}
};
struct Start : Data
{
Data data;
std::vector<std::unique_ptr<Interface>> vector;
void start()
{
vector.emplace_back(new Modul_01(&data));
vector.emplace_back(new Modul_02(&data));
for (auto i = 0; i < vector.size(); i++)
{
vector[i]->Run(1);
}
}
void weitere_Methoden()
{
// ich arbeite auch mit data...
}
};
int main()
{
Start start;
start.start();
return 0;
}
Jetzt hab ich bei diesem Design noch ein Problem. Mich nervt total, dass ich in den Modulen auf die Daten "Data" überall per Pfeil-oder Punkt-Operator zugreifen muss da man auf das extra Objekt "Data" angewiesen ist. Irgendwie wäre es besser wenn "Data" in allen Modulen sozusagen zum Sichbarkeitsbereich gehört und man sich diese Indirektion sparen könnte. Auch in "Start" wird es noch Methoden geben die mit Data arbeiten wollen. Performance könnte am Ende eine Rolle spielen weil eine wiederholte Ausführung der gewählten Module die Grundlage des Programms ist, da ich Klimadaten durchschleife und auf die von der CSV gewählten Module anwende. Insofern bin ich eigentlich noch nicht ganz zufrieden mit dem Design, da es so noch etwas schwerfällig ist und ich die ganzen Zugriffsoperatoren für Data gern weg hätte.
Verbesserungsvorschläge immer gern
, Grüße