You are on page 1of 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 much of 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

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.

Understanding C++ Operators


Translating 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 may not 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 that the former generates more optimized code.

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.

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.

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)

* (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).

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 variable declared 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<30;x++) { code of loop } y = x; In this example there are two variables named x. The second variable, declared in the header of the for loop is in scope only so long as the for loop is executing. When the for loop is executing a reference to x refers to the x declared within the for loop since it is currently in scope. When the for loop exits and we set y equal to x, y gets the value 10 because the variable x declared outside the for loop is now the variable in scope. Code like this will not generate a compiler error since each variable named x has its own scope (an error will be generated however if two variables named x with the same scope are declared). One could

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<30;x++) { code of loop } y = x; This generates a compiler error since x is only in scope within the loop where it was declared, and no longer exists outside the loop. The previous example just above however would be legal, and y would become 10 since this x has the same scope as y (it is visible to y). Global variables in C which are visible everywhere must be declared, similar to Delphi, outside the main body of the program. This would look something like this... #include <conio.h> #pragma hdrstop int x = 1; program functions etc follow here This variable x is global in scope, however if another variable named x is declared in a function or loop or other block of code then it has higher priority than the global variable and any reference to x would then refer to this local variable. The global variable x would only come into scope once again after the local variable x went out of scope. Global variables are only global to the unit (source file) in which they are declared, however using the extern statement any global variable in any source file can become truly global and visible to other program modules. For example if we declared a global variable 'x' as in the example above, and then in another file we include the statement extern int x; the compiler recognizes that this unit will be using the global variable 'x' which is declared in one of the units 'included' at the head of the file. (Note that the ' #include ' statement in C performs the same functions as the ' uses ' statement in Delphi).

If - 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...

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 these conditions 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 which looks 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;

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 provide valid '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.

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 complicated if - then - else construct.

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;x<20;x++) { DoSomething; DoNextThing; } In the above example an integer variable x is declared within the loop definition and is set to the initial value of 1. This is different from Delphi where the variable x would have to be declared using the var statement before the beginning of the code segment. The statement 'x+ +' indicates that x will be incremented by 1 each time through the loop, and as long as x is less than 20 the loop will continue (terminating when x reaches the value of 20). The loop could run backwards by substituting 'x--' in place of 'x++'... for (int x=20; x>0;x--) { the code is here; } In this case the loop begins at 20, and each iteration the value of x is reduced by one and the 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; }

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 so that 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 with the 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 program to skip whatever code follows in the loop and go on to the next iteration of the loop. The

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<10;x++) { dosomecode; if (x == 5) continue; dosomemorecode; } The following simple example assumes that the program is searching for a certain result, and once found the loop might as well be terminated. for (int x=100;x<z;x++) { if (x==y) break; dosomecodehere; }

Structures in C++ and records in Delphi


Translating 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 = record phonenum : 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

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 it in 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...

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 integer variable, 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';

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 declare instances 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 <whatever.h> ...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;

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;

Pointers in C++, the stack and the heap


