klassen dynamisch erstellen
-
volkard schrieb:
wozu die klasse, wenn sie nur eine static-methode hat?
Oh, volkard. Das ist doch nur ein Beispiel. In der Praxis will man vielleicht viel mehr da reinpacken.
Ausserdem kann man so alles Factory-Maessige in dieselbe Klasse packen.
volkard schrieb:
#define ADDCLASS(class) if(name==#class) return new class; BaseClass* myClassFactoryCreate( const string& name ) { ADDCLASS(Alpha); ADDCLASS(Beta); return 0; // unbekannte Klasse }
Stimmt, kann man auch so machen, aber besser noch waere:
#define ADDCLASS(class) if ( name == #class ) return new class BaseClass* myClassFactoryCreate( const string& name ) { ADDCLASS(Alpha)(); ADDCLASS(Beta)(); return 0; // unbekannte Klasse } #undef ADDCLASS
Falls man noch Parameter an den jeweiligen Konstruktor uebergeben will.
-
Power Off schrieb:
volkard schrieb:
wozu die klasse, wenn sie nur eine static-methode hat?
Oh, volkard. Das ist doch nur ein Beispiel. In der Praxis will man vielleicht viel mehr da reinpacken.
Ausserdem kann man so alles Factory-Maessige in dieselbe Klasse packen.
volkard schrieb:
#define ADDCLASS(class) if(name==#class) return new class; BaseClass* myClassFactoryCreate( const string& name ) { ADDCLASS(Alpha); ADDCLASS(Beta); return 0; // unbekannte Klasse }
Stimmt, kann man auch so machen, aber besser noch waere:
#define ADDCLASS(class) if ( name == #class ) return new class BaseClass* myClassFactoryCreate( const string& name ) { ADDCLASS(Alpha)(); ADDCLASS(Beta)(); return 0; // unbekannte Klasse } #undef ADDCLASS
Falls man noch Parameter an den jeweiligen Konstruktor uebergeben will.
bei mir war im makro ein semikolon zu viel.
im code dasADDCLASS(Alpha);
war gut.
und deinADDCLASS(Alpha)();
ist nicht so gut, weil die klammern da nutzlos und unüblich sind.
aber kannst natürlich malADDCLASS(Alpha)(eingabedatei);
schreiben.
-
volkard schrieb:
ADDCLASS(Alpha)();
ist nicht so gut, weil die klammern da nutzlos und unüblich sind.
Das ist nicht ganz korrekt. Einige Compiler bringen eine Fehlermeldung, wenn man bei explizit deklarierten Konstruktoren die Klammern weglaesst.
Hab grad im Standard nachgeguckt, aber nix gefunden, was das Weglassen des new-initializers als Fehler, fehlgeformt oder korrekt betrachten wuerde. Der Standard scheint fuer den Fall keine Vorschrift zu haben.
-
danke erstmal für eure antworten.
nur glaube ich, das es in meinem fall so auch nicht einfacher wird.
(vielleicht hab ich euro lösung aber auch falsch durchblickt.)was ich nun versuche ist folgendes:
ich versuche eine map anzulegen in in der immer den namen klasse
und einen pointer darauf zu speichern.std::map<const char*,void*> myClasses; myClassA *pMyClassA = new MyClassA();
beim hinzufügen jedoch:
myClasses.insert("class A", pMyClassA);
bekomme ich folgende fehlermeldung:
x:/xxx.cpp(638): error C2664: 'std::_Tree<_Traits>::iterator std::_Tree<_Traits>::insert(std::_Tree<_Traits>::iterator,const std::_Tree<_Traits>::value_type &)' : cannot convert parameter 1 from 'const char [18]' to 'std::_Tree<_Traits>::iterator' with [ _Traits=std::_Tmap_traits<const char *,void *,std::less<const char *>,std::allocator<std::pair<const char *const ,void *>>,false> ] and [ _Traits=std::_Tmap_traits<const char *,void *,std::less<const char *>,std::allocator<std::pair<const char *const ,void *>>,false> ]
-
std::map<const char*,void*> myClasses; myClasses["ClassA"] = new ClassA;
haut leider immer noch nicht so ganz hin
ich kann zwar mit obigen code in die map hineinschreibenallerdings hatte ich gehofft nun auch auf methoden von ClassA
mittelsmyClasses["ClassA"]->methode1();
zugreifen zu können.
noch jemand nen tip hierzu?
-
Power Off schrieb:
Das ist nicht ganz korrekt. Einige Compiler bringen eine Fehlermeldung, wenn man bei explizit deklarierten Konstruktoren die Klammern weglaesst.
erstens gleib ich das nicht und zweitens wäre so ein compiler kaputt und man muß nicht jeden bug pflegen.
-
@asr
tatsache ist: du kannst in c++ klassen nicht dynamisch erzeugen, sondern nur objekte. mit deinen new-aufrufen erzeugst du nie eine klasse sondern immer nur ein objekt vom typ dieser klasse.wenn du uns schreiben würdest, welches problem du mit "dynamischen" klassen lösen willst, dann fände sich bestimmt eine alternative dazu.
-
std::map<const char*,void*> myClasses;
Mach mal lieber aus dem "char*" ein "string" und das const kann dann auch weg, weil die map sich das eh kopiert
-
Nicht
myClasses.insert("class A", pMyClassA);
sondern
myClasses.insert( std::make_pair("class A", pMyClassA) );
-
Konfusius schrieb:
@asr
tatsache ist: du kannst in c++ klassen nicht dynamisch erzeugen, sondern nur objekte. mit deinen new-aufrufen erzeugst du nie eine klasse sondern immer nur ein objekt vom typ dieser klasse.hatte ich schon so gemeint
Pellaeon schrieb:
std::map<string,void*> myClasses;
gut, hab ich geändert. machts aber weder besser noch schlechter
kartoffelsack schrieb:
myClasses.insert( std::make_pair("class A", pMyClassA) );
ändert auch nichts. was soll das genau bewirken?
Konfusius schrieb:
wenn du uns schreiben würdest, welches problem du mit "dynamischen" klassen lösen willst, dann fände sich bestimmt eine alternative dazu.
gut, was ich machen wollte/will ist folgendes.
ich habe ein programm, aus dem man aus einem auswahlmenü funktionen anderer klassen aufrufen kann. diese klassen sind immer ähnlich aufgebaut.
und um das menü, etc nicht immer von hand erweitern zu müssen, dachte ich dass ich einfach ein array mache,
in dem ich die klassennamen speicher.also in etwa dieses:
numOfNewClasses = 2; const char newClass[] = {"newClass1","newClass2"};
sinn des ganzen sollte es sein, dass wenn eine klasse hinzukommt, an möglichst wenig
stellen der code geändert werden muss.deswegen dachte ich erst daran das mit einem #define zu lösen.
scheint aber nicht machbar zu sein.
deswegen die idee mit der map. die taugt mir im prinzip auch erstmal.
nur kann ich leider nicht über die pointer auf je so ein objekt meiner klassenauf die methoden meiner klassen zugreifen.
das war das was ich mit
myClasses["ClassA"]->methode1();
machen wollte.
-
dein wert in der Map ist "void*" und einen Void-Zeiger kann man nicht dereferenzieren, den muss man vorher casten.
-
Pellaeon schrieb:
dein wert in der Map ist "void*" und einen Void-Zeiger kann man nicht dereferenzieren, den muss man vorher casten.
stimmt!
so gehts
((ClassA*)myClasses["ClassA"])->methode1();
aber dann tu ich mir ja später noch schwerer das "dynamisch" zu gestalten
-
Heißen die Mehoden denn immer gleich oder gibts da Unterschiede?
-
ich kann sie auch gleich benennen.
allerdings werden es nicht immer genau gleich viele sein.also wird es was wie
doThis1(); doThis2(); doThis2();
in jeder klasse geben. nur eben mal 3 davon mal mehr oder weniger