this* pointer: Selbst bestimmen, als welches objekt eine funktion aufgerufen wird... ?
-
Der code oben soll nur zur veranschaulichung dienen. Ich hab ihn aus dem Kopf geschrieben.
Ich will Klassen dynamisch laden können. Also zur ausführungszeit komponenten meines programs laden oder entladen. Die header kennen die anderen klassen natürlich nicht. Und virtuelle funktionen will ich auch nicht, da die etwas langsamer sind....
-
Du willst ein Plug-In-System bauen?
-
Kann mir mal jemand erklären was "Void**" und "Void***" sind?
Google ist da ja nicht sooo hilfreich, weil es "*" ja immer als Platzhalte interpretiert.

-
void* = Zeiger auf nicht bestimmten Datentypen
void** = Zeiger auf Zeiger von nicht bestimmtem Datentyp
void*** = Zeiger auf Zeiger auf Zeiger von nicht bestimmten DatentypenDas Sternchen steht für Zeiger google "c++ pointer".
-
Danke. Zeiger etc sind mir schon klar. Deine Erklärung hat mir schonmal viel geholfen.
Aber für was brauche ich einen Zeiger auf einen Zeiger (oder sogar einen Zeiger auf Zeiger auf Zeiger"? Ich habe sowas bisher einmal gesehen und als Blackbox angesehen, für was braucht man sowas?
-
ich verwende void*** NUR in diesem codebeispiel. In meinem wirklichem bisheringen Code habe ich alles geordnet. Ist schon gut...
geht nicht schrieb:
Du willst ein Plug-In-System bauen?
Nicht ganz... Ich kann programme auf komponenten in dynamischen bibliotheken verteilen. Das program hat also eine liste an Komponenten, zB "Netwerk", "Spieler", "Karte", usw... (ich dachte, die könnten vielleicht noch unter-komponenten haben, unter-unter-komponenten, etc...).
-
Ich hab da auch eigenaufwand reingesteckt.... Nicht, dass ihr denkt ich bin SuperFaul...
Mit diesem Problem schlag ich mich schon seit einigen wochen rum...
-
Schau dir mal Boost bind an. Damit kannst du die häßlichen typlosen Zeigereien vermeiden und an Instanzen gebundene Klassenmethoden rufen und speichern.
http://www.boost.org/doc/libs/1_45_0/libs/bind/bind.html#with_function_objects
-
Könntet Ihr mir ein Beispiel geben? Erfordert das eine zusätzliche [statische/dynamische] bibliothek oder nur die header? Ich kenne mich mit boost überhaupt nicht aus.
("Diese funktion als DIESE Klasse aufrufen")
-
Für boost gilt die Regel teils/teils. Bei manchen Sachen reicht schon der header, für andere musst du boost erst auf deiner Maschine erstellen. Es gibt auch schon vorerstellte Versionen zur installation.
-
lk schrieb:
[...]Und virtuelle funktionen will ich auch nicht, da die etwas langsamer sind....
Langsamer als was? Als ein ähnlicher Mechanismus von Dir selbst gebastelt? Wohl kaum. Für Plugins braucht man wohldefinierte Interfaces. Und dafür bieten sich unter C++ Klassen mit rein virtuellen Funktionen an.
-
Tachyon schrieb:
lk schrieb:
[...]Und virtuelle funktionen will ich auch nicht, da die etwas langsamer sind....
Langsamer als was? Als ein ähnlicher Mechanismus von Dir selbst gebastelt? Wohl kaum. Für Plugins braucht man wohldefinierte Interfaces. Und dafür bieten sich unter C++ Klassen mit rein virtuellen Funktionen an.
Ich will ja nicht direkt Plugins machen.
Virtuelle funktionen sind einen ganz kleinen tacken langsamer als normale nicht-virtuelle funktionen. Ich werde auch viele funktionen in den plugins aufrufen, sehr oft...
-
lk, du weichst Tachyons Frage aus.
Wenn du eine Fallunterscheidung brauchst, kannst du nicht auf virtuelle Funktionen verzichten, aber gleichzeitig keine Alternative (
if,switch, etc.) anbieten.
-
Der Aufruf einer virtueller Funktion kostet etwas ja. Allerdings bekommst du dafür ja auch etwas, dass du in einer "normalen" Funktion nachbilden musst (irgendeine Art von verzweigung). Normalerweise braucht man sich da keine Sorgen machen.
Deine Aufgabe habe ich allerdings eher in diese Richtung verstanden:#include <map> #include <iterator> #include <functional> #include <stdexcept> class M { public: typedef std::map<std::string, std::function<void(void)> > MethodMap; typedef std::insert_iterator<MethodMap> Inserter; typedef MethodMap::const_iterator Iterator; virtual ~M(){}; void init() { getfuncs(Inserter(methods_, methods_.begin())); } void Call(const std::string& method) { Iterator it = methods_.find(method); if (it == LastMethod()) throw std::runtime_error("Unknown method name."); it->second(); } Iterator FirstMethod() const { return methods_.begin(); } Iterator LastMethod() const { return methods_.end(); } private: virtual void getfuncs(Inserter i) = 0; MethodMap methods_; }; // irgendwo class init : public M { public: void foo() { std::cout << "fooo\n"; } void bar() { std::cout << "baar\n"; } private: void getfuncs(Inserter i) { i = std::make_pair("foo", std::bind(&init::foo, this)); ++i = std::make_pair("bar", std::bind(&init::bar, this)); } }; int main() { M* m = new init; m->init(); std::cout << "available methods:\n"; for(M::Iterator i = m->FirstMethod(), e = m->LastMethod(); i != e; ++i) { std::cout << i->first << "\n"; } std::cout << "call:"; std::string method; std::cin >> method; try { m->Call(method); } catch(std::exception& e) { std::cout << e.what(); } delete m; return 0; }edit: Jetzt bin ich mir doch nicht mehr sicher was du meinst. Wenn es dir immer nur um die get und set geht, dann ist das tatsächlich ganz einfach mit virtuellen Methoden am effektivsten.
-
Hi.
Ich versuche das geschehen nachzuverfolgen. Ich komme hierbei nicht weiter:Fehlermeldung
Wenn ich list->push_back(..) entferne, compiliert es.class BASE { public: typedef pair<string, function<int(int)> > FEntry; typedef vector<FEntry> FList; virtual FList* getFuncs() = 0; }; class MOD : public BASE { public: virtual FList* getFuncs() { FList* list = new FList(); /* * i = std::make_pair("foo", std::bind(&init::foo, this)); * ++i = std::make_pair("bar", std::bind(&init::bar, this)); * */ // HIER list->push_back( (FEntry)make_pair( "mow", bind(&MOD::mow, this) )); //ENTRY("Sub", sub); // mittels define return list; } int mow(int in) { return in * 2; } int sub(int in) { return in - 100; } }; int main() { // noch leer return 0; }
-
Du kannst this nicht an MOD::mow binden. Der Typ des zweiten Arguments von bind muss schon mit dem übereinstimmen, den MOD::mow erwartet, also int. Außerdem sollte man die Referenz (glaube ich) besser durch boost::ref ersetzen.
Hast du schonmal überlegt auf Funktoren umzusteigen, anstatt Funktionen zurückzugeben?
-
lk schrieb:
Virtuelle funktionen sind einen ganz kleinen tacken langsamer als normale nicht-virtuelle funktionen. Ich werde auch viele funktionen in den plugins aufrufen, sehr oft...
Du willst also dynamic binding ohne eine zusätzliche Indirektion? Sry aber das ist ganz einfach nicht möglich.
-
> Du kannst this nicht an MOD::mow binden. Der Typ des zweiten Arguments von bind muss schon mit dem übereinstimmen, den MOD::mow erwartet, also int. Außerdem sollte man die Referenz (glaube ich) besser durch boost::ref ersetzen. > > Hast du schonmal überlegt auf Funktoren umzusteigen, anstatt Funktionen zurückzugeben? Ich kenn mich mit Boost nicht so gut aus. Beispielcode wäre nett... Sollte ich dann `boost::bind(&MOD::mow, _1, this)` aufrufen? Für zwei Parameter dann `_1, _2` ? Im Detail, was macht der Code genau ?
-
lk schrieb:
Sollte ich dann
boost::bind(&MOD::mow, _1, this)aufrufen? Für zwei Parameter dann_1, _2?Nein, boost::bind(&MOD::mow, this, _1 ).
-
lk schrieb:
Tachyon schrieb:
lk schrieb:
[...]Und virtuelle funktionen will ich auch nicht, da die etwas langsamer sind....
Langsamer als was? Als ein ähnlicher Mechanismus von Dir selbst gebastelt? Wohl kaum. Für Plugins braucht man wohldefinierte Interfaces. Und dafür bieten sich unter C++ Klassen mit rein virtuellen Funktionen an.
Ich will ja nicht direkt Plugins machen.
Virtuelle funktionen sind einen ganz kleinen tacken langsamer als normale nicht-virtuelle funktionen. Ich werde auch viele funktionen in den plugins aufrufen, sehr oft...
so what... Lies Dich mal in das Thema: "Premature Optimizing" ein, denn genau das machst Du gerade. Du versuchst ein etabiliertes, optimiertes System (virtuelle Funktion) durch etwas ähnliches zu ersetzen was unterm Strich eher langsamer als schneller sein wird. Abgesehen davon, selbst wenn der Aufruf einer virtuellen Funktion langsamer ist, so macht das vielleicht 0.000001% Deiner Rechnerperformance aus. Optimier lieber erstmal an anderen Stellen die auch eine meßbare Auswirkung auf die Performance haben.