Translating 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 disk drive. 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}

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 dynamically create an instance of a variable of this type the new statement is used in the following way...

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...

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 (rather than 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' but point at random places causing all those familiar pointer errors when running computer

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^; 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 {which means assign the value pointed to by amountPtr}

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 the original 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 by value. 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 function create a copy of the large structure, as would happen if it was passed by value. In addition,

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 other differences 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 and declare 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 reference to a pointer to a record stored in the computer's memory heap (in this case the program listing

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 than simple 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 the program, 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

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;

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

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 same result (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) {

...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... }

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 mimics fstream 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 <fstream.h> 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...

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 quotes for 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 ' << ' operator to send output to the file. ofstream.Afile("c:\somefile.txt"); AFile << "Write out this line please" << endl; AFile.close; The 'endl' means write end of line, or a return carriage. Like TfileStream the streaming classes in C++ have modes that can be used to describe how the file is to be manipulated. These modes are members of the 'ios' class and are specified as in the following example... ofstream.Afile("c:\somefile.txt", ios::binary); The default mode (if none is specified) is textfile mode. The other modes are : ios::app - append to end of file... ios::ate - seek end of file on opening... ios::in - open file for input, used with the fstream class...

ios::out - open for output... ios::trunc - erase and rewrite the file, which is the default... If more than one of these is used they are seperated by the bar character (which means 'or'), as follows (note that with TFileStream in Delphi these are seperated by the keyword 'or')... fstream.Afile("c:\somefile.txt", ios::app | ios::out | ios::binary);

An example of reading a file in and then writing it out using a string variable in C++... #include <fstream> int main() { ifstream readfile("c:\readfile.txt"); ofstream writefile("c:\writefile.txt"); string thetext; while (getline(readfile, thetext)) { writefile << thetext << endl; } readfile.close(); writefile close(); } This program does nothing but read the file in and write it out again, and if the file was to manipulated this would of course be included in the while loop code. Note that when only one line is included in a while loop (if/then construct, for loop etc) the curly braces are not strictly required and the line could be written as... while (getline(readfile, thetext)) writefile << thetext << endl; As well when the file stream variables go out of scope the file stream class automatically closes the file if it has not already been closed, so the two close statements might not be really required either, but I include them here because it seems like good form. In Delphi records can be rewritten to disk using the Blockwrite function of an instance of an untyped file variable whose default record size has been set to the size of the record in question. One of the tricky parts of writing out records is that internally everything is kept aligned along double word boundaries for the sake of modern CPUs (which run fastest when operating with 32 bits). So a record with a byte, a byte, and an integer which have the one byte bytes aligned along a 4 byte (double word) boundary to increase CPU performance, which means that when you try to write out the record to disk you can wind up writing out crap (and wondering what went wrong) if you fail to keep this in mind. For example we are assuming here that TheRecord exists and we want to write it to disk... var afile : file; amt : integer; begin Assignfile(afile, 'C;\somefile.txt'); Rewrite(afile, sizeof(TheRecord)); Blockwrite(afile, TheRecord, sizeof(TheRecord), amt); As I mentioned, 'sizeof(TheRecord)' might not turn out the way you would expect because of that business with the 4 byte boundaries in internal memory representation of the record. As well, just a tip, when you write out a buffer always refer to 'buffer[0]' in the Blockwrite statement (assuming zero is the beginning of the buffer, since writing from 'buffer' will write out a bunch of crap starting from whatever the address of the buffer pointer is, rather than starting from the address contained in the buffer pointer, which is what you want... var afile : file; amt : integer; buffer : array[0..79] of char; begin

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) in Delphi 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 the ifstream 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 a longint...

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. By opening an ofstream variable in read/write mode parts of a file could be accessed and changed randomly.

C++ header interface files


Translating 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 files with 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

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 very simple 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); protected void 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 fact work, and that when a key is pressed on the keyboard it does in fact show up on the screen.)

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. Calling Add 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 default constructor 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 using delete, if the class was created dynamically and thus is on the heap). Once again there is no

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 is accessed by another instance of the same class - this problem is similar to that faced by multithreaded 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 file for 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 compiler encounters 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 ...

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 '<' is used for the standard include files and double quotes are used for the class header, but this is what I have noticed so I reproduce it here... #include <stdio.h> etc. #include "acomputer.h" next the code follows with the constructor having the same name as the class and the destructor preceded only by tilde as mention above. Variables used by the class may also be set to certain values after the function header, seperated by a mandatory colon from the header and from each other by commas, except for the last, and then the function code itself follows... AComputer::Acomputer(int x, int y) : q(16), w(12), cat(122) { ...the code ... } void AComputer::Startme(int partition) { some code... } We will assume then that all the functions declared in the header have been coded and the source file is complete. Next a program will have to create an instance of this class in order for it to become useful... In the calling program there will an 'include' section at the beginning of the code, and then the class is included using the following syntax that typically appears something like the following... #include <something.h> ....etc #pragma hdrstop USEUNIT("acomputer.cpp"); #include "acomputer.h"

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 ... protected etc...

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 new routines 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) function followed 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 have inherited 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

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 was to be designed that was to inherit all the features of a Mac and an Apple. Let's call this new computer the Macle. class Macle : public MacComputer, public AppleComputer { public Macle(whatever vars); private etc.etc. By inheriting both the Mac and the Apple classes and overriding whatever virtual functions are required a new computer class is created (the Macle) which combines both the previous classes.

You might also like