verschiedene Klassen in einem Vektor
-
Definiere move und render als virtuelle Methoden in CBase und leite alle Klassen die in den Vector sollen (als CShip, CTree) von CBase ab. Wenn Du denn Vektor dann so deklarierst:
std::vector<CBase*> g_vTest;
,kannst du Du move und render von allen deinen Objekten in einer Schleife aufrufen.
-
Und als kleinen Bonus kannst du die Objekte dann ohne undefiniertes Verhalten freigeben, wenn du ihnen einen virtuellen Konstruktor spendierst. Ansonsten hätte "delete v[i]" vermutlich nur den Speicher freigegeben, aber den Destruktor nie aufgerufen.
-
Definiere move und render als virtuelle Methoden in CBase und leite alle Klassen die in den Vector sollen (als CShip, CTree) von CBase ab. Wenn Du denn Vektor dann so deklarierst:
Daran hatte ich auch gedacht, aber es gibt ja in verschiedenen Klassen auch verschiedenen Variablen. z.B. in der Klasse CTree nicht nur Move und Render, sondern auch int m_iNumberOfBlätta, in der CShip-Klasse gibt es eine Variable zu den Waffen... Wie kann man soetwas darin hineinbauen
Danke,
Mfg
-
struct base { virtual void move(); virtual void render(); }; class tree : public base; { private: node irgendwas; public: void move(); void render(); void addNode(......); }
-
Aha,
aber, wenn ich es so mache wie du, muss ich immer noch viel, viel Casten. Zu viel, um ehrlich zu sein. Ich könnte nämlich nicht sagen:
m_vEinheiten[0]=new CTree; m_vEinheiten[0]->addNode(); // falsch, da kein Objekt von CBase static_cast<CTree*>(m_vEinheiten[0])->addNode(); // richtig
danke,
__Anfänger__
-
OT-Frage an davie und Bashar:
Warum nimmt man in diesem Fall static_cast? Es handelt sich doch in beiden Fällen um Pointer, die nur anders interpretiert werden - wäre das nicht ein Grund für den gleichnamigen reinterpret_cast? Oder gibt es Systeme, auf denen ein void-Pointer eine andere Größe besitzt als einer auf eine Klasse?
-
naja, um das casten wirst nicht drumherumkommen, wenn du nicht auf der basisfunktionalitaet sitzen bleiben willst. Oder du machst halt alles zu basisfunktionen, und manche objecte machen dann halt gar nix da ... auch keine so elegante Loesung.
Irgendwie muesstest dein komplettes strukturelles design dann aendern, wenn sowas vermeiden willst .
Woher weisst du z.b. das an pos 0 im vector nen CTree sitzt ?
wenn die info nur beim einfuegen brauchst, musst naturlich ned casten ...CTree * pTree = new CTree; pTree->addNode(); m_vEinheiten[0]=pTree;
Mir waeren die 4byte mehr aufn stack lieber als der cast :p
Prinzipiell ists eh fast immer ne gute Idee, containerklassen zu kapseln und zu spezialisieren ... besonders wennst da drinnen Zeiger auf dynamisch erzeugten Objekten hast . Ansonsten ist die gefahr zu gross, das man die obejekte ned loescht, wenn der container verworfen wird ... oder das man die inhalte der container kopiert, und zeiger aus dem einem samt Objekt loescht und aus dem anderen nicht ....
Ciao ...
-
Cocaine schrieb:
Warum nimmt man in diesem Fall static_cast? Es handelt sich doch in beiden Fällen um Pointer, die nur anders interpretiert werden - wäre das nicht ein Grund für den gleichnamigen reinterpret_cast?
Normalerweise braucht man reinterpret_cast um einen Pointer-Typ in einen anderen umzuwandeln. Da es aber automatische Konvertierungen jedes Pointer-Typs nach void* gibt, kann man den umgekehrten Weg auch mit static_cast gehen. Genauso beim Downcast in einer Hierarchie ... von base* nach derived* komm ich mit static_cast.
static_cast ist ein scharfes Messer und reinterpret_cast eine Kettensäge, im Zweifelsfall nehme ich das schwächste Werkzeug was den Job noch tut
-
reinterpret_cast<>() ist doch der unsicherste von allen (den C-Cast mal ausgenommen) ... er macht nix anderes als die bitfolge einfach anders zu interpretieren ?
static_cast<>() dagegen beruecksichtig die standard conversionen von datentypen .... und mault, wenn was eigentlich nicht gehen sollte (wenn der compiler denkt es geht ned, long nach char z.b.) ...
bei nem pointer zu pointer cast gehen beide, und ich wuerd den "sichereren" nehmen ...
castest den Pointer dagegen polymorph hoch, so wie es mittels der gemeinsamen Basisklasse im Thread vorher vorgeschlagen wurde ... dann kommt wahrscheinlich dynamic_cast<>() ins Spiel ... (wenn RTI eingeschalten)
Ciao ...
-
RHBaum schrieb:
bei nem pointer zu pointer cast gehen beide, und ich wuerd den "sichereren" nehmen ...
Das war mir schon klar, nur suchte ich nach dem Grund für static_cast.
Bashar schrieb:
Da es aber automatische Konvertierungen jedes Pointer-Typs nach void* gibt, kann man den umgekehrten Weg auch mit static_cast gehen. Genauso beim Downcast in einer Hierarchie ... von base* nach derived* komm ich mit static_cast.
Danke, das erklärt's
-
nur suchte ich nach dem Grund für static_cast.
Paranoia ?
Ciao ...
-
Also,
ich hab das jetzt so gemacht (nicht ganz so, aber man könnte es so sehe):
class CBase : public CIrgendeineKlasseVonDerEngine { public: int m_iLebenspunkte... BOOL IstSichtbar; virtual void Render(float fTime)=0; virtual void Move(float fTime)=0; } // ... class CPlane : public CBase { public: int m_iAnzahlSchüsse; void Render(float fTime)=0; void Move(float fTime)=0; }
std::vector<CObject*> vObject; vObject.resize(1); vObject[0]=new CPlane;
Wenn ich aber nun vObject->Move() oder vObject->Render() aufrufe, stürzt der Computer ab, bzw. springt in die Zeile, bei der die Funktion aufgerufen wurde. Die eigentlich Funktion wurde aber nicht aufgerufen.
Hat jemand eine Idee, was falsch ist,
Danke
-
Was meinte eigentlich operator void? Das habe ich auch nicht ganz verstanden...
-
Nimm doch ma das =0 am Ende der Methodendeklarationen der abgeleiteten Klasse weg...
-
Schuldigung.
Heißt natürlich virtual void Render(); und auch BOOL IsVisible**()**
Hoffe, dass mein Problem gelöst werden kann,
Danke,
__Anfänger__
PS: und wie ist das nun mit dem
Und als kleinen Bonus kannst du die Objekte dann ohne undefiniertes Verhalten freigeben, wenn du ihnen einen virtuellen Konstruktor spendierst. Ansonsten hätte "delete v[i]" vermutlich nur den Speicher freigegeben, aber den Destruktor nie aufgerufen...
-
Kurz:
struct Base {}; struct Derived : Base {}; Base* b = new Derived; delete b;
Was die letzte Zeile tut, ist undefiniert, weil Base keinen virtuellen Destruktor hat. Richtig geht es so:
struct Base { virtual ~Base() {} };
Als Faustregel sollten Basisklassen einer Hierarchie einen virtuellen Destruktor und privaten Kopierkonstruktor und Zuweisungsoperator haben. Also mal ausführlich:
class Base { private: // Werden nie definiert. So kann man nicht aus Versehen einer Base- // Instanz eine Derived-Instanz zuweisen. Base(const Base&); Base& operator=(const Base&); public: // Erlaubt definiertes Löschen durch ein Base* virtual ~Base() {} };
-
Aha,
das ist klar. Leider stürzt das Pogramm immer noch ab. Ich hab schon hunderte Versuche unternommen, aber es passiert immer noch. Auch, wenn externe Objekte (also nicht Objekte innerhalb des Vektors) gerendert oder bewegt werden sollen. Der Debugger sagt mir soweit gar nichts, außer Acress violation.
Kann vielleicht jemand etwas damit anfangen?
Danke
-
vObject ist doch deine Liste ?
Und Move und Render sind Methoden deiner ListObjecte ?muesste also maximal heissen vObject[0]->Move(); oder so ?
aber ich nehm mal an, das meintest du auch ? Kompilieren wuerde er das so nich :p Und zeig mal, wie du die casts machst ? Da deine Listelemente ned vom typ CBase sind, kennt der compiler das move und render ned ... erst nach dem cast ...
CObject ist das der MFC Typ, oder selbst definiert ?Ciao ...
-
Hast du denn schon das gemacht was D1BAKEL gesagt hat?
-
Ja, hast du schonmal gemacht, was ich gesagt hab???