<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Konstruktor&#x2F;Dekonstruktor Fragen:]]></title><description><![CDATA[<p>Hallo Forum,</p>
<p>ich benutze eine DLL in meinem Projekt. Bevor ich die DLL benutzen kann muß ich ein paar Init Funktionen aufrufen. Wenn ich die DLL nicht mehr brauche muß ich ein paar MakeClean Funktionen aufrufen. Sowohl Init als auch MakeClean dürfen nur einmal aufgerufen werden: Mache ich das mehrmals werden zB. Exceptions beim delete des Objektes geworfen das im Dekonstruktor die MakeClean Funktion hat.</p>
<p>1. Ich dachte mir folgendes: Ich packe Init/MakeClean in eine Klasse von der alle Klassen die die DLL bentzen abgeleiten müssen. Ich kann über eine static Variable mir merken ob die Init Routine schon einmal aufgerufen wurde. Aber wie kriege ich es hin das der Dekonstruktor dann aufgerufen wird wenn es keine Objekte der Basisklassen mehr gibt? Gibt es da ein Konstrukt das ich übersehen habe oder muß ich jetzt die Konstruktoraufrufe zahlenmäßig mit denen der Dekonstruktoraufrufe verrechnen?</p>
<p>2. Unabhängig von obigem Problem: Wenn ich in der Klasse den Konstruktor komplett weglasse wird ein Standard Konstruktor eingefügt. Gibt es zu diesem einen Unterschied wenn mein Konstruktor so aussieht?</p>
<pre><code class="language-cpp">MyClass::MyClass() {}
</code></pre>
<p>3. Warum muß der Dekonstruktor virtual sein?</p>
<pre><code class="language-cpp">A)
class MyClass {
~MyClass() {DoSomething();}; // Hier wird er immer bei der Zerstörung von MyClass aufgerufen.
}

B)
class MyClass {
virtual ~MyClass() {DoSomething();} // Hier kann er überschrieben werden.
}
class Derived : MyClass {
~MyClass() {} // Habe ich so den Aufruf von DoSomething() verhindert?
}

C)
class MyClass {
virtual ~MyClass()=0; // Hier muß er überschrieben werden.
}
class Derived : MyClass {
~MyClass() {DoSomething();} // Hier wird der BasisklassenDekonstruktor erstellt.
~Derived() {DoAbc();} // Hier der Dekonstruktor der abgeleiteten Klasse.
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/topic/190407/konstruktor-dekonstruktor-fragen</link><generator>RSS for Node</generator><lastBuildDate>Fri, 25 Sep 2026 14:59:03 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/190407.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 22 Aug 2007 11:27:57 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Konstruktor&#x2F;Dekonstruktor Fragen: on Wed, 22 Aug 2007 11:27:57 GMT]]></title><description><![CDATA[<p>Hallo Forum,</p>
<p>ich benutze eine DLL in meinem Projekt. Bevor ich die DLL benutzen kann muß ich ein paar Init Funktionen aufrufen. Wenn ich die DLL nicht mehr brauche muß ich ein paar MakeClean Funktionen aufrufen. Sowohl Init als auch MakeClean dürfen nur einmal aufgerufen werden: Mache ich das mehrmals werden zB. Exceptions beim delete des Objektes geworfen das im Dekonstruktor die MakeClean Funktion hat.</p>
<p>1. Ich dachte mir folgendes: Ich packe Init/MakeClean in eine Klasse von der alle Klassen die die DLL bentzen abgeleiten müssen. Ich kann über eine static Variable mir merken ob die Init Routine schon einmal aufgerufen wurde. Aber wie kriege ich es hin das der Dekonstruktor dann aufgerufen wird wenn es keine Objekte der Basisklassen mehr gibt? Gibt es da ein Konstrukt das ich übersehen habe oder muß ich jetzt die Konstruktoraufrufe zahlenmäßig mit denen der Dekonstruktoraufrufe verrechnen?</p>
<p>2. Unabhängig von obigem Problem: Wenn ich in der Klasse den Konstruktor komplett weglasse wird ein Standard Konstruktor eingefügt. Gibt es zu diesem einen Unterschied wenn mein Konstruktor so aussieht?</p>
<pre><code class="language-cpp">MyClass::MyClass() {}
</code></pre>
<p>3. Warum muß der Dekonstruktor virtual sein?</p>
<pre><code class="language-cpp">A)
class MyClass {
~MyClass() {DoSomething();}; // Hier wird er immer bei der Zerstörung von MyClass aufgerufen.
}

