Artery Geschrieben 6. März 2012 Teilen Geschrieben 6. März 2012 (bearbeitet) Hallo leute, wie realisiere ich eine Funktion unterschiedliche Datentypen zurückgeben kann? Um was es sich für einen Datentyp handelt, weiß ich beim Aufruf. Habe es erstmal so probiert: template<typename T> T get_DialogitemByCustomID (std::string strCostumID); template<typename T> T ety::CDialog::get_DialogitemByCustomID(std::string strCostumID) { for(std::list<CDialogitem*>::iterator itDialogitem = m_listDialogitems.begin(); itDialogitem != m_listDialogitems.end(); itDialogitem++) { //Es wird die CustomID des Dialogitems überprüft und wenn sie überein stimmt wird das Dialogitem zurückgegeben if((*itDialogitem)->get_CostumID() == strCostumID) { T bla = (*itDialogitem) return bla; } } return NULL; } aber beim Funktionsaufruf: ety::CButton* p_c_etyButtonMainMenuTmpPointer = m_mapDialogs["MainMenuPad"].get_DialogitemByCustomID<ety::CButton*>("PadStartenButton"); sagt er "Verweis auf nicht aufgelöstes externes Symbol", dass get_DialogitembyCustomID<class ety::CButton*> (...) eben nicht ausformuliert wurde... Wie soll ich es sonst lösen? MfG Artery €dit: Das ist eine memberfunktion von einer Klasse, wenn ich einfach nen Konsolenprojekt anlegen, die funktion über die main packe, klappt es... Bearbeitet 6. März 2012 von Artery Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 6. März 2012 Teilen Geschrieben 6. März 2012 Die Definition eines Funktionstemplates muss dort bekannt sei, wo das Template instanziiert wird. Kurz gesagt heißt das, dass du Templates normalerweise nicht in Header- und Quellcodedatei aufteilst, sondern direkt im Header definierst. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Artery Geschrieben 6. März 2012 Autor Teilen Geschrieben 6. März 2012 Mmmm... okay das funktioniert jetzt. Gibt es aber dennoch eine Möglichkeit das aufzuteilen? Weil ich eigentlich keine Ausformulierungen der Funktionen in den Headern haben möchte. MfG Artery Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 6. März 2012 Teilen Geschrieben 6. März 2012 Aufteilen kannst du es nur, wenn du vorher genau weißt, für welche Templateparameter du das Template brauchst. Dann kannst du es nämlich explizit instantiieren. Ich bin allerdings der Meinung, dass du für die einfache Konvertierung zwischen zwei Zeigertypen, die ohnehin implizit konvertierbar sind, gar kein Template brauchst. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Artery Geschrieben 7. März 2012 Autor Teilen Geschrieben 7. März 2012 Also ich habe eine Klasse von der habe ich nun mehrere Klassen abgeleitet. Ich wollte nun eine Funktion die ich aufrufe und dann eben jehnachdem einen Zeiger auf die eine Klasse oder auf die andere usw. zurück kriege ohne ihrgendwie 8 Funktionen dafür zuhaben! Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
flashpixx Geschrieben 7. März 2012 Teilen Geschrieben 7. März 2012 Ich verstehe irgendwie das Problem nicht. Du hast eine Klasse / Methode als Template, somit kannst Du doch den Template Parameter eben passend setzen und hast die entsprechende Rückgabe. Falls das nicht ausreichend ist, kannst Du auch für konkrete Templates die Methode noch überladen Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Artery Geschrieben 7. März 2012 Autor Teilen Geschrieben 7. März 2012 Ja es funktioniert auch alles wunderbar ich will nur das ausformulierte template nicht in meinem Header stehen haben! Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
flashpixx Geschrieben 7. März 2012 Teilen Geschrieben 7. März 2012 mache die Headerdatei und unterhalb setzt zu ein #include <inhalt_deines_templates.hpp> Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 7. März 2012 Teilen Geschrieben 7. März 2012 Ich wollte nun eine Funktion die ich aufrufe und dann eben jehnachdem einen Zeiger auf die eine Klasse oder auf die andere usw. zurück kriege ohne ihrgendwie 8 Funktionen dafür zuhaben!Wenn dein Funktionstemplate so funktioniert, wie es da steht, ist CDialogitem* implizit (also ohne Cast) in T konvertierbar. Das erreichst du auch mit einer einzigen Funktion, die CDialogitem* zurückgibt. Und selbst wenn du einen Cast brauchen solltest, kannst du die Funktion einfach zerlegen, in den Such-Teil (der ist immer gleich) und den Typumwandlungs-Teil (nur der hängt von T ab). Und dann wirst du feststellen, dass der Typumwandlungsteil dasselbe tut wie static_cast. Und damit tut's das hier auch: // get_DialogitemByCustomID ist kein Template und gibt CDialogItem* zurück ety::CButton* p = static_cast<ety::CButton*>(m_mapDialogs["bla"].get_DialogitemByCustomID("blubb"));[/code] Ein Template ist hier unnötig, und bläht dein Programm nur sinnlos auf. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Artery Geschrieben 10. März 2012 Autor Teilen Geschrieben 10. März 2012 Ja letztlich geht es auch so das stimmt, aber ich wollte einfach nur eine Funktion aufrufen und nicht noch nen cast davor setzen. Ähm noch dazu eine Frage, wo ist der unterschied zwischen static_cast dynamic_cast und dem cast-operator z.b. (CButton*)MeineVariable ? Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 12. März 2012 Teilen Geschrieben 12. März 2012 Ähm noch dazu eine Frage, wo ist der unterschied zwischen static_cast dynamic_cast und dem cast-operator z.b. (CButton*)MeineVariable ?Letzteren hat C++ von C geerbt, daher wird er auch "C-Style-Cast" genannt. Der macht je nach Situation komplett unterschiedliche Dinge, daher hat man in C++ neue Cast-Operatoren eingeführt, die einen klar abgegrenzenten Aufgabenbereich haben. Diese sind static_cast, dynamic_cast, reinterpret_cast und const_cast. static_cast kann beispielsweise von einem Zeiger auf eine Basis- in einen Zeiger auf eine abgeleitete Klasse konvertieren. Dabei wird allerdings nicht geprüft, ob der Zeiger wirklich auf ein Objekt der abgeleiteten Klasse zeigt, der Programmierer muss also wissen, was er tut. Wenn man eine solche Prüfung braucht, kann man dynamic_cast benutzten. Da wird der Typ zur Laufzeit geprüft, und falls er nicht passt, ist das Ergebnis des Cast-Ausdrucks null. Die übermäßige Verwendung von dynamic_cast ist allerdings oft ein Zeichen für schlechtes Design. const_cast kann const und volatile von einem Typ entfernen (oder hinzufügen). reinterpret_cast ist sozusagen der Holzhammer, er wandelt um, indem die Speicherrepräsentation einfach als der neue Typ interpretiert wird. Hier kann der Compiler nichts prüfen, wenn's knallt, ist der Programmierer schuld. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Artery Geschrieben 12. März 2012 Autor Teilen Geschrieben 12. März 2012 Ahh okay... nur wieso ist die Benutzung von dynamic_cast ein Zeichen für schlechtes design? Also was sollte ich dann eher benutzen (CButton*) , static_cast oder dynamic_cast, wenn ich einen Basisklassenzeiger umwandeln will und auch genau weiß worin? MfG Artery Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Klotzkopp Geschrieben 12. März 2012 Teilen Geschrieben 12. März 2012 Ahh okay... nur wieso ist die Benutzung von dynamic_cast ein Zeichen für schlechtes design?Die übermäßige Verwendung ist oft ein Zeichen für schlechtes Design. Wenn man immer wieder prüfen muss, welchen Typ ein Objekt denn nun wirklich hat, dann meist deswegen, weil eine Vererbungsbeziehung besteht, die eigentlich keine ist, sondern nur der Wiederverwendung von Code dient. Also was sollte ich dann eher benutzen (CButton*) , static_cast oder dynamic_cast, wenn ich einen Basisklassenzeiger umwandeln will und auch genau weiß worin?static_cast. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.