Translating C++ Code Into Delphi

download Translating C++ Code Into Delphi

of 46

Transcript of Translating C++ Code Into Delphi

  • 7/30/2019 Translating C++ Code Into Delphi

    1/46

    Translating C++ Code into Delphi Pascal

    Because Microsoft chose C++ as the language of Windows programming API and C++ is

    typically used in Unix and Linux programming systems, most books and many online

    resources present code written in C++ that can be very enigmatic to Delphi programmers. For

    commericial reasons C++ continues to be the principle language of discourse in the

    programming community, despite the fact that it based on ancient technology and the earliest

    attempts to build computer languages and compilers, and retains all of its obsolete syntax as a

    result. (Another superior language, which incorporates decades of research into language and

    compiler developement is Eiffel, which is simple, the new paradigm, even stricter than Delphi

    in many ways, and yet very powerful due to both its simplified syntax and the optimized code

    that results. The end result of compiler and programming research over a period of almost

    forty years is that a CPU with simple instructions and a compiler and language that is

    simplified results in superior execution speeds, with a RISC (Reduced Instruction Set

    Computer) always beating an Intel or Unix computer in performance for the same CPU speed.

    Nevertheless C++ has the weight of historical precedence behind it, even if it is not the best

    language, as all those bugs, buffer over runs, and security patches testify. For all these

    reasons, I have found it neccesary to understand C++ code, even if I don't plan to write muchof it myself, (prefering myself to learn Fortran 90 or Eiffel instead as additonal programming

    languages) and so I have begun to research the syntax and organization of C++ code, and the

    Delphi equivalents, and will be posting the results on this page.

    As I encounter more enigmas in C++ code and interpret them, these pages will be updated

    accordingly (my goal is to be able to read and translate C++ code). Some of the pages below

    rely on what is discussed on other pages (for example there is a page on pointers, but pointers

    are also discussed in the section on structures. I have tried to organize this material logically,

    but you might find it useful to jump back and forth a couple of times between pages, if you

    are unfamiliar with some of the features of C++)

    C++ Operators

    Scope of variables in C++

    If - then - else structures in C++

    The Switch statement

    For, while and do loops in C++

    Structures - records in C++

    C++ pointers, the stack and the heap

    Passing variables by reference and by value

    C++ File I/O

    C++ header interface files

    Classes and inheritance

  • 7/30/2019 Translating C++ Code Into Delphi

    2/46

    In addition to the discussion of C++ on this page, I have also included some examples of

    programs translated from C++ source code to Delphi to illustrate some of the points made in

    the articles linked to from this index page, and I post links to them below as they appear.

  • 7/30/2019 Translating C++ Code Into Delphi

    3/46

    Understanding C++ OperatorsTranslating C++ Code into Delphi Pascal

    C++ has five binary arithmetic operators, which take two operands and two unary

    arithmetic operators, which can take one operand. Five assignment operators can be created

    by combining these arithmetic operators with the equals sign to create 'assignment operators'.

    The arithmetic operators are +, -, *, /, %, with the operators + and - having unary versions

    which require only one operand. the assignment operators are +=, -+, *=, /+, and %=.

    In Delphi the assignment operator is ' := ' while in C++ the assigment operator is simply ' =

    '. This would be the equivalency operator in Delphi, while in C++ the equivalency operator is

    ' == '. So in Delphi we would write ' if x = 16 then ' and in C++ this would be written as ' if

    (x==16) '. In Delphi we would write ' x := y ' which sets x equal to y, and in C++ we drop the

    colon the perform the same operation ... ' x = y'.

    The other relational operators are similar in both languages. They are , =, == and

    then in Delphi where we write ' ' (not equal) in C++ this becomes ' != '.

    The logical operators in C++ representing a logical AND, OR, and NOT as applied to

    boolean operands are ' && ', ' || ', and ' ! '. There are also two logical assigment operators, '

    &= ' and ' |= ' which perform and assign the results of a logical AND and a logical OR

    operation respectively. For example,

    x &= 2;

    This would be similar to writing ' x := x AND 2; '

    One of the differences in a C++ logical test is that if the first test fails the second test maynot be evaluated. To accomplish the same thing in Delphi requires nested if - then statements

    (there is also a compiler option to turn off 'full boolean evaluation').

    For example the following statement would generate an error in Delphi in the second part

    of the statement if Delphi is doing full boolean evaluation and x is equal to zero, due to an

    attempted division by zero...

    if (x = 0) or (100 div x < 10) then

    In C++ this statement would not generate an error, since, if x was equal to zero the test

    would be considered a success and the other conditional statements need not be considered...

    if (x==0 || 100 / x < 10)

    Similarly in the above example a test to ensure that x is not zero would not cause a crash if

    the or relational operator was replaced by an 'and' relational operator.

    In C++ you might see operators and operands combined in the following ways...

    ++x;

    This is similar to writing inc(x) in Delphi, which means x := x + 1 (the difference being thatthe former generates more optimized code.

  • 7/30/2019 Translating C++ Code Into Delphi

    4/46

    The increment operator can appear before or after the operand...

    y = ++x;

    y = x++;

    In the first cause (pre-increment) x is incremented by one, and the result is then assigned to

    y. IN the second case, x is assigned to y and then x is incremented by one.

    In Delphi we could write...

    y := x; inc(x);

    And in C++ this becomes...

    y = x++;

    An example of using an assignment operator in C++ ...

    x /= z;

    In this case two operands (x and z) are combined using an assignment operator. This

    statement could also be written as ' x = x / z; '

    Assignment operators can also be evaluated from right to left in a statement resulting in

    strange looking calculations like the following.

    x = y *= 10;

    This is equivalent to following code...

    y = y * 10; x = y;

    When arithemetic operators are included multiple times in a single line the operators are

    evaluated from left to right if they have the same precedence, otherwise the operator with the

    highest precedence is evaluated first. One way to get around memorizing the precedence of

    operators is to enforce precedence using brackets, in which case the rule is that the inner most

    bracket is evaluated first, then so on until the outer most bracket is evaluated. For example,

    consider the following line of code without brackets.

    x = y + z - q * 6 / t;

    Both mulitiplication and division have a greater precedence than adding or substracting,

    and multiplication ' * ' and division ' / ' both have equal precedence so evaluating from left to

    right we get first q * 6 and then the result is divided by t. Then once again working from the

    left we get y + z evaluated and then the previous results of the multiplication and division are

    subtracted from this result and the solution is then assigned to the variable x. A change in

    precedence causes a change in results. One way to ensure that the results are what you want

    is to use brackets.

  • 7/30/2019 Translating C++ Code Into Delphi

    5/46

    Let us suppose that first q should be subtracted from z and 6 should be divided by t and

    then these two results should multiplied together and then added to y. To override precedence

    and get the results we wanted we would need to use brackets...

    x = y + ((z - q) * (6 / t));

    The two inner brackets are evaluated first, then the multiplication in the outer bracket is

    evaluated, the result of these operations are then added to y and assigned to the variable x.

    This is considerably different than what would result if the rules of precedence were applied

    (indeed such a calculation would just about impossible to achieve without the brackets.

    C++, like Delphi uses the ' dot operator ' to access fields of a record (on the stack) and a

    pointer operators to access variables on the heap.

    In Delphi, assuming we have a record 'info' with a field 'age' we could access this using the

    dot operator if this was a static instance of the record (which would thus be on the stack, and

    not require a pointer).

    x := info.age;

    If info was dynamically created using a pointer we could access the fields using a pointer

    operator...

    x := info^.age;

    C++ also uses the dot operator for static records...

    x = info.age;

    To access a record on the heap (created with a pointer) the indirection operator in C++

    looks like the following...

    x = info->age;

    Let us suppose that we have a pointer to an integer and wish to assign the value of the

    integer to a variable. In Delphi the indirection operator would appear as follows...

    x := intptr^;

    In this case ' intptr ' is a pointer to an integer delcared as follows...

    var intptr : ^integer;

    In C++ the variable is declared as follows...

    int* intptr;

    And then the indirection operation looks like the following...

    x = *intptr;

    This is pretty much the same as in Delphi.

  • 7/30/2019 Translating C++ Code Into Delphi

    6/46

    A short code segment illustrating how this works in Delphi...

    procedure TForm1.Button1Click(Sender: TObject);

    var px : ^integer;

    x : integer;

    begin

    new(px);

    px^ := 12;

    x := px^;

    showmessage(IntToStr(x));

    end;

    For a C++ example of the same sort of thing follow the link to the C++ section at the

    bottom of the page and consult the section on C++ pointers...

    C++ also has a bitwise not operator (the tilde ' ~ ')

    x |= ~0x02;

    What is meant is that this number will be combined with the variable x using a bitwise

    NOT operation (each bit subjected to a NOT operation, in otherwords reversed from 0 to 1 or

    from 1 to 0 before the OR operation is applied) and the result then assigned back to x. This

    bitwise NOT operand is different than the logical NOT operand represented by the ' ! '

    symbol, used in boolean expressions...

    if (!something)

    The scope resolution operator ( ' :: ') is discussed in the section on C++ Classes, and is the

    operand with the highest precedence.

    The table below illustrates operator precendence in C++ ... As you can see along with the

    field operators (used in structures) brackets then have the next highest precedence, for the

    reasons explained above...All operators in each group have equal precedence with assignment

    operators of equal precedence being evaluated right to left and other operators left to right as

    described above...(Therefore a bracket to the left of dot operator would have precedence,

    which makes sense...)

    :: scope resolution operator

    . (the dot operator), -> (pointer), [ ] (square brackets), ( ) (round brackets), ++ and -- (post

    increment/decrement), and the various types cast operands

    ~ (tilde - bitwise not), ! (logical not), + and - (unary), ++ and -- (pre increment/decrement),

    , & (the address of operator), * (dereference a pointer), the new, the delete, and the size of

    functions

    .* (the dot operator and the dereference operator), ->. (pointer operator and the dot

    operator)

  • 7/30/2019 Translating C++ Code Into Delphi

    7/46

    * (as multiply), / , %

    +, -

    > (the assign out to and assign into operators, typically used in printing or file I/O)

    , = (the relational comparison operators)

    ==, != (equivalence test operators)

    & (bitwise and)

    ^ (bitwise xor)

    | (bitwise or)

    && (logical and)

    || (logical or)

    =, +=, -+, *=, /+, %=, =, &=, |=, ^= (assignment operators)

    ? : (? is equivalent to 'then' and colon is equivalent to 'else' operator, with the lowest

    precedence so that everything is evaluated in the test statement before either the 'then' or 'else'

    code is executed, which also makes sense).

  • 7/30/2019 Translating C++ Code Into Delphi

    8/46

    Scope of Variables in C++Translating C++ Code into Delphi Pascal

    In Delphi the scope of a variable is determined by where it is declared. For example a

    variable declared within a function or procedure is 'in scope' (or known and visible) only

    within that particular function or procedure. The variable is created when the function or

    procedure is entered and executed and then once the function/procedure exits, the variable

    goes 'out of scope' and is also destroyed and the memory it consumed is free. A variabledeclared within one procedure is not visible to any other procedure. A variable declared at the

    head of unit is considered a global variable and is visible to every procedure and function

    within that unit. Note that because of caching of memory in high speed memory areas on the

    CPU it has been suggested that global variables be avoided as much as possible since they can

    apparently cause a large number of cache miss penalties which slow down the performance of

    system operating with such a cache. (The cache is normally loaded with memory which is in

    the area of currently executing code, although this explanation is a bit of simplification,

    however a global variable might exist in a far segment of memory not currently in the cache,

    thus causing the cache miss).

    In Delphi variables are declared before they are used at the beginning of the function or

    procedure definition using the var statement, or within the declaration header of the procedure

    or function if it is a variable that is passed to the function by another segment of code..

    function TForm1.ThisFunction(i : integer):integer;

    var x : integer;

    s : string;

    begin

    the code is here

    end;

    In this example the variable 'i' is passed to the function and thus is declared in the header.

    After the var statement the variables x and s are declared and then the body of the function

    begins after the begin statement.

    In C the situation is more complex. Variables can be declared within the body of functions.

    This also introduces complications in regards to the scope of variables. For example we could

    have two variables named 'x' declared within the body of one C function.

    int x=10;

    for (int x=20;x

  • 7/30/2019 Translating C++ Code Into Delphi

    9/46

    imagine loops nested within loops within functions all of which declare variables named x,

    each one with a different scope.

    Because variables are in scope only within the code segment that declares them statements

    such as the following will generate compiler errors.

    int y;

    for (int x=20;x

  • 7/30/2019 Translating C++ Code Into Delphi

    10/46

    I f - then - else statements in C++Translating C++ Code into Delphi Pascal

    The simplest form of an 'if - then' construct expressed in C is as follows.

    If (x == 10)

    DoSomething(x);

    If an if - then type construct has more than one statement to execute C uses curly braces to

    enclose the statements as follows...

    If (x > 10)

    {

    DoFirstThing;

    DoSecondThing;

    }

    C also allows the use of any non zero variable as the test in an if statement. As long as the

    variable is non-zero the test evaluates true and the following statement executes.

    If (x) DoSomething;

    The exclamation point indicates the not statement in C. In the following example if 'not x'

    the statement following will execute (in otherwords if x is zero, which makes the statement

    false, the '!' (not) operator will change the test result to true, so that the following statement

    executes)...

    If (!x) DoSomething;

    The else construct uses the following syntax...(Note the way the curly braces are used to

    seperate the if construct from the else construct...)

    If (x == 20)

    {

    DoSomething;

    DoAnotherThing;

    }

    else

    {

    DoSomethingElse;DoSomeOtherThing;

    }

    If statements can be nested as follows...

    If (x > 10)

    If (x < 20)

    DoSomething;

    Nesting can also become more complex by including multiple statements, which then

    requires the use of the curly braces to delimit the blocks of code...

  • 7/30/2019 Translating C++ Code Into Delphi

    11/46

    if (x > 10)

    {

    DoSomethingOne;

    If (x < 20)

    {

    DoSomeOtherthing;

    If (x = 15)

    {

    DoThatThing;

    DoThisThing;

    }

    }

    }

    else if (x > 0)

    {

    DoSomethingElse;

    If (x = 1)

    { DoWhatEver;

    DoWhatEverElse;

    }

    }

    else {

    DoThis;

    DoThat;

    }

    In the above construct if x > 10 the first block of code is executed, otherwise the 'else if'

    statement is tested and if x > 0 this second block of code executes. If neither of theseconditions is true (in this example x would less than 0) then the else block of code at the end

    of the construct is the only code that will execute...

    You can also see how keeping track of the curly braces can become complicated the more

    complex the structure becomes. (When the code to be executed consists of only a single line

    the curly braces are not required...) In the Borland version of C++ you can always find the

    curly brace that matches any other curly brace by placing the cursor over the brace you want

    to match and pressing ALT and the brace key (which, given that the shift key is not held down

    would be either ' [ ' or ' ] ' ....

    There is also an enigmatic looking 'short cut' syntax used in C for if - else constructs whichlooks as follows.

    x == 10 ? y = 16 : y = 5;

    The shortcut syntax means that if x is 10 then y becomes 16 else y becomes 5. Or, in

    Delphi, to compare the two statements, the question mark is equivalent to 'then' and the colon

    is equivalent to else...

    If x = 10 then y := 16 else y := 5;

    x == 10 ? y = 16 : y = 5;

  • 7/30/2019 Translating C++ Code Into Delphi

    12/46

    You will also notice the different syntax for equivalency texts and for setting the value of

    the variable. In Delphi a single equals sign ( = ) is the test for equivalency used in if

    statements while double equals signs are used in C to test for equivalency ( == ). Delphi uses

    a colon followed by an equal sign ( := ) to set a variable value, while C uses a single equals

    sign to set variable values ( = )...

    One difference between Delphi and C++ is the way the syntax for an if / then construct can

    be written. For example the following line of Code would generate an error in Delphi (the

    compiler will complain that it has the wrong operand type).

    If x = 6 or y = 11 then

    '6 or y = 11' is 'the wrong operand type' for a logical or operation. This should be written

    as...

    if (x = 6) or (y = 11) then

    Both (x = 6) or (y = 11) evaluate to boolean (true or false) expressions and thus providevalid 'operand types' for the or operation. In C++ this could be written as follows...

    if (x==6 || y==1)

    The brackets are not required, since the equivalency test operator in both cases has a higher

    precedence than the or operator.

  • 7/30/2019 Translating C++ Code Into Delphi

    13/46

    The Switch statement in C++Translating C++ Code into Delphi Pascal

    The switch statement simplifies complicated 'if then else' constructs in c ++ and is similar

    to the case statement in Delphi. The variable to be tested comes after the switch statement,

    and it can be variable, an expression or the result of a function.

    switch(x){

    case 1 :

    {

    dosomecode1;

    break;

    }

    case 2 :

    {

    docodefor2;

    break;

    }

    case 3 :

    case 4 :

    case 5 :

    case 6 :

    {

    docodefor3456;

    break;

    }

    default :

    {dodefaultcode;

    }

    }

    In the above example when x is 1 then code for 1 executes. The break statement is

    optional, however if you do not include it the switch statement will go through all the other

    comparisons, whereas with a break statement once a valid comparison is found the program

    executes the code segment and does not bother checking the other comparisons which is more

    efficient. When x is either 3, 4, 5, or 6 the same block of code will execute in each case, and

    if x has none of these values then the final default code executes. It is not mandatory to

    include a default switch, and it functions much like the final 'else' statement of a complicatedif - then - else construct.

  • 7/30/2019 Translating C++ Code Into Delphi

    14/46

    Loops in C++Translating C++ Code into Delphi Pascal

    The syntax for a repeating for loop in C++ follows this pattern

    for (StartingPoint; ConditionalExpression; Increment)

    {

    DoStatementOne;DoStatementTwo;

    }

    If there is only a single statement to be repeatedly executed within the loop the curly braces

    are not required.

    The loop will execute as long as the conditional expression is non-zero. The loop begins at

    Starting point, and each run through the loop the starting value is changed by the amount

    specified by increment.

    An example of what this looks like in practice

    for (int x=1;x0;x--)

    {

    the code is here;

    }

    In this case the loop begins at 20, and each iteration the value of x is reduced by one andthe loop terminates at 0 (continues as long as x is greater than 0).

    Variables can also be used int he conditional section of the loop declaration and the loop

    can be incremented or decremented by an amount other than 1 using the following syntax...

    for (int x=10;x>y;x+=4)

    {

    code hre;

    }

  • 7/30/2019 Translating C++ Code Into Delphi

    15/46

    In this example the x begins at 10 and each iteration x is increased by adding four and the

    loop terminates when x becomes greater than y. Similarly the expression x-=4 would

    decrease x by four each time throught the loop.

    The while loop executes as long as the conditional expression remains true (therefore it is

    required that the code within the loop manipulates the conditional expression in such a way as

    to eventually result in the stopping condition so that the loop does not execute forever...)

    int x;

    while (x < 10)

    {

    DoSomething;

    x = SomeCodeResult;

    }

    Once again the syntax for declaring a variable is different than in Delphi in this example as

    x is declared as an integer just before being used in the loop. The loop code manipulates the

    variable x and should eventually return a result that makes x greater than or equal to ten sothat the loop terminates at some point.

    A variation of the code manipulates the variable within the loop declaration itself.

    int x = 10;

    while (x++ < 20)

    {

    Dosome code here;

    }

    Here x is set to the value 10 and then incremented by one each time through the loop withthe loop terminating when x reaches the value 20.

    C also has a 'do - while' loop structure that mimics the 'repeat - until' structure in Delphi.

    int x = 10;

    do

    {

    code is here;

    x = something;

    } while (x < 20);

    This is similar to the following Delphi code (with the difference that in Delphi the variable

    x would be declared as integer at the beginning of the function or procedure)...

    x := 10;

    repeat

    do some code;

    x := something;

    until (x >= 20);

    The C language also has two special statements that resemble statements used in assembly

    language, the continue and the break statements. The continue statement causes the programto skip whatever code follows in the loop and go on to the next iteration of the loop. The

  • 7/30/2019 Translating C++ Code Into Delphi

    16/46

    break statement jumps out of the loop altogether and goes onto the code following the loop

    (the code which would normally be executed once the loop terminated).

    The following simple example assumes that when the loop value is 5 the code following

    should not be executed and the loop should simply move on to the value 6.

    for (int x=1;x

  • 7/30/2019 Translating C++ Code Into Delphi

    17/46

    Structures in C++ and records in DelphiTranslating C++ Code into Delphi Pascal

    A structure in C is analogous to a record in Delphi. A record can be thought of as a kind of

    complex variable declaration.

    type

    MyData = recordphonenum : string;

    married : boolean;

    age : integer;

    name : string;

    end;

    var

    Datalist : MyData;

    In this example we use the type statement to create a custom data type, in this case a record.

    The declaration of the record can then be used in the var statement to initalize an actual

    instance of the declared data type. The record above is a kind of a custom variable which

    consists of a number of different variable types stored as a single data record.

    We can access a field of the record using the dot operator.

    thephonenum := Datalist.phonenum;

    Sometimes it is more convenient to use pointers to records.

    type MyDataListPointer = ^MyData;

    The declaration of the MyData record then follows as above and then in the var declaration

    we declare a pointer to a record instead of a static instance of a record.

    var

    DataListPtr : MyDataListPointer;

    We then create an actual record from this pointer using the new statement.

    new(DataListPtr);

    And we access the fields of the record using pointer syntax.

    DataListPtr^.phonenum := '336-3344';

    There are many variations in the way records (or structures) are stored and manipulated

    (linked lists, arrays of records, etc.) It is impossible to access common graphics formats,

    Windows or Linux API functions, etc., without dealing with records and so this is a very

    common and very important data type. Records, or structures as they are called in C, are used

    throughout APIs and as interfaces to many standard functions. (For example a common

    bitmap graphic consists of a structure (or record in Delphi), which is referred to as the

    Bitmap info header, which stores in record form all the information about the height, width,

    color depth, etc., of the following raw bitmap data in the file.) The usefulness of records (or

  • 7/30/2019 Translating C++ Code Into Delphi

    18/46

    structures as C calls them) in database applications should be obvious, and they are used in

    any application where related data must be stored conveniently in a single structure.

    If you are familiar with records in Delphi, the structure in C encapsulates the same idea

    using the syntax defined for this purpose in the C language. The keyword 'record' and the

    syntax illustrated above is used to define records in Delphi, and C uses the keyword struct and

    the following syntax...

    struct MyData {

    char phonenum[8];

    bool married;

    int age;

    char name[20];

    };

    This struct statement creates the equivalent of the record declared in Delphi above. This

    declaration defines the 'type' of the structure, just as using the type declaration in Delphi to

    declare a variable of the type record. To create an instance of the record in Delphi you use itin the var declaration as the variable type for the variable being declared as demonstrated

    above. In C you can crate an instance of the structure by including the name of the variable

    after the closing curly braces and before the final semi-colon which completes the definition.

    struct MyData {

    char phonenum[8];

    bool married;

    int age;

    char name[20];

    }Datalist;

    In the example above we have described the type of the structure and then we created an

    instance of the structure - a variable given the name Datalist. Note that C is case sensitive, so

    a variable named Datalist is not the same as a variable named datalist or DataList, whereas all

    three would refer to the same variable in Delphi, which is not case sensitive.

    Alternatively, an instance of the structure can be declared at any place in code prior to

    using the structure, just as any other variable is declared in C. Unlike in Delphi, the variable

    type precedes the name of the instance of the variable.

    MyData DataList;

    This declares a variable DataList which is the type MyData, which means that the program

    allocates memory for the structure defined above, creating an instance of this record.

    The fields of the record can then be accessed using the dot operator, as in Delphi, and using

    standard C functions.

    To copy a string into a field within the structure...

    strcpy(Datalist.phonenum, "383-4455");

    or to fill in other fields...

  • 7/30/2019 Translating C++ Code Into Delphi

    19/46

    Datalist.age = 51;

    Datalist.married = true;

    And so on...

    Instances tructures can be declared as arrays of records, for example as part of a database

    application. Here we will declare an array of 20 records...

    MyData Datalist[20];

    Each individual record can then be accessed using array syntax combined with the dot

    operator used to access record fields...

    Datalist[0].age = 51;

    And so on...

    Structures can also be filled in using the following syntax. Let's assume that the a record

    exists with a string field, and a couple of integer fields, and the structure name is Datalist.

    Datalist = { "Some Name", 12, 102};

    Arrays can also be filled in the same way. The following C++ example creates an array of

    3 strings.

    string sarray[3];

    sarray[0] = 'Hello';

    sarray[1] = 'there';sarray[2] = 'world';

    This could also be accomplished using the following code...

    string sarray = {'Hello', 'there', 'world'};

    Initializer lists (like the above) can be used when the array is declared and in this case the

    dimension of the array can be omitted (the compiler can make the determination based on the

    initializer list).

    Arrays can also be dynamically created, and the dimension can be passed as an integervariable, making the declaration truly dynamic. Here we assume that x is an integer variable

    that has been previously initialized to the required number of strings in the array. Notice that

    declaration is different in that the use of the pointer symbol (the asterik) indicates that this is

    going to be a dynamic array...

    string* sarray = new string[x];

    sarray[1] = 'Hello';

    sarray[2] = 'there';

    sarray[3] = 'world';

  • 7/30/2019 Translating C++ Code Into Delphi

    20/46

    Here the programmer is going to have to code to make sure that bounds of the array are not

    violated, since the compiler will not know if '3' is out of range since the array was declared

    dynamically using a variable (x in the example above).

    In C++ the name of an array is actually a pointer to the first element in an array. When

    arrays are passed to functions as parameters you might see either of the two following ways of

    describing the array...

    int somefunction(int anarray[], int size);

    int somefunction(int* anarray, int size);

    Both the above declarations describe an array parameter passed to a function, with the

    pointer pointing to the first element in the array.

    Within the body of the function the elements of the array are then accessed using the usual

    syntax...

    anarray[2] = 12;

    Multidimensional arrays are declared as follows...

    int anarray[4][6][7]; ... a 3-d array...

    Initializer lists can be used when the array is declared...

    int anarray[2][2] = { {2, 4}, {5, 6} };

    C++, like Delphi, allows types to be declared and then the type to be used to declareinstances of variables. In the example above the delphi 'type' keyword was used to declare

    records consisting of variables. This record type was then used to create an actual instance of

    the record type.

    In C++ the keyword used is 'typedef' (the definition of a type which can then be used to

    create instances of variables...) In both Delphi and C++ arrays can also be declared as types

    and then the type used to create actual arrays (typically this is done in the case of

    multidimensional arrays). The type definition is included at the top of the unit...

    #include

    ...etc etc ...const int X = 12;

    const int Y = 14;

    typedef int TwoDArray[X][Y];

    ..etc etc ...

    int somefunction(TwoDArray, int, double);

    In the body of the code the type (TwoDArray) is then used to create instances of the

    variable in the usual way...

    TwoDArray anarray;

  • 7/30/2019 Translating C++ Code Into Delphi

    21/46

    An initializer list can also be used to put values into the array as it is delcared as illustrated

    above, although it is also typical to use loops (for loops in particular) to initialize or otherwise

    manipulate arrays...

    The fields of a multidimensional array are accessed as follows...

    anarray[2][8] = 32;

  • 7/30/2019 Translating C++ Code Into Delphi

    22/46

    Pointers in C++, the stack and the heapTranslating C++ Code into Delphi Pascal

    When variables are created in a C++ program (when the variables are in scope) the memory

    required to hold the variable is allocated from the program stack, and when the variable goes

    out of scope, the memory which was taken on the stack is freed. When memory is allocated

    dynamically (by the programmer) memory is taken from the heap (which consists of all of the

    computers virutal memory, which includes onboard RAM and space available on the diskdrive. as in Delphi, with C++ memory is allocated dynamically using the new operator.

    As an example of static (stack) variables, and dynamic variables (on the heap) consider a

    simple integer x. The static variable would be declared in Delphi and C++ as follows...

    Delphi...

    var x : integer;

    In C++ variables do no need to be declared in the 'var' segment at the beginning of a

    function (or unit) but can be declared anywhere in code. (If a variable is declared within a for

    loop, then the variable would only be in scope (on the stack) while the for loop executed, and

    then would vanish and go out of scope (off the stack) when the for loop exits. This idea of the

    scope of a variable being limited to the section of code where it was declared is an important

    difference between C++ and Delphi...

    The same integer declared somewhere in C++...

    int x;

    Let's assume that the address of x was 1000. X is an integer, which currently means it is a

    32 bit value so memory is allocated on the stack for four bytes1000, 1001, 1002, and 1003.

    The address of x would be 1000 (so when we use the variable x we are actually referring to

    the address 1000). When we assign a value to x we are assigning this value to the four bytes

    beginning at the address to which x acts as a pointer (the variable name).

    We can also create variables dynamically in which case they do not go onto the stack but

    rather onto the heap. Because the program stack is limited, and the heap consists of all virtual

    memory (RAM and disk space) pointers and heap variables are useful in particular for large

    records (structures in C++) but can also be used for smaller variables.

    To begin with I will create a simple variable on the heap, dynamically, using pointers...The

    variable ' px ' will be a pointer to an integer...

    In Delphi....

    var px : ^integer;

    begin

    new(px); {allocates 4 bytes for the integer);

    ....use variable etc.....

    dispose(px); {frees the 4 bytes);

    px := nil; {the pointer was 'dangling' - set it to the null value}

  • 7/30/2019 Translating C++ Code Into Delphi

    23/46

    To access the value pointed to by ' px ' we deference the pointer. Assume that x is also an

    integer and we wish to assign it the value pointed to by ' px ' (or vice versa).

    x := px^;

    px^ := x;

    In this simple example the address of x is 1000, the address of 'px' (the pointer) could be

    2000. The value stored in px is 1000 which is the address of x since px points to x. We could

    also assign the pointer the address of an integer using the 'address of' operator...Assume that

    we have an integer variable y...

    px := @y;

    The pointer px is now pointing to the address of y. If we dereference px we get the integer

    value stored in y. If we check the value of px itself (we do not dereference the pointer) we get

    the address of y in this case ...and not the integer value stored in y.

    In C++ the same sort of things would be accomplished as follows...

    int* px = &x; ...the pointer px points to x using the address of x operator...

    y = *px; ...the pointer is deferenced and now y = the integer value stored in x....

    int w = *px; ...w now is set equal to the integer value stored in x...

    The dereference operator (' * ') and the address of operator (' & ') perform two functions,

    depending on the context in which they are used.

    int* px;

    Px is a derived type. It is a pointer to an integer, so its type 'pointer to an integer' is derived

    from the type integer. It is also a dangling pointer (it points to nothing at the moment). We

    could set it to null in two ways...

    px = 0; ...a null pointer...

    int* px = 0; ...set to null when it was declared...

    In a different context the symbol becomes the dereference operator...

    y = *px; ...assume px points to x, this dereferences the pointer so that y now is equal to x...

    The ' * ' operator can also mean 'multiply' depending on the context.

    y = x * 2;

    Thus these operators can have multiple meanings in a C++ program dependant on context

    and this is something to keep in mind...

    Pointers are frequently used for large data structures. For example let's assume that a

    structure (record) exists which has been defined with the label 'arecord'. To dynamicallycreate an instance of a variable of this type the new statement is used in the following way...

  • 7/30/2019 Translating C++ Code Into Delphi

    24/46

    First we will declare a pointer to a record (which will then be used to dynamically allocate

    memory from the heap for the record.) The pointer will be given the label MyRecord and the

    asterik indicates that we are defining a pointer to a structure of the type 'arecord'

    arecord* MyRecord;

    MyRecord = new arecord;

    You will notice that the variable declaration in C++ is 'backwards' compared to what you

    are used to in Delphi. An equivalent definition in Delphi which mimics the above could be

    implemented as follows...

    type

    arecordPtr = ^arecord; {a variable arecordPtr which is a pointer to arecord}

    arecord = record {define the structure of the record}

    {some records fields are here}

    aqe : integer;cost : float; {etc etc}

    end;

    {....}

    var

    MyRecord : arecordPtr; {MyRecord is a variable of the type which points to arecord}

    {...}

    begin

    New(MyRecord);

    {create an actual instance of arecord structure - this 'new' function does not create the

    pointer, but rather the record}

    Later we can free the memory occupied by the record using the Dispose statement (which

    disposes of the record, not the pointer) followed by setting the now invalid pointer to nil...

    Dispose(MyRecord);

    MyRecord := nil;

    Using the new statement in either Delphi or C++ dynamically allocates memory from the

    heap (leaving room on the stack for local variables) and the function returns a pointer to the

    memory which has been allocated. Note that pointers themselves are allocated from the stack,

    just like local variables (a 32 bit pointer would use 4 bytes from the stack, and then the

    memory required for the record would be allocated from the heap).

    Let's assume that the type 'arecord' has two integer fields, one named 'amount' and another

    'paid'

    To access the record fields using a pointer in Delphi one uses the following syntax...

    MyRecord^.amount := 10;

    MyRecord^.paid := 5;

    In C++ the syntax for accessing the field of a structure pointed to by a pointer is as

    follows...

  • 7/30/2019 Translating C++ Code Into Delphi

    25/46

    MyRecord->amount = 10;

    MyRecord->paid = 5;

    This can be compared to accessing the same fields from a record declared as a static

    variable using the dot operator (which would take up memory on the stack, rather than the

    heap).

    arecord MyRecord;

    MyRecord.amount = 10;

    In Delphi the dot operator works exactly the same...Here once again the record is a static

    variable stored on the stack, thus not requiring a pointer...

    var MyRecord : arecord;

    begin

    MyRecord.amount := 10;

    As an alterrnative to a linked list the records could be stored as an array of pointers (ratherthan as an array of the records themselves...

    In Delphi we could declare the array as follows...

    MyRecord : array[0..10} of arecordPtr;

    The records themselves would have to be created using the new operator (since all we have

    created so far is an array of pointers).

    new(MyRecord[0]);

    The elements in each record could then accessed using a combination of array and pointer

    syntax as follows ...

    MyRecord[5]^.amount := 10;

    In C++ this would appear as follows...

    arecord* MyRecord[10];

    Once again each record pointed to by one of these array pointers would have to be

    individually created by using the new function.

    MyRecord[4] = new arecord;

    And the individual fields in a given record would once again be accessed in C++ using a

    combination of the array and pointer deferencing syntax...

    MyRecord[5] -> amount = 10;

    Keep in mind here that C++ is case sensitive. In Delphi MyRecord and Myrecord or

    myrecord are all the same variable (Delphi is not case sensitive) while in all three cases in C+

    + these would be different variables. As well in C++ pointers are not initialized to 'nil' butpoint at random places causing all those familiar pointer errors when running computer

  • 7/30/2019 Translating C++ Code Into Delphi

    26/46

    programs (the most common being 'This program has performed an illegal operation and will

    be shut down'). Pointers can be set to 'nil' in Delphi, or set to '0' in C++ to help avoid these

    problems (program code would have to ensure that the pointer is never used if it has the null

    value). In the following C++ example MyRecord is to declared to be a pointer to the structure

    of type 'arecord' and then is set to '0'...

    arecord* MyRecord = 0;

    The record pointer could also be declared to be pointing at a record...

    arecord* MyRecord = new arecord;

    A few other bits and pieces of pointer syntax in C++ as compared to Delphi...

    Let's suppose that a pointer is pointing to an integer variable, and we wish to assign the

    value of this integer to another integer. In the example below we have an integer called

    'amount' pointed to by a pointer 'amountPtr' and we wish to assign this integer value to

    another variable labelled 'storeAmount'.

    First we will declare a pointer to an integer and then assign as the value of the pointer the

    address of the integer variable amount (note that this is the address of the variable amount,

    and not the value contained by the variable, two different things...a pointer requires the

    address of the variable which is being pointed to...)

    int* amountPtr = &amount;

    In Delphi

    var amountPtr : ^integer;begin

    amountPtr := @amount;

    To assign the value of amount to StoreAmount ...

    StoreAmount := amount; ... or in C++ ... StoreAmount = amount;

    Dereferencing a pointer to do the same thing...

    In Delphi..

    StoreAmount := amountPtr^; {which means assign the value pointed to by amountPtr}

    In C++...

    StoreAmount = *amountPtr;

    In both cases, because amountPtr points to amount, StoreAmount is assigned the value of

    amount...

    You might notice the reference operator in a C++ program as well. A reference is simply

    an alias for an already existing variable. References must be initialized when they are

  • 7/30/2019 Translating C++ Code Into Delphi

    27/46

    declared and are treated like constants (you cannot assign a value to the reference after it has

    been declared...)

    A reference can become an alias for any other variable. For example, rx will become the

    alias for x in this C++ example...

    int x = 12;

    int& rx = x;

    Add 4 to the reference variable rx and x also gets becomes 16. From this point on 'rx' and

    'x' refer to the same variable (rx is a reference to x).

    Let's assume that a function is declared which uses the 'var' keyword in Delphi.

    function TForm1.somefunction(var x : integer):integer;

    Now the use of the keyword 'var' tells the compiler to pass the integer to the function 'by

    reference'. In otherwords if the function changes the value of 'x' it will also be changing theoriginal integer that was passed to the function. If the 'var' keyword is not used then the

    parameter is passed by value (no reference, or alias is created for the original variable). Any

    changes to the integer we named 'x' will not alter the original variable that was passed to the

    function.

    In order to achieve the same effect in C++, we pass variables to a function by reference, so

    the function just declared above would like the following...

    int somefunction(int&); ...the function declaration at the top of the unit...

    int somefunction(int& x) ...the function header in the body of the unit...

    { ...the code }

    Because x is declared to be 'passed by reference' (note the & operator) this has the same

    effect as using the var keyword in Delphi. An alias is created for whatever integer you pass

    the function. Any changes made to 'x' in the function will not be local but will also be

    changed in the original variable you passed the function. For example let's assume that a

    function takes an integer which we will call 'huey' and a calling routine passes the integer

    'dewey' to the function. While the function is in scope, huey is now a reference to dewey, and

    changes to huey are changes to dewey. If however the function was declared without the var

    keyword (Delphi) and without the reference operator (in C++) then dewey will be passed byvalue. Only the value contained by the variable dewey will be passed to function but a

    reference to the address of the original variable (dewey) will not be passed. Changes to huey

    will not affect dewey since all huey recieved was the value contained by dewey and not a

    reference to dewey. This is the difference between passing by reference and passing by value,

    and it also illustrates one of the more common uses of the reference operator in C++..

    Another thing to keep in mind is that when a variable in either language is passed by value

    this creates a copy of the variable for the reasons noted above, while if the variable is passed

    by reference no copy is made since the original variable will be used (and changed or altered).

    So then for really large structures a programmer could either create a global variable or the

    structure could be passed to functions by reference to avoid the overhead of having a functioncreate a copy of the large structure, as would happen if it was passed by value. In addition,

  • 7/30/2019 Translating C++ Code Into Delphi

    28/46

    any changes made to this copy would vanish when the function completed and the copied

    variable went out of scope, which is probably not what you wanted (the original structure

    would be the same after the function executed, which would mean nothing was really

    accomplished).

    If you wanted to be really safe, however, and do not want the function to alter a structure or

    large graphic you could pass the variable by reference but declare it to be a constant. This

    avoids the copying of a large structure, but also protects the original variable from unwanted

    alterations...

    int somefunction(const x&);

    The variable x in the above example is both a constant and passed by reference.

    In programming code it is probably more typical to see references used as an alias for a

    pointer, and the end result is that coding is simplified, and thus looks like slightly different in

    the program code. This syntax describes a pointer which is accessed, like an object or stack

    declared record, using the dot operator rather the pointer syntax { -> }. There may be otherdifferences internally, but externally this is about all the visible difference that exists between

    a 'reference' and a 'pointer'...A reference is a pointer declared with the ampersand rather than

    with the asterik, which points to another pointer to the structure. This sounds confusing but

    looks something like this....

    arecord& MyRefRecord = *new arecord;

    MyRefRecord is then declared as a reference to a pointer to arecord structure. The fields of

    this record are then accessed using the dot operator.

    MyRefRecord.amount = 10;

    This can be compared to accessing the field of MyRecord assuming it was a pointer to the

    record...

    MyRecord->amount = 10;

    A reference might be declared in slightly different ways in a computer program. For

    example let us assume that we already a variable MyRecord which was a pointer to a record,

    as just suggested above. We could access MyRecord fields using the -> operator or we could

    go a step further and create a reference to this pointer, the difference being that we will then

    access the fields of the record using the dot operator. To do this we do another step anddeclare a reference to the MyRecord pointer as follows...

    arecord& MyRefRecord = *MyRecord;

    Note that references must be assigned a value when they are declared (this is not true of

    pointers which can be assigned a value later, or have their value changed, and this seems to

    another functional difference between references and pointers...) MyRecord is a pointer and

    MyRefRecord is a reference which points to the pointer MyRecord, and then the fields of

    MyRefRecord will access this record using the dot operator as illustrated above. So then if

    the fields of a structure are accessed in a C++ program using the dot operator, it could be a

    simple record (a type of local variable stored on the program stack) or it could be a referenceto a pointer to a record stored in the computer's memory heap (in this case the program listing

  • 7/30/2019 Translating C++ Code Into Delphi

    29/46

    will indicate this fact by the presence of the apersand ( & ) in the variable declaration.) You

    might notice that the ampersand is also the 'address of' function used on variables, but because

    the context is different, in one case it creates a referenced pointer and in the other it returns

    the address of a variable (when it is after an equals sign).

    Referenced pointer...

    arecord& MyRefRecord = *MyRecord;

    Address of operator (we will assume that IntPtr is a pointer to an int, and amount is an int)..

    IntPtr = &amount;

    This places the address of the amount variable into the pointer IntPtr, as described above...

    As I mentioned above, memory is dynamically allocated in C++ using the new operator.

    When a programmer allocates memory it is the responsibility of the programmer to free this

    memory (to avoid those memory leaks). Note that C++ is more simplified in this respect thansimple C which uses malloc (assigns memory), calloc, realloc, and then free to manipulate

    program memory

    One of the advantages of using 'new' and 'delete' (or 'new' and 'dispose' in Delphi) is that

    program stack memory is limited, but the heap in comparison is very large. For example

    pushing a large array onto the stack might not be a good idea, as your program will crash or

    perform unpredictably if stack memory is exhausted, and in the case of very large arrays or

    strings using a pointer and thus allocating and deallocating heap memory is a better choice,

    and the only difference is in becoming comfortable with working with pointers (and thus the

    heap) rather than using static variable definitions (and thus the stack). The memory used by

    local variables (variables declared in the static manner) is automatically managed by theprogram, with variables being disposed of when they go out of scope. However memory

    management becomes the programmers responsibility when using pointers to the heap and the

    new and delete (or dispose) functions.

    For example, here the memory for the record is allocated, and then freed...

    arecord* MyRecord = new arecord;

    delete MyRecord;

    MyRecord = 0;

    If you need to delete a memory that was accessed using a referenced pointer the syntax

    looks like the following...The address operator ( & ) extracts the address of the pointer from

    the reference and then this pointer is used to delete the actual allocated memory...

    delete &MyRefRecord;

    In C++ it is also a very bad idea to delete an uninitialized pointer (that was never set to

    point to something) since this can cause problems in memory wherever the random pointer

    may be pointing to at delete time. It is also a bad idea to delete a pointer multiple times in

    different parts of the program. Setting the pointer to null allows for testing of these conditions

  • 7/30/2019 Translating C++ Code Into Delphi

    30/46

    For this reason a pointer in C++ should be set to point to something (trying to dispose of a

    pointer in Delphi that points to nothing generates an error).

    arecord* MyRecord = 0;

    delete MyRecord;

    In the above example the pointer is set to Null (MyRecord := nil; in Delphi). I have a habit

    of setting all pointers to the null value when memory is disposed of to avoid crashing

    programs (this requires testing for a null value before using a pointer and taking appropriate

    steps if for some reason a null pointer is being accessed, since accessing a null pointer is

    enough in itself to generate an 'illegal operation' and a program error).

    How it looks in Delphi...

    dispose(MyRecord);

    MyRecord := nil;

    Dynamic arrays can also be created and disposed of using new and delete (thus using heap

    rather than the stack).

    Using Delphi 5 (and perhaps 4) creating dynamic arrays has been simplified. First the

    array declaration indicates that the array is gong to be dynamically allocated.

    var

    SomeArray : array of integer;

    Later in program code the array will be dynamically allocated using the 'SetLength'

    function. For example, suppose we decided that we needed 100 elements in the array...

    SetLength(SomeArray, 100 * sizeof(integer));

    The situation is a little more complicated in earlier versions of Delphi...see the page on

    Dynamic arrays for more information on creating and disposing of dynamic arrays in Delphi...

    In C++ a dynamic array is created using a pointer and then disposed of using delete[] ...

    Note that the two square brackets are required when deleting the memory allocated to a

    dynamic array.

    char* SomeBuffer = new char[1000]'

    delete[] SomeBuffer;

  • 7/30/2019 Translating C++ Code Into Delphi

    31/46

    Passing variables by reference of value in C++Translating C++ Code into Delphi Pascal

    In Delphi it is possible to pass a local copy of a variable when calling a procedure or a

    function, and it is also possible to pass the actual variable itself.

    For example the following code passes a local copy of the integer variable 'amount' to a

    procedure...]

    procedure TForm1.PassAnInt;

    var amount : integer;

    begin

    amount := 10;

    ChangeInt(amount);

    showmessage(IntToStr(amount));

    end;

    procedure TForm1.ChangeInt(amount : integer);

    begin

    amount := 22;

    end;

    When showmessage executes 'amount' is shown to be equal to 10 (the variable 'amount' in

    the second procedure was working on a second copy of a variable also named 'amount' which

    was in scope only while the ChangeInt function was executing. Because amount was passed

    to the procedure by value the original value of amount remains unchanged. However there

    are other ways to pass variables which would actually change the orginal variable 'amount'.

    For example by using the 'var' key word in the procedure definition this indicates to the

    compiler that the variable is to be passed 'by reference' (rather than 'by value').

    procedure TForm1.ChangeInt(var amount : integer);

    In this case when the showmessage procedure executes 'amount' now causes the display of

    the value of 22. The actual variable was changed and no local copy was made, because a

    reference to the actual variable being passed was sent to the procedure as a pointer to its

    location in memory. Note that this would work no matter what name was given to the

    variable in the procedure or function declaration...

    procedure TForm1.ChangeInt(var anyname : integer);

    In this example the anyname would be set to 22, and once again 'amount' would be

    displayed as having the value 22, since the var statement in the header indicates that a pointer

    to the original variable is to be created, so that the procedure or function actually changes the

    original value. This is a feature often used in API functions as a way of returning more than

    one result from a function (while the function returns a result in the usual way, the inclusion

    of pointers in the header declaration results in multiple results being returned in these

    variables as well).

    It also makes sense then that another way to alter an original variable or a set of variables is

    to pass actual pointers to these variables to a function or procedure, and in this case, since the

    pointer is pointing to the actual memory locations of these variables any changes made to

  • 7/30/2019 Translating C++ Code Into Delphi

    32/46

    them in another function is going to change the original values. Passing a pointer to a

    variable is thus the same as using the 'var' keyword in the function header as illustrated above.

    procedure TForm1.PassAPointer;

    var

    amount : integer;

    intPtr : ^integer;

    begin

    amount := 10;

    intPtr^ := amount;

    ChangeInt(intPtr);

    showmessage(IntToStr(amount));

    end;

    procedure TForm1.ChangeInt(apointer : ^integer);

    begin

    apointer^ := 22;

    end;

    In the above example the procedure ChangeInt acts like a function by 'returning a value'

    (because it was passed a pointer to the variable amount it actually alters the value of amount

    when the object pointed to by the pointer is set equal to 22).

    Passing by reference (using either a pointer or the var declaration in the header) makes

    sense if you want to return multiple values from a procedure or function, or when the objects

    being passed are quite large, such as strings, graphics, or objects (a local copy of these large

    data structures need not be made which is quicker and also a more efficient use of memory).

    There is syntax in C++ that resembles the 'var' statement in Delphi and produces the sameresult (rather than creating a local copy of a variable being passed the original is used). The

    ampersand is used in the function or procedure declaration to indicate that the address of the

    variable is being passed rather the value contained by the variable - in otherwords a reference

    to the variable is being passed, the equivalent to passing a pointer, which, after all, just

    contains the address of the variable. In C++ this would look like this...

    void ChangeInt(int& amount)

    {

    amount = 22;

    }

    The keyword 'void' indicates that this routine returns no value (in otherwords it is a

    procedure, since functions return a value). The ampersand indicates that the variable 'amount'

    refers to a variable being passed by reference, so as in the Delphi example above, this variable

    will actually be set to the value 22.

    Records (or structures as they are called in C++) can also be passed by reference and in the

    API this method would be the typical case, since often structures are quite large.

    void DoChanges(arecord& MyRecord)

    {

  • 7/30/2019 Translating C++ Code Into Delphi

    33/46

    ...all the program code here will alter the fields in 'MyRecord', which was passed by

    reference and so refers to the actual address of the original record...

    }

  • 7/30/2019 Translating C++ Code Into Delphi

    34/46

    File I/O in C++Translating C++ Code into Delphi Pascal

    C++ handles basic file I/O using streaming classes, from which instances of a streaming

    variable are created. There is a similar feature in Delphi - TFileStream.

    For example we could declare a file streaming variable in Delphi as follows...

    var

    FileStream : TFileStream;

    begin

    FileStream.Create('c:\something.txt', fmOpenWrite or fmCreate);

    FileStream.write(buffer, count);

    FileStream.free;

    end;

    In C++ the same thing would be accomplished using the classes ofstream, ifstream, and

    fstream.

    Ofstream handles output, ifstream handles input and fstream handles input and output.

    FStream seems similar then to the file variable in Delphi.

    var

    AFile : file;

    amt : integer;

    begin

    Assignfile(AFile, 'c:\somefile.brg');

    Reset(Afile, 1);

    Blockwrite(Afile, buffer[1], 200, amt);....

    Blockread(Afile, buffer[300], 12, amt);

    ....

    end;

    In the above example the untyped file 'AFile' is opened using 'Reset' and is set to one,

    which means that the 'record size' for writes is one byte. The Blockwrite statement begins

    writing at 'Buffer[1]' , writes out 200 bytes, and then returns the number of bytes written in

    'amt'. Later, aftering 'seeking' a spot in the file more than likely, the same file variable is used

    to read into the buffer. Reset allows both read and write, similar to the fstream variable in C+

    +. TFileStream also allows either read or write or 'fmOpenReadWrite' which also mimicsfstream in C++.

    The following is an example of using the ifstream variable in C++ to write out a file.

    remember to include the line #include at the head of the source file...

    Let's assume that we have created a character buffer to store the input...

    char buffer[1024];

    We need to create an instance of the ifstream class...

  • 7/30/2019 Translating C++ Code Into Delphi

    35/46

    ifstream AFile("c:\somefile.txt");

    A line can be read in as follows ...

    Afile.getline(buffer, sizeof(buffer));

    The destructor for the class closes the file if it is still open or you can explicitly close the

    file yourself...

    Afile.close();

    The code above passes a PChar (pointer to a character array) to the constructor of the

    ifstream class. It is also possible to use the following line to open a file...

    ifstream.Afile;

    AFile.open("c:\somefile.txt");

    One thing to watch out for if you are a Delphi programmer is that C++ uses double quotesfor literal strings while Delphi uses single quotes.

    To write to a file you can create an instance of the ofstream class, and then use the '

  • 7/30/2019 Translating C++ Code Into Delphi

    36/46

    An example of reading a file in and then writing it out using a string variable in C++...

    #include

    int main()

    {

    ifstream readfile("c:\readfile.txt");

    ofstream writefile("c:\writefile.txt");

    string thetext;

    while (getline(readfile, thetext))

    {

    writefile

  • 7/30/2019 Translating C++ Code Into Delphi

    37/46

    Assignfile(afile, 'c:\something.txt');

    Rewrite(afile, 1); {set record size to one byte}

    Blockwrite(afile, buffer[0], 80, amt);

    In this example the record size (in the rewrite procedure) was set to one byte. If we set the

    record size to 80 then we could write Blockwrite(afile, buffer[0], 1, amt); and write out 80

    bytes this way as well.

    Let's assume that a record (or structure in C++) exists which has a name field followed by

    two integers, and we will refer to it as theRecord. The structure can be written to disk as

    follows...

    ofstream afile("c:\somefile.txt", ios::binary);

    afile.write((char*)&theRecord, sizeof(theRecord));

    The code (char*) is neccesary to 'cast' the record to a PChar which is required by the

    fstream write function. If you are familiar with using the Windows API in Delphi you know

    that Delphi strings must be cast to pointers to character arrays as well (Pchar(TheString) inDelphi code).

    The code &theRecord extracts the address of the record and so the bytes in the record

    starting from this address are cast to a PChar and then this PChar is passed to the write routine

    and written out to afile. This accomplishes basically the same thing as the Delphi code above

    and this could also be done using the TFileStream class in Delphi, passing the number of

    bytes in the record structure as the argument to the writebuffer method of the streaming class.

    (For some reason I am not clear on, the writebuffer method works while the write method

    does not, but this could have something to do with the way the internal addresses are used in

    these two methods). As well, note that if you are reading in a record from disk you must use

    the same code as above, casting the record structure to a PChar, since the read function of theifstream class also requires a character pointer as its operand.

    When a file is open for read or for read/write it is possible to do random access on the file

    using the seeking functions provided by both Delphi and C++. (Note that in Delphi you

    cannot seek using a textfile but rather you must use a typed or, as in the examples above, an

    untyped file variable). Assume that afile is an untyped file variable...

    var afile : file; fpos : longint;

    begin

    Assignfile(afile, 'C:\something.txt');

    Reset(afile, 1);fpos := sizeof(theRecord) * 122;

    Seek(afile, fpos);

    The Tfilestream class also has a seek method...

    var filestream : TFilestream; offset : longint; origin : word;

    begin

    filestream := TFilestream.create('c:\something.txt', fmopenread);

    filestream.seek(offset, origin);

    Typed and Untyped files can return their file postion using FilePos which returns alongint...

  • 7/30/2019 Translating C++ Code Into Delphi

    38/46

    lx := FilePos(afile);

    As does TfileStream...

    lx := filestream.position;

    In C++ the fstream class has a seek function and a file position function, for either the

    ifstream or the ofstream classes. Seekg() and tellg() seek or return the position for ifstream

    variables while seekp() and tellp() do the same for ofstream classes. The usage of the

    functions looks like the following...

    ifstream afile("c:\something.txt", ios::binary);

    int pos;

    afile.seekg(0, pos)

    pos = afile.tellg();

    By opening a file in append mode tellg() would return the size of the file in bytes. Byopening an ofstream variable in read/write mode parts of a file could be accessed and changed

    randomly.

  • 7/30/2019 Translating C++ Code Into Delphi

    39/46

    C++ header interface filesTranslating C++ Code into Delphi Pascal

    Just as a Delphi program can consist of individual units, a C++ project can consist of any

    number of individual source files. Delphi uses the keyword 'uses' to indicate which source

    files are to be referenced by any given unit (making the code in that unit visible to the calling

    unit) and a C source file uses the keyword ' #include ' to perform the same function. Each

    source file in a C++ program ends with the extension ' .cpp ' and the compiler creates fileswith the extension ' .obj ' from these source files. The task of the linker is then to take these

    object files and link them together into an executable file ending with the familiar extension

    ' .exe '.

    A C project also includes a header file (ending with the extension ' .h ' in the typical case

    (although apparently you might also see ' .hpp ' indicating a C++ header file in particular. The

    header file typically contains declarations of all the classes and all the structures ( or 'records')

    in the program. These declared structures can then be accessed by a C++ source file using

    the #include keyword (which you see at the top of C++ files). For example ' #include

    something.h ' would include all the structures and classes declared in this header file, and also

    any functional declarations provided in the header (note that the functional code itself is not

    included in a header file, rather the header points to such code which will be found in another

    file). The use of header files for classes and structures promotes code reusability and

    modularity, since by the use of the include statement the records can be easily incorporated

    into any new program which requires them. The information in the header file is required by

    the programmer to access classes (not to mention DLLs) and also by the compiler which

    needs to know how to incorporate these classes into the program. The header file forms the

    interface between programmers code and the classes or the DLL.

    A simple header example :

    #indef _ARECORD_H

    #define _ARECORD.H

    struct somerecord {

    char name[30];

    char phonenum[10];

    int age;

    };

    #endif

  • 7/30/2019 Translating C++ Code Into Delphi

    40/46

    Classes and inheritance in C++Translating C++ Code into Delphi Pascal

    A class is similar to a structure, with the difference that a class includes both private and

    protected data and functions which manipulate the data to perform a specific function. It is

    typical for these classes, like structures, to be defined in a header file, with the sources for the

    functions included in a file with the same name with the difference the extension would be

    'cpp' for the source and 'h' for the header file.

    Normally the function of a class allows access to the results of manipulation of the data

    while keeping the implementation private. For example a class might manipulate a set of

    temperature variables and return energy as measurement of calories. The implementation of

    the conversion and any variables these functions use would be private, and the result would be

    public. In this way the actual source code which is also encapsulated in the class can be

    changed while the public interface remains the same, and a caller need not be concerned with

    the implementation of the embedded functions (only that the results returned are correct). A

    large number of programmers could then contribute classes to a project and as long as the

    calling routines understand the input variables and the public output variables of the class the

    actual implementation does not need to concern any other programmer in the project (a

    similar principle applies to DLLs which have a public interface, but, because they consist of

    machine code, have a private implementation.)

    The public section of a class consists of the interface, the part of the class that will be

    visible to other programmers who actually use the class. This is kept separate from the

    private section of the class, which is invisible to the user and the sole responsibility of the

    programmer who designed the class. The protected section consists of that part of the class

    that can be 'inherited' by a descendant class.

    In C++ classes are declared with the class keyword...The following is an attempt at a verysimple example. (In this example I have decided to make the BIOS on the motherboard

    'protected' rather than private....)

    class AComputer {

    public :

    AComputer();

    bool OnSwitch;

    bool ResetButton;

    char Keyboard;

    bool Bootup(int partition);

    protectedvoid BIOS();

    private

    char Keypressed;

    int ScreenPos;

    char GetKey();

    void WriteToScreen;

    }

    Etc., etc... The user here, like most computer users, only need to understand how to turn

    the computer on, and type on a keyboard, and doesn't need to be concerned about the 'private'

    implementation of the inner workings of the machine (only that the machine does in factwork, and that when a key is pressed on the keyboard it does in fact show up on the screen.)

  • 7/30/2019 Translating C++ Code Into Delphi

    41/46

    C++ classes, like Delphi classes, have a constructor, which is called when an actual

    instance of the class is created. A default constructor will be called if none is specified, but if

    you want to initalize the class a custom constructor is required. In the example above the

    constructor is 'AComputer()' and has the same name as the class (there is no 'constructor'

    keyword). The constructor can use function overloading. Functions are overloaded when

    more than one function exists with exactly the same name, but the variable declarations are

    different. The compiler keeps track of which version of the overloaded function is being

    called by comparing the variables being passed in the code. If you take a look inside a DLL -

    or a C++ DLL interface, you will see 'mangled names', since no two functions can have the

    same name in C++. For example a function might look like the following in code...

    int Add(int x, int y);

    float Add(float x, float y);

    The compiler will mangle the names (usually a random looking mixture of garbage

    characters). You will see the mangled name in the interface section of the DLL code. CallingAdd with two integers calls the first function and calling with floats will result in a call to the

    second function. Constructors can be overloaded in the same way. A default constructor

    need take no parameters and overloaded versions of the constructor are distinguished by the

    parameters they accept, as illustrated above.

    Actual instances of a class are created in the same way that variables are created.

    int x;

    X is declared to be of integer type (notice that the syntax is backwards compared to

    Delphi).

    AComputer ThisComputer;

    The members of the class can be accessed using the dot operator. Let's assume that the

    class AComputer includes a public integer variable declared as 'y'. (If 'y' is not public then the

    following code would generate a compiler error.)

    int x = ThisComputer.y;

    ThisComputer is an instance of the class AComputer. In this the default constructor is used

    (either a default constructor, taking no parameters, supplied by the programmer, or the defaultconstructor provided by the compiler). If parameters are supplied then one of the overloaded

    constructors will be called.

    AComputer ThisComputer(16, 2, 9);

    Here we assume that a constructor exists which accepts these parameters. Constructors are

    never called directly, but rather are called automatically when an instance of a class is actually

    created in code.

    The destructor is called just before an instance of a class is destroyed (goes out of scope, if

    the class was declared like a varable and is thus on the program stack, or is destroyed usingdelete, if the class was created dynamically and thus is on the heap). Once again there is no

  • 7/30/2019 Translating C++ Code Into Delphi

    42/46

    keyword 'destructor' but rather the class name is used, preceded by tilde ( ~AComputer() ).

    Destructors cannot be overloaded. If a destructor is not provided the compiler will provide a

    default destructor. One common use for a destructor is to prevent memory leaks by releasing

    any memory that was used by the instance of the class, but depending on the class

    implementation, a destructor may be called on to do any other final operations (save data,

    etc.)

    The functions encapsulated in a class can access all the data and functions in a class

    whether it is public or private, so long as an instance of the class exists. Each instance of a

    class, however, exists seperately in memory (so the data values would be separate for each

    instance, unless declared using the 'static' keyword, which is a way of declaring global

    variables for the class - in this case all instances would share the static variables. However,

    because an instance of the class could be expected to exist within the high speed cache, and

    the global variables could be anywhere in memory, the possibility exists that using static

    global variables in multiple instances of a class could cause cache misses. I just mention this,

    since I have heard talk of how modern computers with a CPU memory cache choke a lot on

    global variables due to the high penalties caused by cache misses. There is also something to

    be concerned about when one instance of a class changes a global variable which then isaccessed by another instance of the same class - this problem is similar to that faced by multi-

    threaded programs which need to co-operate when sharing common data...)

    Typically the 'public' functions of a class are the outside user interface, and the actual

    implementation of the task performed by the class is hidden. These public functions could

    accept parameters and return results, either as the result of the function or as results included

    in the public variables declared for the class. It should be noted here, that these public results

    stored in variables are only 'in scope' and thus usable, so long as the class is in scope and

    actually exists. If the class is destroyed or goes out of scope, so do these public variables.

    A class is typically used in a program in three parts. There is the header file, the source filefor the functions of the class, and then there is the program code which actually uses the class.

    For example you might see the following for the AComputer class)...

    (acomputer.h - the header file)

    #ifndef acomputerH

    #define acomputerH

    constant strings may be defined in the header file for the class (whever the compilerencounters the string SIZE it will substitute '22' in the source code ... it is typical for constants

    to be in uppercase but this is not a strict requirement (just remember that, unlike Delphi, C++

    is case sensitive...)

    #define SIZE 22

    #define LENGTH 13

    The class definition would then follow in the header...

    class AComputer {

    public :...public variables and access functions ...

  • 7/30/2019 Translating C++ Code Into Delphi

    43/46

    protected

    .....

    private

    .... the internal variables and workings of the class hidden from public access...

    };

    #endif;

    In a seperate source file the actual definitions of the functions declared in the header file

    will be found with the same name as the header, but ending with 'cpp'...

    acomputer.cpp ...

    The include statements will be found at the head of the cpp file, and typically look

    something like this - note I am unclear as to why '

  • 7/30/2019 Translating C++ Code Into Delphi

    44/46

    Note that there is no semicolon after the include statement for the acomputer.h header file..

    Next there follows a list of the functions included in this particular source file (note that

    this is different from the source code for the class since the functions are declared in the

    header file which is then included in the source file..) Let's assume that our program has the

    typical 'main' file (which is not declared in the list of functions at the top of the file) and also

    two functions called 'thisone' and 'thatone' ... The list of function declarations is followed by

    the actual description of the code, starting below with the 'main' function...

    int thisone(int x);

    int thatone(int y);

    void main(int whatever)

    {

    main code starts here...blah blah

    }

    int thisone(int x)

    {code for this one..

    }

    etc., etc. ...

    In code we want to create an instance of the class. We could do this using pointers.

    AComputer* ThisComputer = new AComputer(constructor variables here);

    The members of the class can then be accessed using pointer coding...Let's suppose the

    class had a public function 'CPUTemp' which returned an integer...

    int currenttemp = ThisComputer->CPUTemp();

    Public variables can also be accessed using the same pointer syntax...

    Because this instance of the class was created dynamically (on the heap) when we delete it

    we are also calling the destructor for the class...

    delete ThisComputer;

    You might see code that inherits from a class and so I include a brief discussion of

    inheritance from classes here as well...

    Let's suppose that we want to 'inherit' code from the AComputer class to make a new class

    called 'MacComputer'. The base class would be 'AComputer' and the derived class would be

    'MacComputer'. We would indicate that inheritance is at work in the following way...

    class MacComputer : public AComputer {

    public

    MacComputer(maybe some variables here); ...note that this is the constructor...

    virtual char GetKey(some vars); ...note this is 'virtual' so we will 'override' the original

    Acomputer code by writing a new routine for MacComputer ...

    protectedetc...

  • 7/30/2019 Translating C++ Code Into Delphi

    45/46

    private

    virtual int something(variables); another routine is virtual and will be replaced for

    MacComputer

    The descendant class would then call the constructor of the base class in its constructor

    code.

    MacComputer::MacComputer(int x) :

    AComputer(int x)

    {

    constructor for MacComputer code is here

    }

    If the default constructors provided are used then this would not be neccesary.

    If we wanted to literally inherit anything from AComputer then the virtual keyword is not

    used and the original code is simply inherited from the base class. We can also add newroutines not included in the orignal class by declaring them without using the virtual keyword

    (which is not needed since in the case of a new function or variable it is not necessary to

    indicate that we overriding the code in the base class). Note that the virtual keyword must be

    included for those routines in the header file of the original base class 'AComputer' and the

    declaration and the variables must match in the base class and in the derived class (the header

    of the two functions must match) and then the function can be rewritten in the derived class.

    Because the derived class provides its own version of this 'virtual' function this indicates to

    the compiler that the derived (virtual) version of this function is to be called in all derived

    classes, and not the original function by that same name in the base class.

    The functionality of the original virtual can also be included in the new (virtual) functionfollowed by and/or preceded by additional code in the source file in the following way.

    char MacComputer::GetKey(some variables)

    {

    some extra mac code here...

    AComputer::GetKey(some variables); ...include the base code here...

    now add some more mac code...

    }

    Note that 'GetKey' must be in the protected section of the AComputer code and not the

    private section. What is in the protected section can be accessed by descendants that haveinherited from a class but what is in the private section even descendants cannot access, so

    this would not work, and indicates one of the key differences when designing a class between

    putting something into the private section or the protected section of the class. The

    descendants of this class would then access the 'private code' in the same way as any other

    outsider (through the interface provided by the base class). So 'private' functions and data in

    a class are 'hidden' as are protected functions and data, but those that are protected are

    available for inheritance.

    Note that it is not required to call elements in the base class using the 'scope operator' if the

    elements have not been over ridden. For example we must call AComputer::GetKey(blah)

    because GetKey has been over ridden. Let's suppose that we inherit (without overriding)something called GetMouse(blah). We could simply use GetMouse (rather than

  • 7/30/2019 Translating C++ Code Into Delphi

    46/46

    AComputer::GetMouse(blah) ) because there is no need to indicate the scope in this case,

    since there is only one 'GetMouse' to consider. If the scope operator is not used, and a

    function has been over ridden, then to avoid ambiguity the compiler uses the descendant

    function, since it is considered to be more 'in scope' than the 'further away' ancestor or base

    class.

    If we wanted to use 'MacComputer' as the base class for, say, 'Mac64Computer' then it

    would turn out to be the case that Mac64Computer would ultimately be a descendant of

    AComputer as well. Thus inheritance can be thought of as being like a tree, with a root base

    class, and many branches coming off of this root in a tree like structure.

    It is also possible for descendant classes to use multiple inheritance. For example let's

    suppose that a new computer wa