Delphi for C++ Programmers

本文旨在帮助C++程序员向Object Pascal(Delphi)过渡。介绍了两种语言的主要差异,如Object Pascal缺少多重继承、模板和重载等C++特性,同时也有自身独特优势。还详细讲解了指针、字符串、对象等方面的语法差异,以及其他语法元素的不同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

发信人: Mars (FangQ), 信区: Programming
     
     
  题: [HTML]Delphi for C++ Programmers
     
发信站: The Big Green (Sat Jul 27 01:36:29 2002) , 转信
     
 
    

 

Delphi
for C++ Programmers

 


 

 

Introduction

 


 

 

There are a lot of Delphi books out there, but 99% of them deal only with the

more "glamorous" visual aspects. While the visual interface is the main

attraction of development systems like Delphi and Visual Basic, their greatest

strength is that they free the programmer from the drudgery of coding the user

interface, and allow him or her to work on the actual program.

 

It doesn't matter how visual your tools are (or how fantastic the

manufacturer's claims), you won't accomplish much without actually coding the

logic behind the interface.

 

This text is meant to aid C++ programmers in the transition to Object Pascal.

Although the main features of both languages are relatively similar, there are

certain small differences that can be confusing, especially when they lead the

programmer into making incorrect assumptions.

 


 

 

The Major

Differences

 


 

 

There are three main C++ features missing from Object Pascal, these are:

multiple inheritance, templates and overloading . I

can hear the groans now, but don't despair. Object Pascal has enough great

features to more than compensate for these omissions. There are also many Object

Pascal features that are missing from C++ (and they have nothing to do with the

"visual thing").

 

Other major differences include:

 

 

1.      Common base class - In Delphi, all objects descend from TObject.

2.       

3.      No stack objects - In C++ you can create objects on the stack or on the

4.      heap. All Delphi objects are created on the heap, and referenced via pointers.

5.       

6.      Full RTTI - Delphi's Run Time Type Information is more complete than C++'s.

7.       

8.      Class references - In C++ you always work on objects, but in Delphi, you can

9.      also work on uninstantiated classes.

10.   

11.  Properties - A very user-friendly language extension. It's like designating

