Deprecated: Non-static method StringParser_Node::destroyNode() should not be called statically, assuming $this from incompatible context in /www/htdocs/w008ab83/ad/stringparser_bbcode/src/stringparser.class.php on line 356
AUDACIA Software - Warum Delphi-Klassen auf dem Heap erstellt werden müssen
AUDACIA Software

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



  1. TObject
  2. Konstruktion und Destruktion
  3. Virtuelle Funktionen in Konstruktor und Destruktor
  4. Exceptions im Konstruktor
  5. Initialisierung
  6. Mehrfachvererbung
  7. Virtuelle Konstruktoren
  8. Klassenfunktionen
  9. Freigabe
  10. Semantik
  11. Benutzung
  12. Allokation und Deallokation
  13. RTTI
  14. Implizit generierte Methoden
  15. Kommentare


void foo (void)
{
    TStringList sl;
    ...
}

TObject


Alle von TObject abgeleiteten Klassen sind Klassen im Delphi-Stil, vereinfacht: Delphi-Klassen.


Konstruktion und Destruktion

Virtuelle Funktionen in Konstruktor und Destruktor

struct 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 Konstruktor

Initialisierung

Mehrfachvererbung


Das VMT

Virtuelle Konstruktoren

Klassenfunktionen

Freigabe

Free()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-Semantik

Benutzung

void 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 EEFFACE
class 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()

RTTI

Implizit generierte Methoden

class 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

Neuer Eintrag:

Name:
E-Mail:
Website:
Datum:
Anzahl der Zeichen in Ihrem Namen:
Text: