Objektidentität und -instantiierung

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu C++- und Object Pascal-Modelle


In C++ ist eine Instanz einer Klasse ein konkretes Objekt. Dieses Objekt kann direkt manipuliert werden, oder es kann darauf indirekt über eine Referenz oder einen Zeiger zugegriffen werden.

Beispielsweise sind für eine gegebene C++-Klasse CPP_class mit einem Konstruktor, der keine Argumente aufnimmt, alle folgenden Instanzvariablen dieser Klasse gültig:
 CPP_class by_value;// ein Objekt des Typs
 CPP_class CPP_class& ref = by_value;// eine Referenz auf das Objekt per Wert CPP_class* ptr =  new
 CPP_class();// ein Zeiger auf ein Objekt des Typs CPP_class

Im Gegensatz dazu verweist in Object Pascal eine Variable des Typs Objekt immer indirekt auf das Objekt. Der Speicher für alle Objekte wird dynamisch zugewiesen. Beispiel einer gegebenen Object Pascal-Klasse OP_class:

 ref: OP_class ;
 ref := OP_class.Create ;
ref ist eine “Referenz” auf ein Objekt des Typs OP_class.

Der entsprechende C++Builder-Code würde folgendermaßen aussehen:

 
 OP_class* ref =  new  OP_class;

Unterscheiden von C++- und Object Pascal-Referenzen

In der Dokumentation wird eine Object Pascal-Klasseninstanzvariable häufig als Referenz bezeichnet, ihr Verhalten aber als das eines Zeigers beschrieben, und zwar, weil sie Eigenschaften von beiden beinhaltet. Eine Object Pascal-Objektreferenz entspricht einem C++-Zeiger mit den folgenden Ausnahmen:

  • Eine Object Pascal-Referenz ist implizit dereferenziert (in diesem Fall verhält sie sich eher wie eine C++-Referenz).
  • Eine Object Pascal-Referenz hat keine Zeigerarithmetik als definierte Operation.

Object Pascal-Referenzen und C++-Referenzen verfügen auch über Ähnlichkeiten und Unterschiede. Referenzen sind in beiden Sprachen implizit dereferenziert, aber:

  • Eine Object Pascal-Referenz kann neu gebunden werden, eine C++-Referenz nicht.
  • Eine Object Pascal-Referenz kann nil sein, eine C++-Referenz muss auf ein gültiges Objekt verweisen.

Einige der für die FireMonkey- und RTL-Framework getroffenen Designentscheidungen basieren auf der Verwendung dieser Art von Instanzvariable. Zeiger sind das C++-Sprachkonstrukt, das Object Pascal-Referenzen am nächsten kommen. Deshalb werden fast alle FireMonkey- und RTL-Objektbezeichner in C++Builder in C++-Zeiger übersetzt.

Hinweis: Der Object Pascal-Parametertyp var entspricht am ehesten einer C++-Referenz.

Kopieren von Objekten

Im Gegensatz zu C++ bietet Object Pascal keine integrierte Compiler-Unterstützung zum Kopieren eines Objekts. Dieser Abschnitt beschreibt die Auswirkung dieses Unterschieds auf Zuweisungsoperatoren und Kopierkonstruktoren für Klassen im Delphi-Stil. Klassen im Delphi-Stil werden direkt oder indirekt von System::TObject abgeleitet.

Zuweisungsoperatoren

Der Object Pascal-Zuweisungsoperator (:=) ist kein Klassenzuweisungsoperator (operator=()). Der Zuweisungsoperator kopiert die Referenz, nicht das Objekt. Im folgenden Code verweisen B und C auf dasselbe Objekt:

 B, C: TButton ;
 B:= TButton.Create(ownerCtrl) ;
 C:= B ;

In C++Builder würde dieses Beispiel folgendermaßen aussehen:

 TButton *B = NULL ;
 TButton *C = NULL ;
 B = new TButton(ownerCtrl) ;
 C = B;// kopiert den Zeiger, nicht das Objekt

Klassen im Delphi-Stil folgen in C++Builder den Object Pascal-Sprachregeln für Zuweisungsoperatoren. Das heißt, dass im folgenden Code Zuweisungen zwischen dereferenzierten Zeigern nicht gültig sind, weil sie versuchen, das Objekt und nicht den Zeiger zu kopieren:

 TRTLStyleClass *p =  new  TRTLStyleClass ; 
 TRTLStyleClass *q =  new  TRTLStyleClass ; 
 *p = *q;// nicht zulässig für Klassenobjekte im Delphi-Stil

Hinweis: Bei Klassen im Delphi-Stil kann die C++-Syntax zum Binden einer Referenz verwendet werden. Beispielsweise ist der folgende Code zulässig:

 TRTLStyleClass *ptr =  new  TRTLStyleClass ; 
 TRTLStyleClass &ref = *ptr;// OK für Klassen im Delphi-Stil

Obwohl das nicht der Verwendung eines Zuweisungsoperators entspricht, ist die Syntax doch ähnlich genug, um hier aus Klarstellungs- und Vergleichsgründen erwähnt zu werden.


Kopierkonstruktoren

Object Pascal hat keine integrierten Kopierkonstruktoren. Folglich haben auch Klassen im Delphi-Stil in C++Builder keine integrierten Kopierkonstruktoren. Im folgenden Beispielcode wird versucht, einen TButton-Zeiger mithilfe eines Kopierkonstruktors zu erstellen:

 TButton *B =  new  TButton(ownerCtrl) ;
 TButton *C =  new  TButton(*B);// nicht zulässig für Klassenobjekte im Delphi-Stil

Schreiben Sie keinen Quelltext, der von einem integrierten Kopierkonstruktor für Delphi-Klassen abhängig ist. Um in C++Builder eine Kopie eines Klassenobjekts im Delphi-Stil zu erstellen, können Sie eine Member-Funktion schreiben, die das Objekt kopiert. Eine Alternative bieten Nachkommen der RTL-Klasse TPersistent, die die Methode Assign überschreiben können, um Daten von einem Objekt in ein anderes zu kopieren. Dieses Vorgehen wird beispielsweise in FMX-Grafikklassen, wie TBitmap und TIcon, angewandt, die Ressourcenbilder enthalten. Letztlich kann die Art und Weise, wie ein Objekt kopiert wird, durch den Programmierer (Komponentenentwickler) bestimmt werden; denken Sie aber daran, dass einige der C++-Standardkopiermethoden für Klassen im Delphi-Stil nicht zur Verfügung stehen.

Objekte als Funktionsargumente

Wie bereits weiter oben erwähnt, sind Instanzvariablen in C++ und in Object Pascal nicht identisch. Bedenken Sie dies, wenn Sie Objekte als Argumente an Funktionen übergeben. In C++ können Objekte entweder per Wert, per Referenz oder per Zeiger an Funktionen übergeben werden. Wenn in Object Pascal ein Objekt per Wert an eine Funktion übergeben wird, dann ist das Objektargument bereits eine Referenz auf das Objekt. Daher wird tatsächlich die Referenz per Wert übergeben nicht das eigentliche Objekt. In Object Pascal gibt es kein Äquivalent zur Übergabe des tatsächlichen Objekts per Wert wie in C++. Objekte im Delphi-Stil, die an Funktionen übergeben werden, folgen den Object Pascal-Regeln.

Siehe auch