vector mit basisklassen in einen mit abgeleiteten klassen casten?
-
@mael15 sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
Die Antwort scheint "nein" zu sein.
- Die Antwort ist, Dein Code ist schlecht – richtig schlecht. Deshalb auch der Hinweis darauf sich noch einmal das Thema
std::vector
durchzulesen. Man nutzt keinen Zeiger auf vector, weil das so keinerlei Sinn ergibt. - Man übergibt niemals einen besitzende POD Zeiger an einen
vector
, das knallt garantiert. - Dazu muss man wissen, dass man einen Downcoast nur mit
dynamic_cast
durchführen darf, d.h.static_cast
hat in diesem Kontext rein gar nichts zu suchen. - Die Basisklasse einer Klassenhierachie muss einen virtuellen Destruktor haben.
- Die Antwort ist, Dein Code ist schlecht – richtig schlecht. Deshalb auch der Hinweis darauf sich noch einmal das Thema
-
Vor einiger Zeit hatte ich eine ähnliche Frage, dort seht noch mehr zum Thema:
std::vector mit unterschiedliche grossen Datentypen.
-
@titan99_ sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
Vor einiger Zeit hatte ich eine ähnliche Frage, dort seht noch mehr zum Thema:
Das Problem hierbei ist, dass der OP selbst sich die Mühe machen muss damit er was dabei lernt. Es ist kein Kunststück ihm funktionierenden modernen Code zu posten. Er müsste halt mal anfangen Verständnisfragen zu stellen – nur da kommt nichts.
-
@titan99_ danke dass du auf meine frage eingehst.
-
@mael15 sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
// kann ich irgendwie folgendes machen? std::vector<E*> *vecE = static_cast<std::vector<E*> *>(vecD);
Nein.
-
vector<D*>
undvector<E*>
sind völlig unterschiedliche Klassen, der gemeinsame Nenner vector täuscht hier. Selbst wennD
undE
Gemeinsamkeiten besitzen oderE
vonD
erbt heisst das nicht, dassvector<D*>
undvector<E*>
diese Gemeinsamkeit übernehmen. Du kannst diese Gemeinsamkeiten/Vererbung nur auf Elementebene ausnutzen, aber nicht für den ganzen Container.
-
@DocShoe sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
vector<D*>
undvector<E*>
sind völlig unterschiedliche Klassen, der gemeinsame Nenner vector täuscht hier. Selbst wennD
undE
Gemeinsamkeiten besitzen oderE
vonD
erbt heisst das nicht, dassvector<D*>
undvector<E*>
diese Gemeinsamkeit übernehmen. Du kannst diese Gemeinsamkeiten/Vererbung nur auf Elementebene ausnutzen, aber nicht für den ganzen Container.Das ist nicht korrekt, da hier POD Zeiger auf Klassen abgelegt werden. Grundsätzlich sind alle Container der C++ Standard Library nicht dafür geeignet, dass man darin besitzende POD Zeiger auf Objekte ablegt, weil das zu UB führt. Wenn man besitzende Zeiger in Container ablegen will, muss man Smart Pointer nutzen d.h. shared_ptr oder unique_ptr.
-
Dann sind, deiner Meinung nach, alle bestehenden C++98-Programme mit
vector<X*>
UB?
-
@john-0 sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
Das ist nicht korrekt, da hier POD Zeiger auf Klassen abgelegt werden. Grundsätzlich sind alle Container der C++ Standard Library nicht dafür geeignet, dass man darin besitzende POD Zeiger auf Objekte ablegt, weil das zu UB führt. Wenn man besitzende Zeiger in Container ablegen will, muss man Smart Pointer nutzen d.h. shared_ptr oder unique_ptr.
soso
-
@DocShoe sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
soso
Was ist
D*
bzw.E*
für ein Typ?
-
@Th69 sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
Dann sind, deiner Meinung nach, alle bestehenden C++98-Programme mit
vector<X*>
UB?Wie wäre es mit korrektem Lesen? Das steht das Wort besitzenden und das sollte man nicht überlesen.
-
@john-0 sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
weil das zu UB führt
Warum?
vector<X*> v; v.push_back( new X );
ist dann UB,
X* aX; aX = new X;
aber nicht?
-
@manni66 sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
Warum?
vector<X*> v; v.push_back( new X );
ist dann UB,
X* aX; aX = new X;
aber nicht?
Beides zusammen leakt
ist UB, da kein delete ausgeführt wird.Wenn man korrekt rohe Zeiger nutzt,
int main () { int* p = new int; // do something with p delete p; }
hier gibt es kein Leak mehr
ist das kein UB, sofern "something" da nicht querschiesst.Aber bei
#include <vector> int main () { std::vector<int*> vec; vec.push_back(new int); // wird hier die Ownership an den Container übertragen } // <- und hier wird der Stack aufgeräumt und dann gibt es ein memory leak.
Bei der main function wird der Müll vom OS aufgeräumt, aber bei jeder anderen Funktion würdest Du hier bei jedem Aufruf ein
int
verlieren – nicht gut.
-
@john-0 sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
Beides zusammen ist UB, da kein delete ausgeführt wird.
Citation needed.
-
@john-0 sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
Beides zusammen ist UB, da kein delete ausgeführt wird.
Ist ein memory leak UB?
Auch "nach" einem vector kann aufgeräumt werden:
int main () { std::vector<int*> vec; vec.push_back(new int); // do something with vec for_each( begin(vec), end(vec), [](auto p) { delete p; } ); }
Aber es ist natürlich völlig richtig, dass besitzende Zeiger besser keine rohen Zeiger sind, ob in einem Container oder nicht.
-
@SeppJ sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
Citation needed.
Sorry, das UB war an der Stelle falsch. Es leakt halt, und könnte in Folge ein UB ergeben. Da war ich in Gedanken schon wieder weiter.
-
@manni66 sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
Auch "nach" einem vector kann aufgeräumt werden:
Nur dann wenn der Container nicht bereits Objekte verloren hat, und der Sinn und Zweck eines Containers ist es, dass man sich genau darum nicht mehr kümmern muss.
-
Ein Memoryleak ist kein UB und führt auch nicht zu UB.
-
@Bashar sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
Ein Memoryleak ist kein UB und führt auch nicht zu UB.
Erstaunlicherweise doch. Ich habe es auch nicht geglaubt und daher nachgeschlagen:
C++-Standard über object-lifetime:
A program may end the lifetime of any object by reusing the storage which the object occupies or by explicitlycalling the destructor for an object of a class type with a non-trivial destructor. For an object of a class typewith a non-trivial destructor, the program is not required to call the destructor explicitly before the storagewhich the object occupies is reused or released; however, if there is no explicit call to the destructor or if adelete-expression(8.5.2.5) is not used to release the storage, the destructor shall not be implicitly called andany program that depends on the side effects produced by the destructor has undefined behavior
Sinn macht die Passage für mich nicht. Warum ist das undefined, wenn die Seiteneffekte nicht passieren, aber sich das Programm darauf verlässt? Sie passieren dann halt nicht, und das Programm ist falsch, aber das sollte doch meines Erachtens nach definiert sein. Da sehe ich keinen Unterschied zu einem Programmierfehler. Aber da steht, dass es undefiniert sei, und dann ist es eben so.
-
@Bashar sagte in vector mit basisklassen in einen mit abgeleiteten klassen casten?:
Ein Memoryleak ist kein UB und führt auch nicht zu UB.
Dir ist schon bewusst, dass z.B. unter Linux in low memory Situationen Prozesse einfach mal so abgeschossen werden?
By default, Linux follows an optimistic memory allocation strategy. This means that when malloc() returns non-NULL there is no guarantee that the memory really is available. In case it turns out that the system is out of memory, one or more processes will be killed by the OOM killer. For more information, see the description of /proc/sys/vm/overcommit_memory and /proc/sys/vm/oom_adj in proc(5), and the Linux kernel source file Documentation/vm/overcommit-accounting.