Calling a constructor
A constructor is a hybrid of object and class methods. You can call it using an object reference or a class reference. Delphi passes an additional, hidden parameter to indicate how it was called. If you call a constructor using a class reference, Delphi calls the class''''s NewInstance method to allocate a new instance of the class. After calling NewInstance, the constructor continues and initializes the object. The constructor automatically sets up a try-except block, and if any exception occurs in the constructor, Delphi calls the destructor.
When you call a constructor with an object reference, Delphi does not set up the try-except block and does not call NewInstance. Instead, it calls the constructor the same way it calls any ordinary method. This lets you call an inherited constructor without unnecessary overhead.
TIP:
A common error is to try to create an object by calling a constructor with an object reference, rather than calling it with a class reference and assigning it to the object variable:
var Account: TSavingsAccount; begin Account.Create; // wrong Account := TSavingsAccount.Create; // right
One of Delphi''''s features is that you have total control over when, how, and whether to call the inherited constructor. This lets you write some powerful and interesting classes, but also introduces an area where it is easy to make mistakes.
Delphi always constructs the derived class first, and only if the derived class calls the inherited constructor does Delphi construct the base class. C constructs classes in the opposite direction, starting from the ancestor class and constructing the derived class last. Thus, if class C inherits from B, which inherits from A, Delphi constructs C first, then B, and A last. C constructs A first, then B, and finally C.
Virtual methods and constructors
Another significant difference between C and Delphi is that in C , a constructor always runs with the virtual method table of the class being constructed, but in Delphi, the virtual methods are those of the derived class, even when the base class is being constructed. As a result, you must be careful when writing any virtual method that might be called from a constructor. Unless you are careful, the object might not be fully constructed when the method is called. To avoid any problems, you should override the AfterConstruction method and use that for any code that needs to wait until the object is fully constructed. If you override AfterConstruction, be sure to call the inherited method, too.
One constructor can call another constructor. Delphi can tell the call is from an object reference (namely, Self), so it calls the constructor as an ordinary method. The most common reason to call another constructor is to put all the initialization code in a single constructor. Example 2-7 shows some different ways to define and call constructors.
Example 2-7: Declaring and Calling Constructors
type
TCustomer = class ... end;
TAccount = class
private
fBalance: Currency;
fNumber: Cardinal;
fCustomer: TCustomer;
public
constructor Create(Customer: TCustomer); virtual;
destructor Destroy; override;
end;
TSavingsAccount = class(TAccount)
private
fInterestRate: Integer; // Scaled by 1000
public
constructor Create(Customer: TCustomer); override; overload;
constructor Create(Customer: TCustomer; InterestRate: Integer);
overload;
// Note that TSavingsAccount does not need a destructor. It simply
// inherits the destructor from TAccount.
end;
var
AccountNumber: Cardinal = 1;
constructor TAccount.Create(Customer: TCustomer);
begin
inherited Create; // Call TObject.Create.
fNumber := AccountNumber; // Assign a unique account number.
Inc(AccountNumber);
fCustomer := Customer; // Notify customer of new account.
Customer.AttachAccount(Self);
end;
destructor TAccount.Destroy;
begin
// If the constructor fails before setting fCustomer, the field
// will be nil. Release the account only if Customer is not nil.
if Customer <> nil then
Customer.ReleaseAccount(Self);
// Call TObject.Destroy.
inherited Destroy;
end;
const
DefaultInterestRate = 5000; // 5%, scaled by 1000
constructor TSavingsAccount.Create(Customer: TCustomer);
begin
// Call a sibling constructor.
Create(Customer, DefaultInterestRate);
end;
constructor TSavingsAccount(Customer: TCustomer; InterestRate:Integer);
begin
// Call TAccount.Create.
inherited Create(Customer);
fInterestRate := InterestRate;
end;
Destructors
Destructors, like constructors, take an extra hidden parameter. The first call to a destructor passes True for the extra parameter. This tells Delphi to call FreeInstance to free the object. If the destructor calls an inherited destructor, Delphi passes False as the hidden parameter to prevent the inherited destructor from trying to free the same object.
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