B)
class MyClass {
virtual ~MyClass() {DoSomething();} // Hier kann er überschrieben werden.
}
class Derived : MyClass {
~MyClass() {} // Habe ich so den Aufruf von DoSomething() verhindert?
}

C)
class MyClass {
virtual ~MyClass()=0; // Hier muß er überschrieben werden.
}
class Derived : MyClass {
~MyClass() {DoSomething();} // Hier wird der BasisklassenDekonstruktor erstellt.
~Derived() {DoAbc();} // Hier der Dekonstruktor der abgeleiteten Klasse.
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1349715</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1349715</guid><dc:creator><![CDATA[martin_salo]]></dc:creator><pubDate>Wed, 22 Aug 2007 11:27:57 GMT</pubDate></item><item><title><![CDATA[Reply to Konstruktor&#x2F;Dekonstruktor Fragen: on Wed, 22 Aug 2007 11:32:50 GMT]]></title><description><![CDATA[<p>generell:<br />
bei allen klassen die als basisklasse fungieren sollte man den destruktor viruell deklaieren.</p>
<pre><code class="language-cpp">class MyClass {
virtual ~MyClass() {DoSomething();} // Hier kann er überschrieben werden
</code></pre>
<p>ansonsten müllst du deinen speicher bei solchen anweisungen zu:</p>
<pre><code class="language-cpp">Base *ptr = new Derived;
delete ptr; //hier würde ohne virtuel nur der basisklassenanteil zerstört werden
            //der derived anteil würd eunreferenziert im speicher verweilen
</code></pre>
<p>ein bsp aus einem anderen thread von mir:<br />
(so soll es aussehen)</p>
<pre><code class="language-cpp">class Base{ 
public: 
Base() {std::cout&lt;&lt;&quot;Base&quot;&lt;&lt;std::endl; } 
virtual ~Base(){ std::cout&lt;&lt;&quot;~Base&quot;&lt;&lt;std::endl;} 
}; 

class D1 : public Base { 
D1 () {std::cout&lt;&lt;&quot;D1 &quot;&lt;&lt;std::endl; } 
~D1(){ std::cout&lt;&lt;&quot;~D1 &quot;&lt;&lt;std::endl;} 
 }; 

class D2 : public D1 { 
D2 () {std::cout&lt;&lt;&quot;D2 &quot;&lt;&lt;std::endl; } 
~D2(){ std::cout&lt;&lt;&quot;~D2 &quot;&lt;&lt;std::endl;}   
}; 

int main() 
{ 
  D2 d1; 
std::cout&lt;&lt;std::endl; 
}  

//output auf der konsole
Base 
D1 
D2 

~D2 
~D1 
~Base
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1349716</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1349716</guid><dc:creator><![CDATA[muffmolch]]></dc:creator><pubDate>Wed, 22 Aug 2007 11:32:50 GMT</pubDate></item><item><title><![CDATA[Reply to Konstruktor&#x2F;Dekonstruktor Fragen: on Wed, 22 Aug 2007 11:38:06 GMT]]></title><description><![CDATA[<p>@1: Du solltest die Initialisierung/Aufräumarbeiten in einem Singleton unterbringen - oder du nutzt gleich die DllMain() für sowas.</p>
<p>@2: Wenn du nicht explizit über die Initialisierungsliste einen anderen Ctor anforderst, wird der Default-Konstruktor der Basisklasse aufgerufen - das ist in der Tat identisch zu deinem leeren Ctor. (aber wenn du irgendeinen eigenen Ctor anlegst, bekommst du keinen automatisch erzeugten Default-Ctor mehr - dann mußt du notfalls einen eigenen erzeugen)</p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/5290">@3</a>: Ein virtueller Destruktor ist nicht nötig für Vererbung, aber für polymorphe Verwendung der Klassen:</p>
<pre><code class="language-cpp">base*p = new derived;
...
delete p;
</code></pre>
<p>(ohne virtuellen Dtor löschst du damit bestenfalls den base-Anteil von *p - afair ist sogar undefiniert, was dort herauskommt)</p>
<p>@Beispieltext:<br />
B verhindert nicht, daß 'DoSomething()' aufgerufen wird - mit dem 'virtual' sicherst du nur ab, daß auch Derived aufgeräumt werden kann.<br />
C ist Käse - niemand darf fremde Destruktoren definieren (und auch ein pur virtueller Dtor muß definiert werden, sonst fliegt er dir um die Ohren).</p>
<p>PS: Das heißt übrigens nicht &quot;Dekonstruktor <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1349720</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1349720</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Wed, 22 Aug 2007 11:38:06 GMT</pubDate></item><item><title><![CDATA[Reply to Konstruktor&#x2F;Dekonstruktor Fragen: on Wed, 22 Aug 2007 13:50:11 GMT]]></title><description><![CDATA[<p>Ich habe die Beispiele von Muffmolch ausprobiert. Der Destruktor von Base wird nur aufgerufen wenn er virtual ist. Das führt auf die Diskussion was virtual eigentlich soll? (Ich meine nicht pure virtual). Auch ohne virtual kann ich jede Methode überschreiben. Nach CStoll macht virtual bei der Vererbung keinen Sinn. Was meint polymorphe Verwendung? Könnte man dieses Vererbungsbeispiel so umstricken das der Sinn von virtual sichtbar wird?</p>
<pre><code class="language-cpp">class Vater{
public:
	Vater() {
		std::cout&lt;&lt;&quot;Vater&quot;&lt;&lt;std::endl;
	}
	virtual ~Vater() {
		std::cout&lt;&lt;&quot;~Vater&quot;&lt;&lt;std::endl;
	}
	// Ob ich nun diese Funktion virtual mache oder nicht scheint vollkommen Latte
	// zu sein. Egal ob ich nun DoIt in Kind überschreibe oder nicht.
	virtual void DoIt() {
		std::cout&lt;&lt;&quot;DoIt Vater&quot;&lt;&lt;std::endl;
	}
};

class Kind : public Vater {
public:
	Kind() {
		std::cout&lt;&lt;&quot;Kind&quot;&lt;&lt;std::endl;
	}
	~Kind() {
		std::cout&lt;&lt;&quot;~Kind&quot;&lt;&lt;std::endl;
	}
	void DoIt() {
		std::cout&lt;&lt;&quot;DoIt Kind&quot;&lt;&lt;std::endl;
	}
};

int main() {
	Kind *K;
	K = new Kind();
	K-&gt;DoIt(); // Hier wird nur DoIt vom Kind ausgeführt?
	delete K; // Hier werden aber beide Destruktoren ausgeführt?
	return 0;
}
</code></pre>
<p>2. Singleton<br />
Wann wird der Dekonstruktor aufgerufen? Solange irgendwo noch ein Pointer auf dem Singleton ist geht es wohl nicht. Sobald der letzte Pointer aber weg ist kann das Objekt jederzeit zerstört werden. Korrekt? (Je nachdem wie der Kompiler das organisiert, einen Garbage Kollektor scheint es unter c++ nicht zugeben.)</p>
<pre><code class="language-cpp">class Singleton {
	private:
		//Konstruktor private, damit man sich keine Instanzen holen kann.
		Singleton() {
			// Hier eine Init Methode die nur einmal aufgerufen werden soll.
		}
		//Den Kopierkonstruktor schützen um zu vermeiden, dass das Objekt unbeabsichtigt kopiert wird.
		Singleton(const Singleton&amp; cc){
		}

	public:
		~Singleton() {
			// Hier die Aufräumfunktionen die auch nur einmal aufgerufen werden sollen.
		}
		static Singleton* getInstance() {
			static Singleton instance; 
			return &amp;instance; 
		}
};

int main() {
	Singleton *S = Singleton::getInstance();
	return 0;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1349818</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1349818</guid><dc:creator><![CDATA[martin_salo]]></dc:creator><pubDate>Wed, 22 Aug 2007 13:50:11 GMT</pubDate></item><item><title><![CDATA[Reply to Konstruktor&#x2F;Dekonstruktor Fragen: on Wed, 22 Aug 2007 13:59:56 GMT]]></title><description><![CDATA[<p>martin_salo schrieb:</p>
<blockquote>
<p>Ich habe die Beispiele von Muffmolch ausprobiert. Der Destruktor von Base wird nur aufgerufen wenn er virtual ist. Das führt auf die Diskussion was virtual eigentlich soll? (Ich meine nicht pure virtual). Auch ohne virtual kann ich jede Methode überschreiben. Nach CStoll macht virtual bei der Vererbung keinen Sinn. Was meint polymorphe Verwendung? Könnte man dieses Vererbungsbeispiel so umstricken das der Sinn von virtual sichtbar wird?</p>
</blockquote>
<p>Entweder ich habe mich falsch ausgedrückt oder du hast mich falsch verstanden - virtual ohne Vererbung macht keinen Sinn, aber man kann auch ohne virtual vererben. Und Polymorphie bedeutet, daß erst zur Laufzeit feststeht, was für ein Objekt du hast.</p>
<blockquote>
<pre><code class="language-cpp">class Vater{
public:
	Vater() {
		std::cout&lt;&lt;&quot;Vater&quot;&lt;&lt;std::endl;
	}
	virtual ~Vater() {
		std::cout&lt;&lt;&quot;~Vater&quot;&lt;&lt;std::endl;
	}
	// Ob ich nun diese Funktion virtual mache oder nicht scheint vollkommen Latte
	// zu sein. Egal ob ich nun DoIt in Kind überschreibe oder nicht.
	virtual void DoIt() {
		std::cout&lt;&lt;&quot;DoIt Vater&quot;&lt;&lt;std::endl;
	}
};

class Kind : public Vater {
public:
	Kind() {
		std::cout&lt;&lt;&quot;Kind&quot;&lt;&lt;std::endl;
	}
	~Kind() {
		std::cout&lt;&lt;&quot;~Kind&quot;&lt;&lt;std::endl;
	}
	void DoIt() {
		std::cout&lt;&lt;&quot;DoIt Kind&quot;&lt;&lt;std::endl;
	}
};

int main() {
	Kind *K;
	K = new Kind();
	K-&gt;DoIt(); // Hier wird nur DoIt vom Kind ausgeführt?
	delete K; // Hier werden aber beide Destruktoren ausgeführt?
	return 0;
}
</code></pre>
</blockquote>
<p>Ändere mal die main() um zu:</p>
<pre><code class="language-cpp">Vater* ptr = new Kind();
ptr-&gt;DoIt();
delete ptr;
</code></pre>
<p>Dann siehst du den Unterschied zwischen virtual und nicht-virtual.</p>
<blockquote>
<p>2. Singleton<br />
Wann wird der Dekonstruktor aufgerufen? Solange irgendwo noch ein Pointer auf dem Singleton ist geht es wohl nicht. Sobald der letzte Pointer aber weg ist kann das Objekt jederzeit zerstört werden. Korrekt? (Je nachdem wie der Kompiler das organisiert, einen Garbage Kollektor scheint es unter c++ nicht zugeben.)</p>
</blockquote>
<p>Die einzige je existierende Singleton-Variable ist static - und damit wird sie bei einem regulären Programmende (exit() oder return aus der main()) auch normal zerstört. (bei einem Absturz allerdings nicht - aber bei einem Absturz ist sowieso nichts mehr zu retten)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1349825</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1349825</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Wed, 22 Aug 2007 13:59:56 GMT</pubDate></item><item><title><![CDATA[Reply to Konstruktor&#x2F;Dekonstruktor Fragen: on Wed, 22 Aug 2007 14:28:47 GMT]]></title><description><![CDATA[<p>Wenn ich die Methode nicht virtual mache wir in CStolls Erweiterung immer nur die Funktion des Vaters aufgerufen. Ok, so macht virtual Sinn. Zum Destruktor: Ohne virtual gäbe es diesen VTable nicht. Die C++ Laufzeitumgebung könnte nicht alle Destruktoren der Vererbungshierachie nach geordnet aufrufen.</p>
<p>Zu static Variablen: Wenn werden diese aus dem Speicher entfernt? Immer erst nach Programmende? Bei Funktionen ist es ja so das die static Variablen beim nächsten Funktionsaufruf wieder mit den gleichen Werten belegt sind.</p>
<p>Wie wäre das bei Threads? Wenn ich eine Klasse in verschiedenen Threads instanziiere, haben dann die static Variablen den gleichen Wert? Wahrscheinlich nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1349841</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1349841</guid><dc:creator><![CDATA[martin_salo]]></dc:creator><pubDate>Wed, 22 Aug 2007 14:28:47 GMT</pubDate></item><item><title><![CDATA[Reply to Konstruktor&#x2F;Dekonstruktor Fragen: on Wed, 22 Aug 2007 15:32:05 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>martin_salo schrieb:</p>
<blockquote>
<p>Zu static Variablen: Wenn werden diese aus dem Speicher entfernt? Immer erst nach Programmende?</p>
</blockquote>
<p>Ja, übrigens gilt das auch für statics in Funktionen, denn was du schreibst ist nicht ganz eindeutig:</p>
<p>martin_salo schrieb:</p>
<blockquote>
<p>Bei Funktionen ist es ja so das die static Variablen beim nächsten Funktionsaufruf wieder mit den gleichen Werten belegt sind.</p>
</blockquote>
<p>Etwas &quot;unscharf&quot;: Eine static-Variable wird angelegt (und initialisiert) beim ersten Aufruf, JEDER weitere Aufruf greift auf die gleiche Variable zu. Sie sind nicht nur mit gleichen Werten belegt, sie sind auch physikalisch gleich.</p>
<p>martin_salo schrieb:</p>
<blockquote>
<p>Wie wäre das bei Threads? Wenn ich eine Klasse in verschiedenen Threads instanziiere, haben dann die static Variablen den gleichen Wert? Wahrscheinlich nicht.</p>
</blockquote>
<p>Doch, weil es genau der gleiche Speicherbereich ist. Daher muss man mit statics und Threads besonders stark aufpassen!</p>
<p>Vielleicht noch eine Ergänzung: globale statics werden in nicht festgelegter Reihenfolge initialisiert, statics in Methoden wiederum erst wenn die Methode das erste mal aufgerufen wird. Dies ist besonders dann wichtig falls man abhängigkeiten in statics hat (Im Zweifel ist die Abfrage über eine Methode sicherer, da die Reihenfolge zumindest definiert ist).</p>
<p>cu André</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1349881</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1349881</guid><dc:creator><![CDATA[asc]]></dc:creator><pubDate>Wed, 22 Aug 2007 15:32:05 GMT</pubDate></item></channel></rss>