Warum Delphi-Klassen auf dem Heap erstellt werden müssen
Kurzer Abriß der technischen Unterschiede zwischen C++- und Delphi-Klassen.
Moritz Beutel, 14.10.2008, 06.07.2009
- TObject
- Konstruktion und Destruktion
- Virtuelle Funktionen in Konstruktor und Destruktor
- Exceptions im Konstruktor
- Initialisierung
- Mehrfachvererbung
- Virtuelle Konstruktoren
- Klassenfunktionen
- Freigabe
- Semantik
- Benutzung
- Allokation und Deallokation
- RTTI
- Implizit generierte Methoden
- Kommentare
void foo (void)
{
TStringList sl;
...
}
TObject
Alle von TObject abgeleiteten Klassen sind Klassen im Delphi-Stil, vereinfacht: Delphi-Klassen.
Konstruktion und DestruktionVirtuelle Funktionen in Konstruktor und Destruktorstruct Base
{
virtual void foo (void) = 0;
Base (void) { foo (); }
};
struct Derived : Base
{
virtual void foo (void) { ShowMessage ("It's me!"); }
};
struct TBase : TObject
{
virtual void foo (void) = 0;
TBase (void) { foo (); }
};
struct TDerived : TBase
{
virtual void foo (void) { ShowMessage ("It's me!"); }
};
void bar (void)
{
TDerived* td = new TDerived; // zeigt "It's me!" an
Derived d; // zeigt "Pure virtual function called" an
}
Exceptions im KonstruktorInitialisierungMehrfachvererbung
Das VMTVirtuelle KonstruktorenKlassenfunktionenFreigabeFree()TObject::Free()delete obj), explizit (obj->T ()Semantik
Delphi-Code wie
procedure foo;
var
sl1, sl2: TStringList;
begin
sl1 := TStringList.Create;
sl2 := sl1; // diese Zeile
... Assign()hierNamed Return Value OptimizationMove-SemantikBenutzungvoid foobar (void)
{
TStringList* sl = 0;
try
{
sl = new TStringList;
...
}
__finally
{
delete sl;
}
} RAII-Wrappers wie std::auto_ptr:
#include <memory>
void foobar (void)
{
std::auto_ptr <TStringList> sl (new TStringList);
...
} std::tr1::shared_ptr, passend:
#include <memory>
TStringList* stringListFactory (void)
{
std::auto_ptr <TStringList> result (new TStringList);
result->Add ("Initial string");
return result.release ();
}
void foobaz (void)
{
std::auto_ptr <TStringList> theStringList (stringListFactory ());
}
Addenda vom 06.07.2009:
Wie in External Exception EEFFACEclass TMyThread : public TThread
{
protected:
virtual void __fastcall Execute (void) {}
public:
TMyThread (void) : TThread (false) {}
};
void startMyThreadTheFreakyWay (void)
{
TMyThread ().FreeOnTerminate = true;
}
void startMyThreadTheNormalWay (void)
{
new TMyThread ()->FreeOnTerminate = true;
}
Allokation und Deallokation#include <string>
void constructSomeObjects (void)
{
// Allokation auf dem Stack
std::string myStackString ("foo");
myStackString += std::string ("bar");
// Allokation auf dem Heap
std::string* myHeapString = new std::string ("baz");
delete myHeapString;
// Explizite Konstruktion und Destruktion
char buffer[sizeof (std::string)];
std::string* anotherStackString = new (buffer) std::string ("wtf?");
anotherStackString->~string ();
}
class MyCppClass
{
public:
void* operator new (unsigned long size)
{ return std::malloc (size); }
void operator delete (void* ptr)
{ std::free (ptr); }
virtual ~MyCppClass (void) {}
}; Bei einem virtuellen Destruktor allerdings kommt besagte Ausnahme ins Spiel:
hierNewInstance()FreeInstance()
InitInstance()InstanceSize()sizeof(TMyCustomAllocatedClass)TMyCustomAllocatedClass // System.pas, 263ff
{ Hidden TObject field info }
hfFieldSize = 4;
hfMonitorOffset = 0; System.TMonitor (analog zu System.Threading.Monitorsizeof(TMyCustomAllocatedClass)operator new auf Delphi-Klassen keine Auswirkung haben kann, denn der Destruktor einer Delphi-Klasse ist stets virtuell und benutzt demnach immer die virtuelle Funktion FreeInstance()RTTIImplizit generierte Methodenclass ClassWithProperties
{
private:
int FFoo;
String FBar;
public:
__property int Foo = { read = FFoo, write = FFoo };
};
Referenzen
[1] Die C++Builder 6-Dokumentation, besonders das Kapitel
[2] Barry Kelly, Programming language design philosophy: C++'s value orientation, 08.08.2006
[3] Ayman B. Shoukry, Named Return Value Optimization in Visual C++ 2005, 10.2005
[4] The C++ Standards Committee, A Brief Introduction to Rvalue References, 12.06.2006
[5] Hallvard Vassbotn, The Rise and Fall of TObject, 07.1998
Dieser Artikel basiert auf Material, das ich zuvor im c++.de-Forum verwendet hatte.
Kommentare
Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead in /www/htdocs/w008ab83/ad/phputils/dbc_mysql.php on line 112
|