Object Identity and Instantiation

From RAD Studio
Jump to: navigation, search

Go Up to C++ and Object Pascal Models


In C++, an instance of a class is an actual object. That object can be directly manipulated, or it can be accessed indirectly through either a reference or a pointer to it.

For example, given a C++ class CPP_class with a constructor that takes no arguments, the following are all valid instance variables of that class:
 CPP_class by_value;// an object of type CPP_clas s 
 CPP_class& ref = by_value;// a reference to the object by_value, abov e 
 CPP_class* ptr =  new  CPP_class();// a pointer to an object of type CPP_clas s

By contrast, in Object Pascal a variable of type object always refers to the object indirectly. The memory for all objects is dynamically allocated. For example, given an Object Pascal class OP_class:

 ref: OP_class ; 
 ref := OP_class.Create ;
ref is a "reference" to an object of type OP_class.
Translated to C++Builder code, it would be:
 OP_class* ref =  new  OP_class;

Distinguishing C++ and Object Pascal references

Documentation frequently refers to an Object Pascal class instance variable as a reference, but describes its behavior as that of a pointer. This is because it has properties of both. An Object Pascal object reference is like a C++ pointer with the following exceptions:

  • An Object Pascal reference is implicitly dereferenced (in which case it acts more like a C++ reference).
  • An Object Pascal reference does not have pointer arithmetic as a defined operation.

When comparing an Object Pascal reference with a C++ reference, there are also similarities and differences. References in both languages are implicitly dereferenced, however,

  • An Object Pascal reference can be rebound, whereas a C++ reference cannot.
  • An Object Pascal reference can be nil, whereas a C++ reference must refer to a valid object.

Some of the design decisions underlying the FireMonkey and RTL frameworks are based upon the use of this type of instance variable. A pointer is the closest C++ language construct to an Object Pascal reference. Consequently, nearly all FireMonkey and RTL object identifiers are translated into C++ pointers in C++Builder.

Note: The Object Pascal var parameter type is a close match to a C++ reference.

Copying objects

Unlike C++, Object Pascal does not have built-in compiler support for making a copy of an object. This section describes the impact of this difference on assignment operators and copy constructors for Delphi style classes. Delphi style classes derive directly or indirectly from System::TObject.

Assignment operators

The Object Pascal assignment operator (:=) is not a class assignment operator (operator=()). The assignment operator copies the reference, not the object. In the following code, B and C both refer to the same object:

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

This example translates to the following code in C++Builder:

 TButton *B = NULL ; 
 TButton *C = NULL ; 
 B = new TButton(ownerCtrl) ; 
 C = B;// makes a copy of the pointer, not the object

Delphi style classes in C++Builder follow the Object Pascal language rules for assignment operators. This means that, in the following code, assignments between dereferenced pointers are not valid because they attempt to copy the object, not the pointer:

 TRTLStyleClass *p =  new  TRTLStyleClass ; 
 TRTLStyleClass *q =  new  TRTLStyleClass ; 
 *p = *q;// not allowed for Delphi style class objects

Note: For Delphi style classes, it is still valid to use C++ syntax to bind a reference. For example, the following code is valid:

 TRTLStyleClass *ptr =  new  TRTLStyleClass ; 
 TRTLStyleClass &ref = *ptr;// OK for Delphi style classes

Although this is not the same as using an assignment operator, the syntax is similar enough that it is mentioned here for clarification and comparison.

Copy constructors

Object Pascal does not have built-in copy constructors. Consequently, Delphi style classes in C++Builder do not have built-in copy constructors. The following example code attempts to create a TButton pointer by using a copy constructor:

 TButton *B =  new  TButton(ownerCtrl) ; 
 TButton *C =  new  TButton(*B);// not allowed for Delphi style class object s

Do not write code that depends upon a built-in copy constructor for Delphi style classes. To create a copy of a Delphi style class object in C++Builder, you can write code for a member function that copies the object. Alternatively, descendants of the RTL TPersistent class can override the Assign method to copy data from one object to another. This is typically done, for example, in FMX graphics classes such as TBitmap and TIcon that contain resource images. Ultimately, the manner of copying an object can be determined by the programmer (component writer); but be aware that some of the copy methods used in standard C++ are not available for Delphi style classes.

Objects as function arguments

As discussed previously, instance variables in C++ and in Object Pascal are not identical. You should be aware of this when passing objects as arguments to functions. In C++, objects can be passed to functions either by value, by reference, or by pointer. In Object Pascal, when an object is passed by value to a function, remember that the object argument is already a reference to an object. So, it is, in fact, the reference that is passed by value, not the actual object. There is no Object Pascal equivalent to passing an actual object by value as in C++. Delphi style objects passed to functions follow the Object Pascal rules.

See Also