NewHandlerSupport
-
Ich lese grade Effektiv C++ programmieren! Ziemlich am Anfang wird eine Klasse vorgestellt, die das setzen von Klassenspeziefischen new_handlern erleichtern soll! Das ganze sieht so aus:
new_handler.htemplate<class T> class NewHandlerSupport { private: static new_handler CurrentHandler; public: static new_handler SetNewHandler(new_handler p); static void * operator new(size_t size); };
new_handler_impl.cpp:
template<class T> static new_handler NewHandlerSupport(T)::SetNewHandler(new_handler P) { new_handler OldHandler=CurrentHandler; CurrentHandler=p; return OldHandler; }; template <class T> static void * NewHandlerSuppor(T)::operator new(size_t size) { new_handler GlobalHandler=std::set_new_handler(CurrentHandler); void *memory; try { memory=::operator new(size); }; catch (std::bad_alloc) { std::set_new_handler(GlobalHandler); throw; }; std::set_new_handler(GlobalHandler); return memory; }; template <class T> new_handler NewHandlerSupport(T)::CurrentHandler;
Wenn ich das versuche zu kompilieren, bekomme ich 7 Errors: (u.a.)
error C2039: 'SetNewHandler': Ist kein Element von 'operator``global namespace''' error C2146: Syntaxfehler: Fehlendes ';' vor Bezeichner 'SetNewHandler' error C2904: 'NewHandlerSupport': Name wird bereits für eine Vorlage im aktuellen Bereich verwendet
Wenn ich die Stellen in der Implementation von NewHandlerSupport, wo sowas wie "NewHandlerSuppor(T)::operator new" steht, das "(T)" weglasse, kommen Errors anderer Art (so ungefähr: benutzung einer Vorlagenklasse erfordert benutzung einer Vorlagenargumentliste...) Wenn ich besagte Stellen durch "<T>" ersetze, und dann in main folgendes schreibe:
#include "new_handler.h" using namespace std; class X : public NewHandlerSupport<X> { private: int saved; public: X(int s); int GetSaved(); void SetSaved(int s); }; X::X(int s) :saved(s) {}; int X::GetSaved() { return saved; }; void X::SetSaved(int s) { saved=s; }; void NoMoreMemory() { cout<<"Speicherüberlauf!"; cin.get(); exit(-1); }; int _tmain(int argc, _TCHAR* argv[]) { cout<<"NewHandlerSupportTest"<<endl; X::SetNewHandler(NoMoreMemory); return 0; }
Bekomme ich folgende Error:
error LNK2019: Nicht aufgelöstes externes Symbol '"public: static void (__cdecl*__cdecl mer::NewHandlerSupport<class X>::SetNewHandler(void (__cdecl*)(void)))(void)" (?SetNewHandler@?$NewHandlerSupport@VX@@@mer@@SAP6AXXZP6AXXZ@Z)', verwiesen in Funktion '_main' fatal error LNK1120: 1 unaufgelöste externe Verweise
Wie muss ich es richtig machen?
-
Templates muessen in den header - oder du packst sie in ein inline file:
[.h]
template<typename bla> class blub {
...
}#include "bla_impl.inl"
[.inl]
...
-
OK, hift schon mal! Noch eine Frage: um das ganze möglichst idiotensicher zu machen, würde ich NewHandlerSupport gerne abstrakt machen! Aber wie? Ich meine, so das, wenn ich dann meine Klasse davon erben lasse, ich nichts neu definieren muss! (Ist das unverstandlich?) Ich habs schon so probiert, geht aber net:
virtual ~NewHandlerSupport() {}=0;
-
So müsste es klappen:
virtual ~NewHandlerSupport() = 0; //außerhalb der Klasse dann: NewHandlerSupport::~NewHandlerSupport() { }
-
OK, das klappt! Nun habe ich mir zum Test das Programm geschrieben:
void NoMoreMemory() { cout<<"Speicherüberlauf!"; cin.get(); exit(-1); }; int _tmain(int argc, _TCHAR* argv[]) { cout<<"NewHandlerSupportTest"<<endl; X::SetNewHandler(NoMoreMemory); X *px; for(int i=0;i<=1000000000000;++i) px=new X(4); cin.get(); return 0; }
Nun kommt aber irgendwann meine Fehlermeldung, aber zusammen mit dem (Windows-) Fehler, dass nicht genügend virtueller zur verfügung stände! Ist unter XP der heap etwa mir dem virtuellen Speicher begrenzt? Müll ich mir den so zu? Oder wird der automatisch gelöscht wenn das Programm beendet wird?