 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Kirsten Guest
|
Posted: Mon Oct 04, 2004 10:49 pm Post subject: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Hi Leut,
Man lasse folgenden kurzen Pseudo-Code mal kurz auf sich wirken:
-----------------------
class GeneralPlayer
{
public:
GeneralPlayer();
~GeneralPlayer()
{
Stop();
}
virtual void Start();
virtual void Stop();
}
class WAVPlayer: public GeneralPlayer
{
protected:
void *BufferAllocated;
public:
WAVPlayer();
~WAVPlayer()
{
delete BufferAllocated;
}
virtual void Start();
virtual void Stop()
{
// Einfach irgendwas mit dem reservierten Speicher machen
memset(BufferAllocated,0,1024);
}
};
-----------------------
Ich hoffe man erkennt meine Absichten: ich will eine Basisklasse eines
AudioPlayers definieren. In dessen Destruktor wird Stop() aufgerufen!
Der Player soll also das Spielen beenden. ABER: Ich darf Stop() nicht
im Destruktor aufrufen! Aufgrund der Reihenfolge der Destruktoren wird
ja leider der Destruktor von WAVPlayer VOR dem Destruktor von
GeneralPlayer aufgerufen. Folglich wird Stop() im Destruktor von
GeneralPlayer erst aufgerufen, wenn der benötigte BufferAllocated
bereits vom Destruktor von WAVPlayer ferigegeben wurde.
Natürlich ein Problem!
Ok, ich checke selber, dass es mit diesem Design nicht funktionieren
kann, aber es muss doch einen Weg geben, dass ich in GeneralPlayer
definiere, dass der Player gestoppt wird bzw. Stop() aufgerufen wird,
wenn das Objekt freigegeben wird! ABER das alles muss passieren bevor
WAVPlayer Resourcen bereits freigibt...
Profis für solche Angelegenheiten hier?
Kleine Feature-Lücke in C++?
THX,
Kirsten
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Christoph Horst Guest
|
Posted: Tue Oct 05, 2004 9:33 am Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Hallo,
Kirsten wrote:
| Quote: | class GeneralPlayer
{
public:
GeneralPlayer();
~GeneralPlayer()
{
Stop();
}
virtual void Start();
virtual void Stop();
}
|
Bedenke bitte zusätzlich zu deinem primären Design-Problem, dass der
Stop-Aufruf im Destruktor statisch gebunden ist, d.h. dass die
Stop-Methode der GeneralPlayer-Klasse aufgerufen wird.
(Streng genommen ist es nicht statisch gebunden, aber das Objekt macht
während des Konstruktions- und Destruktionsvorgangs eine Änderung des
dynamischen Typs durch.)
--
better implies different
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Philipp Bachmann Guest
|
Posted: Tue Oct 05, 2004 10:29 am Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
| Quote: | class GeneralPlayer
{
public:
GeneralPlayer();
~GeneralPlayer()
{
Stop();
}
virtual void Start();
virtual void Stop();
}
class WAVPlayer: public GeneralPlayer
{
protected:
void *BufferAllocated;
public:
WAVPlayer();
~WAVPlayer()
{
delete BufferAllocated;
}
virtual void Start();
virtual void Stop()
{
// Einfach irgendwas mit dem reservierten Speicher machen
memset(BufferAllocated,0,1024);
}
};
Ich hoffe man erkennt meine Absichten: ich will eine Basisklasse eines
AudioPlayers definieren. In dessen Destruktor wird Stop() aufgerufen!
Der Player soll also das Spielen beenden. ABER: Ich darf Stop() nicht
im Destruktor aufrufen! Aufgrund der Reihenfolge der Destruktoren wird
ja leider der Destruktor von WAVPlayer VOR dem Destruktor von
GeneralPlayer aufgerufen. Folglich wird Stop() im Destruktor von
GeneralPlayer erst aufgerufen, wenn der benötigte BufferAllocated
bereits vom Destruktor von WAVPlayer ferigegeben wurde.
Natürlich ein Problem!
Ok, ich checke selber, dass es mit diesem Design nicht funktionieren
kann, aber es muss doch einen Weg geben, dass ich in GeneralPlayer
definiere, dass der Player gestoppt wird bzw. Stop() aufgerufen wird,
wenn das Objekt freigegeben wird! ABER das alles muss passieren bevor
WAVPlayer Resourcen bereits freigibt...
|
Dein Design der Basisklasse erweckt einen truegerischen Eindruck von
Konfigurierbarkeit, indem Du "GeneralPlayer::Stop()" "virtual" deklariert hast.
Dies ist das Hauptproblem an Deinem Design. Du kannst es nicht auf eine Art
loesen, die minimal invasiv ist.
Das Problem ist uebrigens "schlimmer", als Du
vielleicht denkst: Es wird vom Basisklassendestruktor "Stop()" nicht nur
spaeter aufgerufen, als Dir recht ist, sondern es wird auch das "falsche"
"Stop()" aufgerufen, naemlich das der Basisklasse, weil die virtual Table
schon wieder zurueckgebaut worden ist. Dies verhindert immerhin, dass
"Stop()" auf Daten operiert, die schon nicht mehr gueltig sind, naemlich
denjenigen, die die abgeleitete(n) Klasse(n) hinzugefuegt haben.
Es gibt i.W. nur zwei Moeglichkeiten: Du rufst "Stop()" nicht vom Destruktor
der Basisklasse auf, sondern dokumentierst, dass jeder, der eine Klasse von
derselben ableitet, im Destruktor der "finalen" Klasse "Stop()" aufrufen muss.
Zweitens - und m.E. die einzig wirklich sichere Loesung - Du baust eine Hilfsklasse,
etwa "GeneralPlayerPlay()", die eine non-"const"-Referenz auf eine "GeneralPlayer"-
Instanz im Konstruktor nimmt und als non-"const"-Referenz-Member speichert, in
ihrem Konstruktor damit "Start()" und in ihrem Destruktor damit "Stop()" aufruft.
Dieses Prinzip heisst "resource acquisition is initialization" (RAII).
Also:
WAVPlayer wp;
GeneralPlayerPlay play(wp);
Der Witz ist nun, dass "Stop()" aufgerufen wird, bevor "wp" zerstoert wird, weil
"play" dank seines Scopes vor "wp" zerstoert wird. Exception safety gibt's
damit ausserdem noch geschenkt.
Gruessle,
Philipp.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Enrico Thierbach Guest
|
Posted: Tue Oct 05, 2004 10:35 am Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Kirsten wrote:
| Quote: | Hi Leut,
Man lasse folgenden kurzen Pseudo-Code mal kurz auf sich wirken:
-----------------------
class GeneralPlayer
{
public:
GeneralPlayer();
~GeneralPlayer()
{
Stop();
}
virtual void Start();
virtual void Stop();
}
class WAVPlayer: public GeneralPlayer
{
protected:
void *BufferAllocated;
public:
WAVPlayer();
~WAVPlayer()
{
delete BufferAllocated;
}
virtual void Start();
virtual void Stop()
{
// Einfach irgendwas mit dem reservierten Speicher machen
memset(BufferAllocated,0,1024);
}
};
|
Besser (und funktionierend!)
alles wie oben, und:
class GlobalPlayer /* */ {
std::auto_ptr<GeneralPlayer> pimpl_;
public:
GlobalPlayer(std::auto_ptr<GeneralPlayer> p): pimpl_(p)
{
// Bei Bedarf: pimpl_->stop();
}
~GlobalPlayer()
{
pimpl_->stop();
}
GeneralPlayer& player() const
{ return *pimpl_; }
};
/eno
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Thomas Zimmermann Guest
|
Posted: Tue Oct 05, 2004 10:40 am Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Hallo,
ich kenne keinen Weg, die Reihenfolge der Destruktoren zu veraendern. Die
einzige Moeglichkeit, waehre, die Funktion des Destruktors in andere
Methoden auszulagern und sich selbst um den korrekten Aufruf dieser
Methoden zu kuemmern. Die Idee ist aber nicht besonders toll.
| Quote: | Ok, ich checke selber, dass es mit diesem Design nicht funktionieren
kann, aber es muss doch einen Weg geben, dass ich in GeneralPlayer
definiere, dass der Player gestoppt wird bzw. Stop() aufgerufen wird,
wenn das Objekt freigegeben wird! ABER das alles muss passieren bevor
WAVPlayer Resourcen bereits freigibt...
|
Stimmt, das Design funktioniert so nicht. Sound-Dateien liegen in einem
allgemeinen Format vor, wenn Sie abgespielt werden. Nach meiner Meinung
waehre es am Besten, wenn Du eine Klasse schreibst, die die WAV-Dateien
laed und eine, die sie abspielt; etwa so:
class WAVLoader
{
static char* load(std::string& filename);
}
class Player
{
void start();
void stop();
load(const std::string& filename)
{
buf = WAVLoader::load(filename);
}
char* buf;
}
Das ist kein(!) korrektes Design, aufgrund der moeglichen Memory-Leaks, aber
der Ansatz funktionert besser. Die Variable 'buf' wird am besten als eigene
Klasse implementiert. Dann koennen verschiedene Instanzen von Player sich
eine Instanz von 'buf' teilen.
Gruss Thomas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Kurt Stege Guest
|
Posted: Tue Oct 05, 2004 11:08 am Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
On 4 Oct 2004 15:49:05 -0700, [email]tthunder (AT) gmx (DOT) de[/email] (Kirsten) wrote:
| Quote: | Man lasse folgenden kurzen Pseudo-Code mal kurz auf sich wirken:
-----------------------
class GeneralPlayer
{
public:
GeneralPlayer();
~GeneralPlayer()
{
Stop();
}
virtual void Start();
virtual void Stop();
}
class WAVPlayer: public GeneralPlayer
{
protected:
void *BufferAllocated;
public:
WAVPlayer();
~WAVPlayer()
{
delete BufferAllocated;
}
virtual void Start();
virtual void Stop()
{
// Einfach irgendwas mit dem reservierten Speicher machen
memset(BufferAllocated,0,1024);
}
};
-----------------------
Ich hoffe man erkennt meine Absichten: ich will eine Basisklasse eines
AudioPlayers definieren. In dessen Destruktor wird Stop() aufgerufen!
Der Player soll also das Spielen beenden. ABER: Ich darf Stop() nicht
im Destruktor aufrufen! Aufgrund der Reihenfolge der Destruktoren wird
ja leider der Destruktor von WAVPlayer VOR dem Destruktor von
GeneralPlayer aufgerufen. Folglich wird Stop() im Destruktor von
GeneralPlayer erst aufgerufen, wenn der benötigte BufferAllocated
bereits vom Destruktor von WAVPlayer ferigegeben wurde.
Natürlich ein Problem!
|
Nein. Das ist in C++ anders gelöst.
Wenn Du ein Objekt der Klasse WAVPlayer hast und dessen Destruktor
aufrufst, passiert in etwa folgendes:
- Der Destruktor von WAVPlayer wird ausgeführt, ruft
also "delete BufferAllocated" auf.
- Das Objekt wird zur Basisklasse "degradiert", ist also ab
jetzt kein WAVPlayer mehr, sondern ein GeneralPlayer.
- Der Destruktor von GeneralPlayer wird aufgerufen, ruft
also "Stop()" auf. Da das Objekt vom Typ GeneralPlayer
ist, wird hier auch GeneralPlayer::Stop() aufgerufen.
Diese Funktion ist deklariert, muß auch implementiert
sein und greift eben nicht auf "memset(BufferAllocated,0,1024)"
zu.
Also keine Lücke in C++, sondern konsequent und sauber umgesetzt.
Allerdings womöglich nicht so, wie Du es erwartet hattest...
Gruß,
Kurt.
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Edzard Egberts Guest
|
Posted: Tue Oct 05, 2004 11:27 am Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Hallo Kirsten,
| Quote: | class GeneralPlayer
{
public:
GeneralPlayer();
~GeneralPlayer()
|
da wäre vielleicht "virtual ~GeneralPlayer()" besser.
| Quote: | Aufgrund der Reihenfolge der Destruktoren wird
ja leider der Destruktor von WAVPlayer VOR dem Destruktor von
GeneralPlayer aufgerufen.
|
Hier könnte es dann nämlich sein, dass es keine Reihenfolge, sondern
überschriebene Destruktoren gibt. Die Basisklasse muss dann meines
Wissens explizit aufgerufen werden:
~WAVPlayer()
{
GeneralPlayer::~GeneralPlayer();
delete BufferAllocated;
}
Bin mir natürlich nicht ganz sicher, aber das läßt sich ja leicht
ausprobieren...
Gruß,
Ed
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Tue Oct 05, 2004 11:59 am Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Edzard Egberts wrote:
| Quote: |
Hallo Kirsten,
class GeneralPlayer
{
public:
GeneralPlayer();
~GeneralPlayer()
da wäre vielleicht "virtual ~GeneralPlayer()" besser.
|
Kommt drauf an wie die Klasse verwendet wird, aber prinzipiell
hast Du nicht unrecht.
| Quote: | Aufgrund der Reihenfolge der Destruktoren wird
ja leider der Destruktor von WAVPlayer VOR dem Destruktor von
GeneralPlayer aufgerufen.
Hier könnte es dann nämlich sein, dass es keine Reihenfolge, sondern
überschriebene Destruktoren gibt. Die Basisklasse muss dann meines
Wissens explizit aufgerufen werden:
~WAVPlayer()
{
GeneralPlayer::~GeneralPlayer();
|
Bis auf ganz wenige Ausnahmefaelle rufst Du niemals einen Destruktur selbst
auf. Solange Du diese Ausnahmen nicht kennst, kannst Du auch davon ausgehen
dass ein Destruktor niemals selbst aufgerufen wird. Diese Ausnahmen sind naemlich
extrem selten und treten nur dann auf, wenns wirklich ans Eingemachte geht. Etwas
worueber ein Newcomer in den ersten 3 Jahren seiner Programmierkarriere nicht
stolpern wird.
| Quote: | delete BufferAllocated;
}
Bin mir natürlich nicht ganz sicher, aber das läßt sich ja leicht
ausprobieren...
|
Aehm, nein
In diesem Fall bringt Dich ausprobieren nicht weiter. Wenn Du ein
WAVPlayer Objekt ueber einen Basiszeiger delete-st und der Destruktor
nicht virtual ist, dann ist das Verhalten undefiniert. Theoretisch
darf das Program auch abstuerzen und die Festplatte loeschen :-)
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Edzard Egberts Guest
|
Posted: Tue Oct 05, 2004 12:13 pm Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Hallo Karl Heinz,
| Quote: | Bis auf ganz wenige Ausnahmefaelle rufst Du niemals einen Destruktur selbst
auf.
|
mir kam das auch seltsam vor, aber bei "virtual" habe ich eben vor allem
überschriebene Methoden im Kopf und da braucht man das ja öfter.
| Quote: | Aehm, nein
In diesem Fall bringt Dich ausprobieren nicht weiter. Wenn Du ein
WAVPlayer Objekt ueber einen Basiszeiger delete-st und der Destruktor
nicht virtual ist, dann ist das Verhalten undefiniert. Theoretisch
darf das Program auch abstuerzen und die Festplatte loeschen
|
Nach Murphy hat es gar keine andere Wahl. ;o)
Dann eben den virtuellen Destruktor ohne Aufruf der Basisklasse
überschreiben - das müsste dann doch wirklich das richtige Stop aufrufen
und den Puffer aufräumen...
Gruß,
Ed
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Tue Oct 05, 2004 12:21 pm Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Edzard Egberts wrote:
| Quote: |
Aehm, nein
In diesem Fall bringt Dich ausprobieren nicht weiter. Wenn Du ein
WAVPlayer Objekt ueber einen Basiszeiger delete-st und der Destruktor
nicht virtual ist, dann ist das Verhalten undefiniert. Theoretisch
darf das Program auch abstuerzen und die Festplatte loeschen :-)
Nach Murphy hat es gar keine andere Wahl. ;o)
Dann eben den virtuellen Destruktor ohne Aufruf der Basisklasse
überschreiben - das müsste dann doch wirklich das richtige Stop aufrufen
und den Puffer aufräumen..
|
Nicht ganz.
Der OP hat hier ein Designproblem. Aus dem Basisklassendestruktor
heraus wird naemlich gar nicht das Stop der abgeleiteten Klasse
aufgerufen. Merke: Waehrend ein Konstruktor oder Destruktor laueft
hat 'virtual' keinen Effekt. Kurt hat das sehr schoen beschrieben.
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Rolf Magnus Guest
|
Posted: Tue Oct 05, 2004 12:34 pm Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Karl Heinz Buchegger wrote:
| Quote: | Dann eben den virtuellen Destruktor ohne Aufruf der Basisklasse
überschreiben - das müsste dann doch wirklich das richtige Stop aufrufen
und den Puffer aufräumen..
Nicht ganz.
Der OP hat hier ein Designproblem. Aus dem Basisklassendestruktor
heraus wird naemlich gar nicht das Stop der abgeleiteten Klasse
aufgerufen. Merke: Waehrend ein Konstruktor oder Destruktor laueft
hat 'virtual' keinen Effekt. Kurt hat das sehr schoen beschrieben.
|
Doch, einen Effekt hat es schon, aber eben nur bis zu der Klasse, zu der der
Destruktor bzw. Konstruktor gehört, in dem wir uns grade befinden. Ich
denke hier an sowas wie:
#include <iostream>
struct A
{
virtual void Foo() { std::cout << "An"; }
void Bar() { Foo(); }
};
struct B : public A
{
virtual void Foo() { std::cout << "Bn"; }
~B() { Bar(); } // ruft B::Foo auf, ist also polymorph
};
int main()
{
B b;
}
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Karl Heinz Buchegger Guest
|
Posted: Tue Oct 05, 2004 1:06 pm Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Rolf Magnus wrote:
| Quote: |
aufgerufen. Merke: Waehrend ein Konstruktor oder Destruktor laueft
hat 'virtual' keinen Effekt. Kurt hat das sehr schoen beschrieben.
Doch, einen Effekt hat es schon, aber eben nur bis zu der Klasse, zu der der
Destruktor bzw. Konstruktor gehört, in dem wir uns grade befinden. Ich
denke hier an sowas wie:
|
Mein Fehler: Schlechte Wortwahl. Ich habs zu sehr vereinfacht.
Komisch. In comp.lang.c++ passiert mir das wesentlich seltener als hier :-)
--
Karl Heinz Buchegger
[email]kbuchegg (AT) gascad (DOT) at[/email]
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Enrico Thierbach Guest
|
Posted: Tue Oct 05, 2004 4:51 pm Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
| Quote: | Besser (und funktionierend!)
|
Und um mich jetzt noch mal zu korrigieren, hier der code komplettiert:
class GeneralPlayer
{
/* kann in diesem Fall nicht schaden. */
GeneralPlayer(const GeneralPlayer&);
GeneralPlayer& operator = (const GeneralPlayer&);
public:
GeneralPlayer() { };
virtual /* !! */ ~GeneralPlayer() { } /* should *not* call stop() */
virtual void Start() = 0;
virtual void Stop() = 0;
};
class WAVPlayer: public GeneralPlayer
{
public:
WAVPlayer();
~WAVPlayer() { } /* should *not* call stop() */
void Start() { /* ... */ }
void Stop() { /* ... */ }
};
class GlobalPlayer {
std::auto_ptr<GeneralPlayer> pimpl_;
public:
/** c'tor; starts the player. */
GlobalPlayer(std::auto_ptr<GeneralPlayer> p): pimpl_(p)
{ start(); }
/** d'tor; stops the player automatically. */
~GlobalPlayer()
{ stop(); }
/*
* const or not? hier geschmackssache. Technisch gesehen ist
* das Object natürlich const, aber semantisch ändert stop()
* und start() ja vielleicht doch den Zustand des Objects?
*/
void stop()
{ pimpl_->stop(); }
void start()
{ pimpl_->start(); }
/** for those who need it */
GeneralPlayer& player() const
{ return *pimpl_; }
};
Die Benutzung erfolgt durch ein GlobalPlayer object, welches bei der
Konstruktion eine Instanz von einer von GeneralPlayer abgeleiteten
Klasse mitgegeben wird:
{
GlobalPlayer player(new WAVPlayer());
player.stop();
player.start();
/* etc. pp. */
}
Der d'tor ~GlobalPlayer() stoppt automatisch die Wiedergabe.
HIH,
/eno
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Michael Karcher Guest
|
Posted: Tue Oct 05, 2004 7:49 pm Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Enrico Thierbach <eno (AT) open-lab (DOT) org> wrote:
| Quote: | Und um mich jetzt noch mal zu korrigieren, hier der code komplettiert:
[Siehe Originalposting: |
GeneralPlayer, Unterklasse WAVPlayer
GlobalPlayer-Objekt, dass die Start- und Stop-Methoden verwendet. ]
Und jatzt kann man auch noch (ich würde das so machen, Pflicht ist es aber
nicht) die start- und stop-Methoden in der GeneralPlayer-Klasse als private
deklarieren, und das GlobalPlayer-Objekt zum Freund machen. Damit stellt man
sicher, dass die Start- und Stop-Methoden immer schön in Paaren aufgerufen
werden. Was man damit noch nicht sicher stellt ist allerdings, dass man
möglicherweise mehr als einen GlobalPlayer mit dem gleichen GeneralPlayer
initialisiert.
Anderer Ansatz wäre, den GlobalPlayer mit privatem Konstruktor zu versehen,
und GeneralPlayer als Freund zu definieren. GeneralPlayer hat dann eine
startPlaying-Methode, die als Factory für GlobalPlayers funktioniert:
class GlobalPlayer;
class GeneralPlayer {
GlobalPlayer * myplayer; /* wird im c'tor geNULLt */
void releasePlayer() { myplayer = NULL; }
virtual void start() = 0;
virtual void stop() = 0;
friend class GlobalPlayer;
public:
your_favorite_smart_pointer<GeneralPlayer>
startPlaying() {
if(myplayer)
throw already_playing;
myplayer = new GlobalPlayer(*this);
return myplayer;
}
};
class GlobalPlayer {
friend class GeneralPlayer;
GeneralPlayer& myplayer;
GlobalPlayer(GeneralPlayer & pl) : myplayer(pl) { myplayer->start(); }
public:
~GlobalPlayer() { myplayer->stop(); myplayer->releasePlayer(); }
};
Michael Karcher
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Kirsten Guest
|
Posted: Tue Oct 05, 2004 10:58 pm Post subject: Re: Reihenfolge der Destruktorenaufrufe umkehren? |
|
|
Hallo Kurt,
klar hast du Recht, und sorry, wenn sich meine Frage "amateurhaft"
anhört. Das von dir beschriebene Verhalten ist vollkommen klar, und
ist auch "von mir erwartet" *g*
Dass ich dachte das das virtuelle Stop() vom Destruktor der
Basisklasse aufgerufen wird, war dumm von mir, hab ich nur nicht so
schnell überdacht als ich mir den Pseudo-Code überlegte! Eigentlich
weiß ich es ja besser... Aber an dem Problem ändert es ja nix!
Und bei der "Lücke", meinte ich nicht, dass C++ da Fehler macht! Nein,
im Gegenteil, C++ ist sauber und konsequent! Aber ich vermisse
folgendes Feature:
Sagen wir einfach dass VOR dem Destruktor automatisch (wie eben der
Destruktor) eine virtuelle Funktion aufgerufen werden soll! Und sie
soll sich genau wie eine virtuelle Funktion verhalten! D.h. ich kann
die Hirarchie von oben nach unten oder von unten nach oben durchgehen
(je nachdem wann und ob ich die Basisfunktionen aufrufe). Danach
dürfen die Destruktoren aufgerufen werden und alles korrekt
freigegeben werden...
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|