|
You last visited: Today at 15:01
Advertisement
Struct/MAP in struct speichern?
Discussion on Struct/MAP in struct speichern? within the C/C++ forum part of the Coders Den category.
09/14/2013, 11:58
|
#16
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,904
Received Thanks: 25,394
|
Verstehe ich nicht. Die Einführung des Schlüsselwortes "abstract" hat doch gerade bewirkt, dass man nicht mehr solche hässlichen Exceptions schmeißen muss mit "Not Implemented blabla". Der Compilier erzwingt die Implementation bei abgeleiteten Klassen und verbietet die Instanzierung der abstrakten Klasse. Wo soll da noch Raum sein, eine abstrakte Methode aufzurufen? Das muss schon gezielt mit Workarounds provoziert werden und da ist undefiniertes Verhalten für das Schwein doch genau das richtige. Eine saubere Fehlermeldung hat so jemand nicht verdient :<
|
|
|
09/14/2013, 12:50
|
#17
|
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
|
Und wenn du den Fehler finden musst (weil du für den entsprechenden Teil des Quellcodes verantwortlich bist) und sich herausstellt, das in einer (viel zu tiefen, aber nicht von dir entworfenen) Klassenhierarchie im Konstruktor / Destruktor einer Klasse eine virtuelle Methode aufgerufen wird, obwohl der Teil des Objekts notwendig für diese Implementierung dieser Methode nocht nicht existiert / schon zerstört wurde?
|
|
|
09/14/2013, 13:36
|
#18
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,904
Received Thanks: 25,394
|
Virtuelle Methode im Konstruktor? Tasiro pls..
|
|
|
09/14/2013, 13:49
|
#19
|
elite*gold: 0
Join Date: Dec 2012
Posts: 255
Received Thanks: 110
|
Quote:
Originally Posted by MrSm!th
Verstehe ich nicht. Die Einführung des Schlüsselwortes "abstract" hat doch gerade bewirkt, dass man nicht mehr solche hässlichen Exceptions schmeißen muss mit "Not Implemented blabla". Der Compilier erzwingt die Implementation bei abgeleiteten Klassen und verbietet die Instanzierung der abstrakten Klasse. Wo soll da noch Raum sein, eine abstrakte Methode aufzurufen? Das muss schon gezielt mit Workarounds provoziert werden und da ist undefiniertes Verhalten für das Schwein doch genau das richtige. Eine saubere Fehlermeldung hat so jemand nicht verdient :<
|
Hatte nen Fehler in nem library (luabind), das hat mir irgendwas zerfressen wenn noch shared referenzen übrig waren ( ), aber der lua_State geschlossen wurde. Lief dann im Endeffekt auf nen pure virtual function call raus. Wäre aber fast besser einfach zu crashen, dann hätte mein Filter nen Stacktrace machen können
|
|
|
09/15/2013, 01:09
|
#20
|
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
|
Quote:
Originally Posted by MrSm!th
Virtuelle Methode im Konstruktor?
|
Den Konstruktor hatte ich nur erwähnt, weil es für diesen genauso wie für den Destruktor gilt. Es kann aber tatsächlich dazu kommen:
Code:
//B.h - Arbeitsgruppe B
class A;
class B {
private:
A a;
public:
B ();
virtual void initialize () = 0;
};
//A.h - Arbeitsgruppe A
class A {
private:
B * b;
void initialize_b ();
public:
A (B * b);
};
//A.cc
A::A (B * b) : b (b) {
this->initialize_b ();
}
void A::initialize_b () {
this->b->initialize ();
}
//B.cc
B::B () : a (this) {}
Jetzt werde ein B erstellt.
(Es ist ein Beispiel, nicht mehr.)
Der Aufruf einer virtuellen Funktion ist natürlich warscheinlicher in einem Destruktor.
|
|
|
09/15/2013, 02:42
|
#21
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,904
Received Thanks: 25,394
|
Nur ist das Beispiel absolut nichtssagend, denn von B kannst du sowieso keine Instanz erstellen, da die Klasse abstrakt ist.
Eine erbende Klasse muss initialize implementieren und damit ist das Problem dann auch wieder verschwunden.
Code:
class A
{
protected:
int x;
public:
A(int x)
: x(x) {}
int getX();
virtual void initialize_x() = 0;
virtual void uninitialize_x() = 0;
virtual ~A();
};
int A::getX()
{
return x;
}
A::~A()
{
uninitialize_x();
};
class B : public A
{
public:
B(int x);
virtual void initialize_x();
virtual void uninitialize_x();
virtual ~B();
};
B::B(int x)
: A(x)
{
initialize_x();
}
void B::initialize_x()
{
x *=2;
}
void B::uninitialize_x()
{
x /= 2;
}
B::~B()
{
//andere Aufräumarbeiten
A::~A();
}
int main()
{
A *binst = new B(10); //exception: B::B() ruft A::initialize_x() auf, weil der B Teil der Instanz noch nicht existiert
std::cout << binst->getX() << std::endl;
delete binst; //würde exception werfen, wenn das Programm so weit käme, weil A::~A() A::uninitialize_x() aufruft (da der B Teil bereits zerstört ist)
return 0;
}
Dieses sinnlose Klassenbeispiel verdeutlicht schon eher, was du mir sagen willst.
Und darauf antwortete ich schon passend: Calls zu virtuellen Funktionen haben weder im Kon- noch im Destruktor etwas verloren.
|
|
|
09/15/2013, 11:50
|
#22
|
elite*gold: 0
Join Date: Jul 2013
Posts: 16
Received Thanks: 1
|
struct EventGift
{
DWORD dwID;
int nCount;
int nPercentage;
};
struct EventMonster
{
DWORD dwID;
int nInerval;
int nPercentage;
map<DWORD,EventGift> m_aEventGift;
};
class AutoEvent
{
public:
map<DWORD, EventMonster> m_aEventMonster;
AutoEvent();
~AutoEvent();
void ReadInc();
void Process();
};
|
|
|
09/15/2013, 12:22
|
#23
|
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
|
Quote:
Originally Posted by MrSm!th
Eine erbende Klasse muss initialize implementieren und damit ist das Problem dann auch wieder verschwunden.
|
Ist es nicht, zum Zeitpunkt der Konstruktion bzw. Destruktion eines Bs ist der this-Zeiger (für den Aufruf virtueller Funktionen) immer ein Zeiger auf ein B und nicht auf eine von B abgeleiteten Klasse, damit kann die aufgerufene Funktion statisch ermittelt werden (siehe §12.7.4).
Ähnliches Verhalten bei Rückruffunktionen, welche im Destruktor aufgerufen werden können und auf das eigentliche Objekt zugreifen können.
Dein Beispiel tut übrigens nicht das, was du sagst, initialize_x wird erst nach Erstellen aller Felder von B aufgerufen (aber vor dem Konstruktor einer von B abgeleiteten Klasse, in B sollte initialize_x mit final versehen werden - und mit override).
Wenn eine virtuelle Funktion im Destruktor (oder im Konstruktor...) aufgerufen wird, so geschieht das für gewöhnlich nicht absichtlich, aber es passiert hin und wieder.
|
|
|
09/15/2013, 19:11
|
#24
|
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,904
Received Thanks: 25,394
|
Ich habe nichts dazu gesagt, wann initialize_x() in Bezug auf die Felder von B aufgerufen wird - ist mir schon klar, dass der Konstruktorrumpf nach deren Konstruktion aufgerufen wird.
Aber ich habe mich vertan, natürlich muss initialize_x() ebenfalls in den Konstruktor von A und nicht in den von B. Dann stimmt der Sinn des Beispiels auch wieder.
Quote:
Ist es nicht, zum Zeitpunkt der Konstruktion bzw. Destruktion eines Bs ist der this-Zeiger (für den Aufruf virtueller Funktionen) immer ein Zeiger auf ein B und nicht auf eine von B abgeleiteten Klasse, damit kann die aufgerufene Funktion statisch ermittelt werden (siehe §12.7.4).
Ähnliches Verhalten bei Rückruffunktionen, welche im Destruktor aufgerufen werden können und auf das eigentliche Objekt zugreifen können.
|
Ist es wohl, wenn man sich an die Regel hält, virtuelle Funktionen in Konstruktoren nicht aufzurufen.
Nun gut, für den Fall der Fälle kannst du natürlich die Funktion dennoch definieren und eine Exception schmeißen lassen. Durch sauberes Programmieren geht es imho aber auch ohne, alleine mit den Absicherungen des Compilers bei Verwendung von abstrakten Klassen.
|
|
|
09/15/2013, 20:40
|
#25
|
elite*gold: 0
Join Date: Aug 2012
Posts: 236
Received Thanks: 94
|
Quote:
Originally Posted by MrSm!th
Ist es wohl, wenn man sich an die Regel hält, virtuelle Funktionen in Konstruktoren nicht aufzurufen.
|
Welches Problem ist verschwunden? Der Aufruf einer (da) rein virtuellen Funktion im Kon-/Destruktor? Wenn nichts aufgerufen wird, gibt es kein Problem, allerdings.
Dann dürfen also übergebene Funktionsobjekte nicht im Kon-/Destruktor aufgerufen werden, wenn es eine Klasse ist, die eine (u. U. private) Basisklasse mit einer (nicht notwendigigerweise rein) virtuellen Funktion hat?
Quote:
Originally Posted by MrSm!th
Nun gut, für den Fall der Fälle kannst du natürlich die Funktion dennoch definieren und eine Exception schmeißen lassen. Durch sauberes Programmieren geht es imho aber auch ohne, alleine mit den Absicherungen des Compilers bei Verwendung von abstrakten Klassen.
|
Eine Klasse ist (in C++) dann abstrakt, wenn sie mindestens eine nicht überschriebene rein virtuelle Funktion hat. Ob eine rein virtuelle Funktion dann tatsächlich auch eine Implementierung hat, ist dafür irrelevant, sie bleibt rein virtuell. Deshalb sind es ja gerade diese Sonderfälle mit Konstruktor und Destruktor und unangebracht statischen Typkonvertierungen (und natürlich Parallelität), welche zu solchen Aufrufen führen.
|
|
|
09/17/2013, 21:43
|
#26
|
elite*gold: 4
Join Date: Mar 2010
Posts: 3,148
Received Thanks: 1,535
|
mein goot ist der thread ausgeatet, habs nun geschafft. lag wirklich an dem ZeroMemory
danke!
#closerrequest
|
|
|
09/19/2013, 22:40
|
#27
|
elite*gold: 900
Join Date: Apr 2009
Posts: 14,976
Received Thanks: 11,388
|
closed on request
|
|
|
|
|
Similar Threads
|
[help] new, delete, struct
01/23/2013 - C/C++ - 9 Replies
Well, i have a structure, input and output functions, to get some data, now i would like to make the following:
-the user inputs a number (for which i need a dynamic memory reservation)
-and that number declares how many times the input should loop)
so for example the use puts in 4; it will run the input function 4 times he can tpye in stuff for 4 different companyes or w/e ... same with the output
Here is waht i ahev for now:
|
Struct Allokieren ?
12/08/2012 - C/C++ - 11 Replies
Hallo,
Ich arbeite mich gerade durch das Buch C++ A - Z und bin gerade bei den Structuren, so
jetzt habe ich mir als beispiel ein kleines (Telefon Buch) gemacht ganz simpel (Vorname, Nachname, Geschlecht, Nummer)
Code
#include "stdafx.h"
using namespace std;
|
struct and classes
08/03/2012 - CO2 Programming - 6 Replies
took about 50 pages reading about difference between structs and classes , so i thought it's good idea to sum up this for whoever want to get it with a spoon , feel free to correct or add information
at struct cannot have instance field initializers in structs
struct time
{
private int x = 5; // compile-time error
}
Structs cannot contain explicit parameterless constructors
struct time
{
|
[c++] struct
08/25/2011 - C/C++ - 2 Replies
Kann closed werden. sry
|
Packet Struct's
05/02/2009 - Kal Online - 30 Replies
Mir war langweilig hier nen beispiel wie ihr wie ich finde alles bischen besser aussehn lassen könnt :P
struct PacketsSend
{
DWORD VersionCheck;
DWORD Login;
DWORD Ping;
DWORD Skill;
DWORD Chat;
|
All times are GMT +2. The time now is 15:01.
|
|