Gateway_man Geschrieben 7. April 2013 Geschrieben 7. April 2013 Hallo Leute, damit man mein Problem versteht hol ich kurz einmal weiter aus. Ich schreibe aktuell ein Framework das letztendlich aus mehreren DLL bestehen wird. Aktuell habe ich ein mächtiges Problem mit exportieren der Klassen. Da die Klassen größtenteils voneinander abhängig sind muss ich fast überall ein Export machen und das finde ich jetzt nicht sehr elegant und das würde ich auch gerne vermeiden. Zumal ich dann die Header immer mit in die anderen Projekte schleppen müsste. Ich hatte mir daher folgendes überlegt: Ich schreibe "Interface" Klassen, welche die Notwendigen Funktionen (als abstract) beinhalten. Diese Interface Klassen exportiere ich. Die nicht exportierten Klassen erben von den "Interface" Klassen und implementieren deren Funktionen. Dann gibt es eine Exportierte Funktion die letztendlich eine Instanz der nichtexportierten Klasse erstellt und über ein Cast die Interface Klasse zurückgibt. Bin mir jetzt nicht sicher ob das verständlich rüberkam. Daher werde ich jetzt einfach mal ein Beispiel posten (Hierbei geht es nur um das Casten und Vererbung): class Mother { private: std::string data; public: Mother(std::string input); void SetString(std::string input); std::string GetString(); }; class Child : public Mother { private: int number; public: Child(int input, std::string input2); void SetInt(int input); int GetInt(); }; Mother* GetMotherInstance(int input1, std::string input2) { Child result = Child(input1, input2); return dynamic_cast<Mother*>(&result); } Wenn ich jetzt den Mother Pointer, welchen ich von der Funktion GetMotherInstance zurückerhalten wieder versuche zum Child zu casten macht er das auch. Aber ich habe keinen Zugriff mehr auf die Membervariablen der Mother Klasse. Ich arbeite leider nur selten mit Vererbung in C++, daher sind meine Kentnisse diesbezüglich sehr beschränkt. Da es in anderen Programmiersprachen möglich ist, nahm ich an das es eventuell auch in C++ möglich ist. Damit meine ich: Wenn ich eine Instanz der Kindes erstelle, es mit Daten fülle und dann die Variable als Mutter Typ caste und dann die Muttervariable wieder zurück als Kind Typ caste, dann will ich, das die Kindspezifischen Daten, welche ich vorher gesetzt habe, noch vorhanden sind. Jetzt die Frage. Ist das generel in C++ nicht möglich oder muss ich bei dem Konstrukt nur auf etwas achten oder eine spezielle Art des Castings nutzen? LG Gateway Zitieren
Klotzkopp Geschrieben 7. April 2013 Geschrieben 7. April 2013 Erstens brauchst du gar keinen Cast, um einen Child- in einen Mother-Zeiger umzuwandeln, das ist eine implizite Konvertierung. Zweitens gibst du die Adresse eine lokalen Variablen zurück. Die Variable result wird am Ende von GetMotherInstance zerstört, der zurückgegebene Zeiger ist ungültig. Drittens sollte eine Schnittstelle keine Datenmember haben, und die Methoden sollten pure virtual sein. Zitieren
Gateway_man Geschrieben 7. April 2013 Autor Geschrieben 7. April 2013 Hi Klotzkopp, danke. Das war totales versagen auf ganzer Linie . Eine Lokale Variable die nach dem Aufruf keine Gültigkeit mehr hatte.... Was hab ich mir nur dabei gedacht. Und ich meinte natürlich virtual anstatt abstract. Ich verwechsel die Schlüsselwörter immer mal wieder. Hab es jetzt nochmal fix ausprobiert und es geht doch einfwandfrei . Fand das schon komisch das ich nicht zwischen beiden Typen nicht Casten konnte. Child* child = new Child(33,"das ist ein test"); Mother* mother = (Mother*)child; cout << "-->" << ((Child*)mother)->GetString() << ((Child*)mother)->GetInt() << endl; delete child; Aus reinem Interesse würde mich mal interessieren wie du das angehen würdest? Würdest du alle Klassen exportieren oder auch Interface Klassen (mit den relevanten Funktionen) schreiben und diese exportieren? Ich weiß nicht ob das so gänig ist. Ich hatte erst angefangen alle Klassen zu exportieren, bin aber fast wahnsinnig geworden weil ich wieder jede kleine Neuerung exportieren musste (Auch wenn diese nur intern genutzt wird). Lg Gateway Zitieren
Klotzkopp Geschrieben 7. April 2013 Geschrieben 7. April 2013 Würdest du alle Klassen exportieren oder auch Interface Klassen (mit den relevanten Funktionen) schreiben und diese exportieren?Ich würde festlegen, was die öffentliche Schnittstelle der DLL ist, und genau die dazu gehörenden Klassen und Funktionen exportieren. Man verwendet DLLs nicht zuletzt ja auch deshalb, weil man sie unabhängig von den sie verwendenden Programmen aktualisieren kann. Jedes exportierte Symbol stellt dabei eine Abhängigkeit dar, deren Zusicherungen nicht verändert werden dürfen. Aber nochmal zu deinem letzten Codefragment: Du solltest nicht den C-Style-Cast verwenden. Der macht je nach Situation etwas anderes. Benutz lieber die C++-Casts (static_cast, const_cast, reinterpret_cast), die erfüllen jeweils eine ganz bestimmte Aufgabe, und man sieht ihnen auch gleich an, was sie tun sollen. Der Cast von Child* auf Mother* ist wie gesagt unnötig, das muss ohne Cast gehen. Ein Cast von Mother* auf Child* ist verdächtig. Wenn Mother ein ordentliches Interface ist, sollte der nicht notwendig sein, virtual kümmert sich darum, dass die richtige Methode aufgerufen wird. Allgemein sollten Casts in deinem Code eher selten auftauchen. Viele Casts (insbesondere dynamic_cast) weisen auf ein Designproblem hin. Und schließlich würde ich Smartpointer verwenden. Dein Code ist nicht "exception safe". Wenn GetString oder GetInt eine Exception wirft, wird das delete übersprungen, und du hast ein Speicherleck. Die Antwort auf dieses Problem ist allerdings nicht, jeden Funktionsaufruf in einen try-Block zu stecken, sondern RAII. Wenn sich ein Smartpointer automatisch um das delete kümmert, kannst du es nicht mehr vergessen, und auch bei einer Exception wird es ausgeführt. Zitieren
Astasor Geschrieben 31. Juli 2013 Geschrieben 31. Juli 2013 Der reinterpret_cast ist aber genauso schlecht wie die C-Casts, da er den Inhalt einer Variable als beliebig interpretierbares Bitmuster wahrnimmt. Das ist genau dieselbe Philosophie wie bei den zu vermeidenden C-Casts. Zitieren
Klotzkopp Geschrieben 31. Juli 2013 Geschrieben 31. Juli 2013 Der reinterpret_cast ist aber genauso schlecht wie die C-Casts, da er den Inhalt einer Variable als beliebig interpretierbares Bitmuster wahrnimmt. Nicht ganz. Ein reinterpret_cast kann beispielsweise kein const oder volatile entfernen. Reinterpret_cast ist hässlich, aber manchmal braucht man ihn doch. Und noch eins hat der dem C-Cast voraus: Man erkennt ihn sofort, er ist ein Warnsignal. Zitieren
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.