Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!
Werbeanzeige
C-/C++-Quelltext |
|
1 |
struct OstreamHolder { std::ostream *listener_one; std::ostream *listener_two;}; |
Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »dot« (24.01.2011, 14:17)
C-/C++-Quelltext |
|
1 2 3 4 5 6 7 8 |
OstreamHolder h; { ofstream x; x.open("Test.txt"); h.SetListener(x); } //x ist zerstört, in h wird aber immernoch auf das nicht mehr existente x verwiesen h << "Test"; |
Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Darkrel« (24.01.2011, 17:26)
C-/C++-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
class Log { public: Log() : listener(NULL){}; //Streams, die hinzugefügt werden, müssen vom typ Log::LogStream<BaseStream> sein. //ein Log::LogStream<ofstream> ist also z.B. abgeleitet von ofstream. //struct, weil ich zu faul war um hier fürs Forum auch noch auf private / public zu achten ;) Für das Beispiel hier reichts. template<typename BaseStream> struct LogStream : public BaseStream { //Standardkonstruktor. Initialisiert die beiden Pointer mit NULL. LogStream() : destroy(NULL), log(NULL){}; //Destruktor. Virtuell, zur sicherheit, falls ein vom LogStream abgeleiteter stream eingefügt werden soll. //Das Herz des Memberpointer callback mechanismus. Da der destruktor von ios_base (und damit auch der von ostream) virtuell ist, //kommt es nicht zu object slicing, auch nicht wenn ein LogStream objekt über einen BaseClass pointer verwaltet wird. virtual ~LogStream() { if(log != NULL && destroy != NULL) { ((*log).*destroy)(); log = NULL; } }; //Signatur des Callbacks. typedef void (Log::*Callback)(void); //Der Callback. In der fertig designten version wird natürlich auch auf Kapselung geachtet. Bitte hier nicht weiter darauf rumhacken. Callback destroy; //Da wir einen memberpointer verwenden, muss auch das objekt, auf welchem wir die funktion aufrufen vorhanden sein. Log *log; }; //Template funktion, die LogStreams mit beliebigem base stream als listener hinzufügt. //Dank ADL (Argument dependent lookup), muss der template parameter nicht explizit benannt werden. template<typename BaseStream> void AddListener(LogStream<BaseStream> &stream) { if(listener != NULL && !listener->bad()) { listener->flush(); } listener = &stream; //Callback setzen stream.destroy = &Log::DisableListener; stream.log = this; }; void CheckStream() { if(listener == NULL) cout << "Listener is NULL" << endl; else cout << "Listener is not NULL" << endl; }; private: //Hier wird meine Anforderung erfüllt. Damit nicht jeder x beliebige Typ als BaseStream verwendet werden kann, //muss der LogStream (und damit der BaseStream) in einen ostream konvertierbar sein. Für alle Typen, die diese //anforderung nicht erfüllen, spuckt der compiler einen Fehler aus. (Remember, Fehler zur compile time = "guter" fehler). ostream *listener; //Die Callback funktion, die den listener auf NULL setzt. void DisableListener() { if(listener != NULL && !listener->bad()) listener->flush(); listener = NULL; }; }; |
C-/C++-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
int main(int argc, char** argv) { Log l; l.CheckStream(); { Log::LogStream<ofstream> t; l.AddListener(t); l.CheckStream(); } //t wird hier zerstört. l.CheckStream(); system("pause"); }; |
Dieser Beitrag wurde bereits 9 mal editiert, zuletzt von »Darkrel« (24.01.2011, 22:24)
Werbeanzeige