12.  methods to be executed upon reading from, or writing to, a data member. (This

13.  can be implemented in C++, but it's not as simple. Check out the C++ section for more details.)

14.   

 


 

 

Pointers

 


 

 

Pointers give C a lot of it's power and flexibility, but they are also the

cause of most major bugs. There are pointers in Pascal too, but the compiler is

a little more protective (or restrictive, depending on your point of view).

 


 

 

Declaring &

De-referencing

 


 

 

The syntax for declaring pointers in Pascal is similar to the one used in C.

The main difference being that the caret ("^") is used instead of the

asterisk ("*

"):

  
{ Declare

a pointer to a character

}
  CharPtr: ^char;

To de-reference

a pointer, the caret is placed on the right hand side of the

variable:

  { Set

MyChar to what CharPtr points to

}
  MyChar :=

CharPtr^;

Whatever follows the caret must be a defined

type. You can't directly create a pointer to an array,

structure or class. You must first define these as types

before you can create pointers to them.

 

While in C you can do this:

 

  // Pointer to a pointer to
  // an

array of 5 characters
  char

**CharArrPtr[5];

>

 

In Pascal you are required to do it in steps:

 

  type

    { define type: array of 5 characters

}
    TChArr = Array [0..4] of char;

    { define type: pointer to TChArr

}
    TPChArr = ^TChArr;

  var
    { declare

variable as pointer to type TPChArr }

    CharArrPtr:

^TPChArr;

 


 

 

Indexing

 


 

 

This may come as a shock to most C programmers, but in Pascal, as a general

rule, pointers can't be indexed. A Pascal pointer lets you reference one, and

only one object in memory. This rule is not as limiting as it may seem at first,

since the object that you reference through the pointer can be an array, a

structure or a class.

 

When you need a pointer to a list of integers, you use a pointer to an array

of integers instead of a pointer to an integer. You still can't index a pointer

to an array, but you can index the array itself. The way to accomplish this is

by de-referencing the pointer before using the index.

 

For these declarations:

 

  type<

/tt>
    {

declare type: array of 101 char

}
    TCharArr = Array

><>color="#808080">[0..100] of

char;

< br>
    { declare type: pointer

to an array of 101 char

}
    TCharArrPtr

=

^TCharArr;

  var< br>     { declare a pointer to an array of 101 char

}
    MyPtr:

TCharArrPtr;>

 

The following facts apply:

 

   { This

is wrong, can't index a pointer }
  X

:= MyPtr[10];



  { This is fine.

De-referencing the pointer }
  { gives you an array, which can be indexed

}
  X :=

MyPtr^[10];

 


 

 

Allocating &

Deallocating

 


 

 

Just like in C, the Delphi programmer is responsible for the allocation and

deallocation of pointer space. There are several ways of allocating memory for

pointers. The simplest one is through the procedure "New".

 

The procedure "New" allocates the exact amount of memory needed for the

specified pointer. Using the previous example:

 

  New(<

/tt>MyPtr);

 

Allocates exactly 101 bytes to "MyPtr" (since it points to an array of 101

characters).

 

There is also another form of "New", a function, which may be used for the

same purpose. In this version, the parameter is a type, not a variable. The

return value is a pointer to the allocated space.

 

  MyPtr :=

New(>TCharArrPtr<>color="#808080">);

 

This is a tad more complicated, but would be useful if you wanted to allocate

memory for one type of data, but wanted to point to it with a different type

pointer (like an untyped pointer).

 

To deallocate the memory allocated with "New", you must use

"Dispose":

 

  Dispose(MyPtr><>color="#808080">);

 

If you want to be able to specify the exact amount of memory to allocate, you

can use the "GetMem" procedure. To allocate the 101 bytes

needed for "MyPtr", you would do the following:

 

  GetMem(MyPtr><>color="#808080">,

101);

 

Allocating more than the space required is a waste of memory, since Delphi

won't let you index it anyway (See the section "Range Checking and Pointers").

Allocating less could cause serious problems if you write to the unallocated

part of the variable.

 

To deallocate this memory, you must use "FreeMem", and you

must explicitly state the size of the allocated memory:

 

  FreeMem(MyPtr, 101);

 


 

 

Range Checking and

Pointers

 


 

 

When you declare an array, you must specify an upper and lower value for it's

index. The Pascal compiler, unlike C's, performs range checking to ensure that

you don't use an out of bounds index . This offers additional protection against

memory overwrites, but has an unexpected side-effect (unexpected for C

programmers that is): pointers to arrays are also range checked.

 

Since you are responsible for allocating memory for the array pointer, and

you can allocate as much or as little memory as you want, you may be tempted to

assume that you can use as high an index as you need. This is not the case.

 

Remember that you can't really index the pointer. You must de-reference the

pointer and then index the array. Since the array has specific index boundaries,

you are constrained by them.

 


 

 

Dynamic

Arrays

>


 

 

So, what happens if you need an array of variable size? Well, Pascal was

never meant to support variable size arrays. However, there is an easy, if

rather inelegant, workaround (e.g. a hack). What you must do is declare a

pointer to an array as big as it can possibly be. In 16 bit Delphi, this size

limit happens to be 32,767 bytes (32k), but in Delphi 2.0, you have a little

more space; about 2,147,483,647 bytes (yes, that's 2gb!). The upper bound of the

array would be this number divided by the length of the array's type:

 

  const
    MAX_SIZE = 2147483647;

 

  type<

/tt>
    TMyArr = Array

><>color="#808080">[0..(MAX_SIZE

div

SizeOf(AType))]

< font

color="#800000">of

AType;
    TMyPtr =

^TMyArr;

 

After this, you can declare variables of type TMyPtr, and

allocate as much or as little memory as you need. The only thing to keep in

mind, is that for all practical purposes, you won't have range checking in

effect for this type of array.

 

By the way, don't be deceived into thinking that you can use any mathematical

expression in the declaration of an array. Only constant expressions, those that

can be resolved at compile time, can be used here.

 

I must point out that you will rarely need to perform any of these steps.

Delphi comes with a very useful class called TList which

implements all of the functionality of a dynamic array of pointers. Since all

objects are pointers, you can use TList with them. If you need

an array of strings, you can use TStringList.

 

I only bothered with the above explanation, because I think it will give C

programmers an insight into how things work in Pascal. 

 


 

 

Strings

 


 

 

In Pascal, you do not generally need character pointers for text. There's a

string data type that simplifies string handling immensely.

Pascal strings are particularly easy to use because the assignment and addition

operators can be used to set and concatenate them.

 


 

 

Strings in 16 bit

Delphi

 


 

 

In Delphi 1.0, when you declare a variable of type string,

you can specify a size from 1 to 255 characters; if you omit the size, it

defaults to 255. The first byte of the string (byte number zero) contains the

length of the text that's stored in the string. You do not include the length

byte when declaring the size.

 

  MyVar1:

string[3];

  { 3 chars + length byte

}
  MyVar2: string[255]; { 255 chars + length byte

}
  MyVar3: string;

     { 255 chars + length byte

}
  MyVar4: string[300]; { Syntax error }

 

Because of the length byte, Pascal strings don't need a null-terminator.

 

Although it is possible to directly read and set byte #0, it is better not to

do this. The "correct" way of getting the length of a string is through the

Length function. The length is set automatically when you

assign or add a value to the variable.

 

Changing the length byte won't change the allocated size, only the size of

the text. (much like moving the null terminator in a C string). For example, a 5

character string would initially look like this:

 

  [0][0][0][0][0][0]   

;  <-if you

print this, it will say: "".
  

^-Length Byte

 

If you assigned it the word "HELLO", it would look like this:

 

  [5][H][E][L][L][O]   

;  <-if you

print this, it will say: "HELLO".
  

^->Length

Byte

 

If you assign it the word "GOODBYE", it would look like this:

 

  [5][G][O][O][D][B]   

;  <-if you

print this, it will say: "GOODB".
   ^->Length

Byte

 

As you can see, the word gets truncated at the fifth

character, because the variable is only 5 bytes long (plus byte #0). If

you now assign it the word "HI", it would look like this:

 

  [2][H][I][O][D][B]   

;  <-if you

print this, it will say: "HI".
   ^->Length

Byte

 

Since "HI" is a two letter word, the length byte now contains a "2". The

positions after the "I" have not been changed.

 


 

 

Strings in 32 bit

Delphi

 


 

 

In Delphi 2.0, strings have improved dramatically. The maximum size for

strings is now 2 gigabytes, and they are dynamically allocated. This means that

you now declare them without an initial size, and the strings grow and shrink as

necessary depending on what you assign to them.

 

The strings described in the previous section are still available on Delphi

2.0, but the type is now called "ShortString". Also, if you

use the old style declaration with a size between 1 and 255, you'll get a

ShortString:

 

var
  newstr1:

string;

     { new type of string

}
  oldstr1:

string[255]; { old type of string

}< tt>
  oldstr2
:

ShortString;>

<>color="#408080">{ old type of string

}< tt>
  newstr2
:

AnsiString;

  { new type of string

}

 

There is also a new string related function:

SetLength. This function forces a string to reallocate itself

to a specific size. This can be useful for truncating values, and for allocating

space for character by character operations:

 

  msg := 'Hello';    { Allocs 5 bytes and sets to 'Hello'

}
  SetLength(msg, 3); { Reallocs to 3 bytes (& truncates)

 }
  ShowMessage(< /tt>msg);  { Displays the message

'Hel'         }>

 

  SetLength< font

color="#808080">(msg, 4); { Reallocs to 4 bytes, adding a char

}
  msg[4] := 'p';     < font

color="#408080">{ Assigns 'p' to the last

char       }
  ShowMessage(< /tt>msg);  { Displays the message

'Help'        }

 


 

 

In General

 


 

 

Individual characters in a string can be accessed by indexing, just like

character arrays in C, with the exception that the first character is #1 instead

of #0.

 

Unlike C's strings, Delphi's aren't pointers. If you assign one string to

another, the value is copied from the source to the destination. Here is

(roughly) how a Delphi string assignment would look in C++.

 

  16 bits

  32 bits

  char str1[256];
  char str2[256];
  ...
  strcpy( str2, str1);

  char < /strong>*str1 = NULL;
  char *str2 = NULL;
  ...
  if (str2< /strong>) delete str2;
  str2 =< /strong> new char[strlen(str1)+1];
  strcpy( str2, str1);

 

The same applies when passing strings as parameters (unless they're

"var" parameters).

 


 

 

C Style

Strings

 


 

 

There are times, like when making API calls, when you absolutely must use a

C-style null-terminated string. For this reason, Delphi lets you use C-style

strings too. Their type is known as PChar, and as you may have

already guessed, they are character pointers (but of a special kind). Unlike

strings, PChars must be explicitly allocated and deallocated.

 

The functions used to allocate and deallocate PChars in Delphi are

StrAlloc and StrDispose. There is also a group

of functions used to manipulate these strings. A pleasant surprise is that their

names are almost the same as their C counterparts. Some of these are:

StrCopy, StrComp, StrCat and

StrLen. There is also a function called StrFmt that works just like "sprintf".

 


 

 

Why have

PChars

 


 

 

A PChar is not exactly the same as a pointer to a char. As you already know,

in Pascal, you can't index a character pointer. To be able to access the

elements via indexing you would normally need a pointer to an array of

characters. Even then, you would need to de-reference the pointer before

indexing it. The PChar is a new type that is treated in a special way by the

compiler so that it works exactly like a char pointer in C. 

 


 

 

Objects

 


 

 

In C++, there are two ways to instantiate an object: on the stack or on the

heap. In Delphi, all objects are created on the heap. When you declare a

variable as an object type, you are actually declaring a pointer. In this

example:

 

var
  MyList:>   TList<>color="#808080">;
  MyButton:

TButton;

>

MyList is actually a pointer to a TList object in the heap. Of course, until

you assign something to MyList, it doesn't point to a valid object. You must

create an object an assign it to MyList before you can access any of it's

methods or properties.

 

In Delphi, unlike C++, an object's constructor allocates it's own memory, and

you must explicitly call the constructor:

 

  MyList   :=

TList.Create;
  MyButton

:= TButton.Create(Self);

 

This is equivalent to the following C++ statements:

 

  MyList   = new

TList;
  MyButton = new

TButton(this);

 

When you finish using the object, you must explicitly deallocate it's memory

by calling the object's "Free" method. "Free"

is not the object's destructor; that one is typically called

"Destroy"; but "Free" calls

"Destroy" after performing certain checks. A programmer would

normally redefine "Destroy", but call "Free".

 

  MyList.Free;
  MyButton.Free;

 

This is the equivalent of using "delete" on objects in

C++:

 

  delet e

MyList;
  delete

MyButton;

But wait! Isn't MyList a pointer? Shouldn't it have to be dereferenced before

calling Free or any of it's methods? Yes, it should, but object pointers are

different from regular pointers. They don't need dereferencing (in fact, they

don't allow it). This makes for a simpler syntax, and code that's a lot easier

to read and maintain.

 


 

 

Virtual and

Override

 


 

 

Just like C++, Object Pascal has virtual methods (i

n fact it has several kinds of virtual methods). A method is defined as such

with the keyword "virtual". The difference here is that when

you redefine a virtual method you have to use the "override"

directive. If you don't, the new method will just hide the old one, as if it was

static. For example:

 

For the base class TMyBase:

  
TMyBase

=

class
    { declare a virtual method

}
    procedur e

MyMethod(Arg1

:

Integer); virtual;
    procedur e

MyCaller;
  end;

 

  procedure TMyBase.MyMethod(Arg1: Integer);
  begin
    { write the name of the class plus Arg1

}
    writeln('TMyBase [' +

IntToStr(Arg1)

+ ']');
  end;

 

  proce

dure TMyBase.MyCaller;
  begin<

/font>
    MyMethod(1);
  end;

 

When you call TMyBase.MyCaller, you get: 'TMyBase

[1]'.

 

In a class derived from TMyBase, the method "MyMethod&q

uot; can be overridden like this:

 

  TMyChild = class(TMyBase)
    { override the virtual method

}
    procedur e

MyMethod(Arg1: Integer); override;
  end;

 

  procedure TMyChild.MyMethod(Arg1: Integer);
  begin
    { write the name of the class plus Arg1

}
    <

/tt>writeln('TMyChild [' +

IntToStr(Arg1)

+ ']');
  end;

 

Now, when you call TMyChild.MyCaller, you'll get:

'TMyChild [1]'

 

A hassle you say? Maybe. But it gives you the flexibility of deciding whether

or not to override the virtual method. If you do this instead:

 

  TMyChild = class(TMyBase)
    { don't override the virtual method

}
    procedur e

MyMethod(Arg1: Integer);
  end;

 

  procedure TMyChild.MyMethod(Arg1: Integer);
  begin
    { write the name of the class plus Arg1

}
    <

/tt>writeln('TMyChild [' +

IntToStr(Arg1)

+ ']');
  end;

 

Then "MyMethod" will be treated (for polymorphic purposes)

as if the original definition was static. When you call TMyChild.MyCaller,

you'll get: 'TMyBase [1]'.

 

You can not, by the way, override a static method.

 


 

 

Invoking Redefined

Methods

 


 

 

You can use "inherited" to call the most recent version of

an inherited method, even if it is being redefined or overridden in the current

class. However, if you need to call an older version of the method, you are out

of luck.

 

  procedure<

strong> TMyClass.MyMethod(Arg1: Integer);
  begin<

/font>
    {

call the inherited virtual method

}
    inherite d

MyMethod(Arg1);
    
    { call a different inherited method

}
    inherite d

OtherMethod;>
  end;

 

Inside an event handler, you are allowed to call the ancestor handler without

knowing it's name. You do this by calling "inherited" all by itself.

 

  { Event handler.

You only need the keyword

}
  procedure

WMPaint(var

Msg:> TMessage);<

strong>
  begin<

/font>
    ...


    inherite d;
    ...


  end;

 


 

 

Inherited Constructors and Destructors

 


 

 

One of the greatest sources of bugs for C++ programmers moving to Delphi is

forgetting to call inherited constructors and destructors explicitly.

 

Derived class constructors in C++ can explicitly indicate which base class

constructor to call, but the compiler will automatically call the base class'

default constructor if none is specified. For this reason, it is very common to

do this in C++:

 

  TMyClass::TMyClass
  {
    // Your Code Here
  };

 

instead of:

 

  TMyClass::TMyClass : TMyBase
  {
    // Your Code Here
  };

 

However in Object Pascal, if you redefine a constructor, you must

explicitly call the inherited constructor. All classes have at least one

inherited constructor and destructor (the ones inherited from TObject).

 

  const ructor

TMyClass.Create;
  begin<

/font>
    {

Call the base class'   }
    { constructor explicitly

}< tt>
    
inherite d

Create;
    
    { Your code here

}< br>   end;

 

This would be the same as the following C++ construct:

 

  TMyClass::TMyClass;
  {
    / / Call the constructor of this
    //

object's base class explicitly
    T

MyBase::TMyBase;
    
    / / Your code here
  };

 

Do not attempt to use a similar syntax with Object Pascal. While the program

would compile, the logic would be wrong:

 

  const ructor

TMyClass.Create;
  begin<

/font>
    {

This is not what you expect

}
    TMyBase.Create;
    
    { Your code here

}
  end;

 

This constructor is indeed calling the constructor for the base class, but it

is just creating an independent object of type TMyBase. This does not allocate

memory for the current object, nor does it initialize it.

 

The call to the inherited constructor is generally the first statement in a

constructor. This is not a syntax requirement; you can call class methods and

non-member functions and you can access local, global or modular variables

first; but if you try to access any of the class' data elements or methods

before calling the inherited constructor, you'll get a General Protection

Fault.

 

As sneaky as this error can be, it's nothing compared to what happens when

you forget to call the inherited destructor. With the constructor, you at least

get a GPF that tells you where the error occurred. With the destructor however,

your problem is more difficult to detect: you just start running out of memory.

Depending on your program, you may notice performance degradations, inability to

allocate memory, running out of Windows resources, locked devices or files,

etc.

 

To prevent this from happening, always call the inherited destructor. This is

usually done at the end of the new destructor (but again, this is not a

syntactical requirement):

 

  destr

uctor TMyClass.Destroy;
  begin<

/font>
    {

Your code here

}
    
    inherite d

Destroy;
  end;

 

One other thing about destructors: remember to

"override>" them. The "Free" method won't find your

new destructor if you don't. Neglecting this is just as bad as forgetting to

call the inherited destructor.

 


 

 

Multiple

Constructors

 


 

 

Since there is no overloading in Object Pascal, you might be wondering how

you can have multiple constructors. The answer to this is very simple: The old

fashioned way!

 

You can have as many constructors as you want, provided they each have a

different name. While in C++ all constructors have the same name as the class,

in Object Pascal they are generally called "Create". This is not a requirement,

just a standard. If you need extra constructors, you generally use the word

"Create" with something else. For example:

 

  constructor>

CreateCopy( iOriginal: TObject);
  constructor

CreateAsChild(iParent: TObject);
  constructor

CreateFromFile(iFileName: string);

 

You can only override a constructor with another that has the same name and

parameter list (even the argument names are important). If you only match the

constructor's name, you'll only be "hiding" the inherited constructor.

 

If you are developing a Visual Control, keep in mind that all controls

must have a constructor declared like this:

 

  const ructor

Create(AOwner: TComponent); override;

 

If you omit this declaration, Delphi won't be able to instantiate your

control.

 


 

 

Common Base

Class

 


 

 

Every object created in Delphi is a descendant of TObject.

If you don't specify a base class when declaring your class, Delphi derives it

from TObject anyway. All components are derived from

TComponent (which of course, derives from

TObject), and all controls are derived from

TControl (which is in turn derived from

TComponent), etc.

 

The importance of this fact is that it gives the Visual Component Library a

great advantage over C++ class libraries like OWL and MFC. Since all objects

have a common ancestor, you can create container classes that can take any kind

of object, (or components only, or controls only, etc.) neatly doing away with

one of the main reasons for requiring templates.

 


 

 

The Self

Pointer

 


 

 

The "self" pointer is Object Pascal's equivalent to C++'s

"this" pointer. They are exactly the same except in one case.

When used within a class method, self refers to the

class and not to the object (the instance). This hardly ever

matters, since class methods are very rare, and you can't do a great deal in

them anyway.

 


 

 

Class Methods

 


 

 

Class methods are member functions or procedures that act on a class instead

of an instance of a class.

 

You can call a class method in the regular manner, but you can also call it

without having an object instance. This is done by prepending the class name

instead of the name of an instance. A class method's "self" pointer refers to a

class instead of an object.

 

If you want to turn a method into a class method, you just prepend the word

"class" to it's declaration (and definition). The compiler will

not let you access any data elements or regular methods from within a class

method.You can declare local variables though. An example of a class method is

the GetClassName function:

 

  class function

TMyClass.GetClassName<

/strong>:

string;


  begin
    Result := 'TMyClass';
  end;

 

Constructors are a special kind of class method. The constructor's "self"

pointer is a regular object pointer, not a class reference; and you can access

data elements from within it (just make sure you call that inherited constructor

first).

 


 

 

Member

Visibility and "Friends"

 


 

 

In C++ we are used to the keywords: "public",

"private" and "protected". These are present

in Object Pascal as well, but they work a little different.

"Public" works as expected, but "private" and

"protected" have no effect on other classes declared within

the same unit. In other words, all the classes declared in the same unit are

friends with each other. This is important, since there is no

"friend" keyword in Delphi.

 

Delphi also has a "published" keyword which behaves almost

exactly like "public", but you won't need to use it unless you

want to create your own controls. Since there is nothing similar in C++, the

"published" keyword is beyond the scope of this text.

 


 

 

The Scope

Resolution Operator

 


 

 

C++ has the double-colon ("::"), but Object Pascal, has no separate scope resolution operator.

Instead, the dot (".")serves multiple duty.

 

We already know that the dot is used in method declarations, and for

accessing methods, properties and data members. But when there's a name conflict

between a stand-alone function or procedure and a class method, you can precede

the function call with the name of the unit that contains the function and a

dot:

 

Language

Syntax

C++

<var> = ::<function>(<arg list>);
X = ::GetName(Handle);

Object Pascal

<var> := <unit>.<function>(<arg list>);
X :=
> SomeUnit.< /font>GetName(Handle><> color="#808080">);

 

As discussed earlier, you can not use the dot notation to call an inherited

method, for this you would use the keyword "inherited<

/strong>". 

 


 

 

Other Syntax

Elements

 


 

 

Here are some relatively trivial items that can be annoying to C++

programmers.

 


 

 

The Assignment

Operator

 


 

 

Remember "=" is for

comparison and ":=" is for

assignment. You will often find yourself using C++'s operators. No big deal, the

compiler will catch the error, because Pascal doesn't allow the use of the

assignment operator in evaluation expressions, nor does it permit chained

assignments.

 


 

 

The Else>

Clause

 


 

 

The statement preceding an "else" must never end in a

semicolon. You will probably always forget this. Even seasoned Pascal

programmers forget it. The compiler will catch it, but it's rather annoying.

 


 

 

Incrementing and Decrementing Values

 


 

 

In C++, the "++&q

uot;, "--", "+=" and "-=" operators are a very useful

(and fast) shorthand. In Delphi, there are two useful, if not as elegant,

equivalents: "Inc " and "Dec".

 

C++

Pascal Code>

Shortcuts< /td>

++><> color="#000000">A; A++;

A := A + 1;

Inc(A);

--><> color="#000000">A; A--;

A := A - 1;

Dec(A);

A +=2;

A := A + 2;

Inc(A,2);

A -=2;

A := A - 2;

Dec(A,2);

 

Although Inc and Dec look like regular procedures, the fact that they can

have one or two parameters gives us a hint that they are not (there's no

overloading in Pascal). In fact, the compiler generates more efficient code for

them than for the regular assignment-and-addition or assignment-and-subtraction.

 

Inc and Dec are not exact equivalents for

the "++" and "--" operators. Since they are

procedures, not functions, they don't return a value, so they can't be used in

expressions.

 

 

-- 你佛慈悲 ※ 来源:.The Big GreenWWW BBS.Dartmouth.Edu.

[FROM: 129.170.66.196] ※ 修改:.Mars 于 Jul 27

01:38:43 修改本文.[FROM: thayer66-bp-196.]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值