Posts

Showing posts from April, 2009

Using local transactions

The BDE supports local transactions against local Paradox, dBASE, Access, and FoxPro tables. From a coding perspective, there is no difference to you between a local transaction and a transaction against a remote database server.
When a transaction is started against a local table, updates performed against the table are logged. Each log record contains the old record buffer for a record. When a transaction is active, records that are updated are locked until the transaction is committed or rolled back. On rollback, old record buffers are applied against updated records to restore them to their pre-update states.

Local transactions are more limited than transactions against SQL servers or ODBC drivers. In particular, the following limitations apply to local transactions:

Automatic crash recovery is not provided.

Data definition statements are not supported.

Transactions cannot be run against temporary tables.

For Paradox, local transactions can only be performed on tables with valid indexes…

Using passthrough SQL

With passthrough SQL, you use a TQuery, TStoredProc, or TUpdateSQL component to send an SQL transaction control statement directly to a remote database server. The BDE does not process the SQL statement. Using passthrough SQL enables you to take direct advantage of the transaction controls offered by your server, especially when those controls are non-standard.
To use passthrough SQL to control a transaction, you must

Install the proper SQL Links drivers. If you chose the “Typical” installation when installing C++Builder, all SQL Links drivers are already properly installed.
Configure your network protocol correctly. See your network administrator for more information.
Have access to a database on a remote server.
Set SQLPASSTHRU MODE to NOT SHARED using the SQL Explorer. SQLPASSTHRU MODE specifies whether the BDE and passthrough SQL statements can share the same database connections. In most cases, SQLPASSTHRU MODE is set to SHARED AUTOCOMMIT. However, you can’t share database connecti…

Using a database component for transactions

When you start a transaction, all subsequent statements that read from and write to the database occur in the context of that transaction. Each statement is considered part of a group. Changes must be successfully committed to the database, or every change made in the group must be undone.
Ideally, a transaction should only last as long as necessary. The longer a transaction is active, the more simultaneous users that access the database, and the more concurrent, simultaneous transactions that start and end during the lifetime of your transaction, the greater the likelihood that your transaction will conflict with another when you attempt to commit your changes.
When using a database component, you code a single transaction as follows:

1.Start the transaction by calling the database’s StartTransaction method.

2.Once the transaction is started, all subsequent database actions are considered part of the transaction until the transaction is explicitly terminated. You can determine whether a …

Explicitly controlling transactions

There are two mutually exclusive ways to control transactions explicitly in a BDE-based database application:
Use the methods and properties of the database component,
such as StartTransaction, Commit, Rollback, InTransaction, and TransIsolation. The main advantage to using the methods and properties of a database component to control transactions is that it provides a clean, portable application that is not dependent on a particular database or server.

Use passthrough SQLin a query component to pass SQL statements directly to remote SQL or ODBC servers. For more information about query components, see "Working with queries.” The main advantage to passthrough SQL is that you can use the advanced transaction management capabilities of a particular database server, such as schema caching. To understand the advantages of your server’s transaction management model, see your database server documentation.
One-tiered applications can‘t use passthrough SQL. You can use the database componen…

Initializing the thread

Image
Use the constructor to initialize your new thread class. This is where you can assign a default priority for your thread and indicate whether it should be freed automatically when it finishes executing.

Assigning a default priority

Priority indicates how much preference the thread gets when the operating system schedules CPU time among all the threads in your application. Use a high priority thread to handle time critical tasks, and a low priority thread to perform other tasks. To indicate the priority of your thread object, set the! Priority property. Priority values fall along a seven point scale, as described in the following table:

Value Priority
tpIdle The thread executes only when the system is idle. Windows won't interrupt other threads to execute a thread with tpIdle priority.
tpLowest The thread's priority is two points below normal.
tpLower The thread's priority is one point below normal.
tpNormal The thread has normal priority.
tpHigher The thread's priorit…

Distributing database applications

C++Builder provides support for creating distributed database applications using the MIDAS technology. This powerful technology includes a coordinated set of components that allow you to build a wide variety of multi-tiered database applications. Distributed database applications can be built on a variety of communications protocols, including DCOM, TCP/IP, and OLEnterprise.

Creating multi-tiered applications
A multi-tiered client/server application is partitioned into logical units which run in conjunction on separate machines. Multi-tiered applications share data and communicate with one another over a local-area network or even over the Internet. They provide many benefits, such as centralized business logic and thin client applications.
In its simplest form, sometimes called the “three-tiered model,” a multi-tiered application is partitioned into thirds:

Client application: provides a user interface on the user’s machine.
Application server: resides in a central networking location ac…

Understanding MIDAS technology

MIDAS provides the mechanism by which client applications and application servers communicate database information. Using MIDAS requires MIDAS.DLL, which is used by both client and server applications to manage datasets stored as data packets. Building MIDAS applications may also require the SQL explorer to help in database administration and to import server constraints into the Data Dictionary so that they can be checked at any level of the multi-tiered application.

Note:You must purchase server licenses for deploying your MIDAS applications.
MIDAS-based multi-tiered applications use the components on the MIDAS page of the component palette, plus a remote data module that is created by a wizard on the Multitier page of the New Items dialog.

remote data modules
Specialized data modules that work with a COM Automation server to give client applications access to any providers they contain. Used on the application server.

provider component
A data broker that provides data by creating data p…

Granting permission to access and launch the application server

Requests from the InternetExpress application appear to the application server as originating from a guest account with the name IUSR_computername, where computername is the name of the system running the Web application. By default, this account does not have access or launch permission for the application server. If you try to use the Web application without granting these permissions, when the Web browser tries to load the requested page it times out with EOLE_ACCESS_ERROR.
Note: Because the application server runs under this guest account, it can’t be shut down by other accounts.

To grant the Web application access and launch permissions, run DCOMCnfg.exe, which is located in the System32 directory of the machine that runs the application server. The following steps describe how to configure your application server:

1.When you run DCOMCnfg, select your application server in the list of applications on the Applications page.

2.Click the Properties button. When the dialog changes, sele…

Building an InternetExpress application

The following steps describe how to build a Web application that creates HTML pages for allowing users to interact with the data from an application server via a javascript-enabled Web browser.
1.Choose File|New to display the New Items dialog box, and on the New page select Web Server application.

2.From the MIDAS page of the component palette, add a connection component to the Web Module that appears when you create a new Web server application. The type of connection component you add depends on the communication protocol you want to use.

3.Set properties on your connection component to specify the application server with which it should establish a connection.

4.Instead of a client dataset, add an XML broker from the InternetExpress page of the component palette to the Web module. Like TClientDataSet, TXMLBroker represents the data from a provider on the application server and interacts with the application server through its IAppServer interface. However, unlike client datasets, XML…

Using the javascript libraries

The HTML pages generated by the InternetExpress components and the Web items they contain make use of several javascript libraries that ship with C++Builder:

xmldom.js
This library is a DOM-compatible XML parser written in javascript. It allows parsers that do not support XML to use XML data packets. Note that this does not include support for XML Islands, which are supported by IE5 and later.

xmldb.js
This library defines data access classes that manage XML data packets and XML delta packets.

xmldisp.js
This library defines classes that associate the data access classes in xmldb with HTML controls in the HTML page.

xmlerrdisp.js
This library defines classes that can be used when reconciling update errors. These classes are not used by any of the built-in InternetExpress components, but are useful when writing a Reconcile producer.

xmlshow.js
This library includes functions to display formatted XML data packets and XML delta packets. This library is not used by any of the InternetExpress compo…

Creating the client application

In most regards, creating a multi-tiered client application is similar to creating a traditional two-tiered client. The major differences are that a multi-tiered client uses

A connection component to establish a conduit to the application server.
One or more TClientDataSet components to link to a data provider on the application server. Data-aware controls on the client are connected through data source components to these client datasets instead of TTable, TQuery, TStoredProc or TADODataSet components.

To create a multi-tiered client application, start a new project and follow these steps:
1.Add a new data module to the project.

2.Place a connection component on the data module. The type of connection component you add depends on the communication protocol you want to use.

3.Set properties on your connection component to specify the application server with which it should establish a connection. To learn more about setting up the connection component.

4.Set the other connection component pr…

Creating an Active Form for the client application

1.Because the client application will be deployed as an ActiveX control, you must have a Web server that runs on the same system as the client application. You can use a ready-made server such as Microsoft’s Personal Web server or you can write your own using the socket components described in "Working with sockets.”

2.Create the client application following the steps described in "Creating the client application.” except start by choosing File|New|Active Form, rather than beginning the client project as an ordinary C++Builder project.

3.If your client application uses a data module, add a call to explicitly create the data module in the active form initialization.

4.When your client application is finished, compile the project, and select Project | Web Deployment Options. In the Web Deployment Options dialog, you must do the following:

-On the Project page, specify the Target directory, the URL for the target directory, and the HTML directory. Typically, the Target directory an…

Creating the application server

You create an application server very much as you create most database applications. The major difference is that the application server includes a dataset provider.
To create an application server, start a new project, save it, and follow these steps:

1.Add a new remote data module to the project. From the main menu, choose File|New. Choose the Multitier page in the new items dialog, and select

Remote Data Module if you are creating a COM Automation server that clients access using DCOM, HTTP, or sockets.
Transactional Data Module if you are creating a remote data module that runs under MTS or COM+. Connections can be formed using DCOM, HTTP, or sockets. However, only DCOM supports the security services.

NB:When you add a remote data module to your project, the Wizard also creates a special COM Automation object that contains a reference to the remote data module and uses it to look for providers. This object is called the implementation object.

2.Place the appropriate dataset components …

Distributing a client application as an ActiveX control

The MIDAS architecture can be combined with C++Builder’s ActiveX features to distribute a MIDAS client application as an ActiveX control.
When you distribute your client application as an ActiveX control,create the application server as you would for any other multi-tiered application.
When creating the client application, you must use an Active Form as the basis instead of an ordinary form.

Once you have built and deployed your client application, it can be accessed from any ActiveX-enabled Web browser on another machine. For a Web browser to successfully launch your client application, the Web server must be running on the machine that has the client application.
If the client application uses DCOM to communicate between the client application and the application server, the machine with the Web browser must be enabled to work with DCOM. If the machine with the Web browser is a Windows 95 machine, it must have installed DCOM95, which is available from Microsoft

Building Web applications using InternetExpress

MIDAS clients can request that the application server provide data packets that are coded in XML instead of OleVariants. By combining XML-coded data packets, specialjavascript libraries of database functions, and C++Builder’s Web server application support, you can create thin client applications that can be accessed using a Web browser that supports javascript. These applications make up C++Builder’s InternetExpress support.

Before building an InternetExpress application,, you should understand C++Builder’s Web server application architecture and the MIDAS database architecture.Understanding MIDAS technology.

On the InternetExpress page of the component palette, you can find a set of components that extend this Web server application architecture to act as a MIDAS client. Using these components, the Web application generates HTML pages that contain a mixture of HTML, XML, and javascript. The HTML governs the layout and appearance of the pages seen by end users in their browsers. The …

Distributing a client application as an ActiveX control

The MIDAS architecture can be combined with C++Builder’s ActiveX features to distribute a MIDAS client application as an ActiveX control.
When you distribute your client application as an ActiveX control, create the application server as you would for any other multi-tiered application.

When creating the client application, you must use an Active Form as the basis instead of an ordinary form.
Once you have built and deployed your client application, it can be accessed from any ActiveX-enabled Web browser on another machine. For a Web browser to successfully launch your client application, the Web server must be running on the machine that has the client application.
If the client application uses DCOM to communicate between the client application and the application server, the machine with the Web browser must be enabled to work with DCOM. If the machine with the Web browser is a Windows 95 machine, it must have installed DCOM95, which is available from Microsoft.

Writing MIDAS Web applications

If you want to create Web-based clients for your multi-tiered database application, you must replace the client tier with a special Web applications that acts simultaneously as a client to the application server and as a Web server application that is installed with a Web server on the same machine.
There are two approaches that you can take to build the MIDAS Web application:

You can combine the MIDAS architecture with C++Builder’s ActiveX support to distribute a MIDAS client application as an ActiveX control.
This allows any browser that supports ActiveX to run your client application as an in-process server.
You can use XML data packets to build an InternetExpress application. This allows browsers that supports javascript to interact with your client application through html pages.

These two approaches are very different. Which one you choose depends on the following considerations:

Each approach relies on a different technology (ActiveX vs. javascript and XML). Consider what systems …

Requesting data from an application server

The following table lists the properties and methods of TClientDataSet that determine how data is fetched from an application server in a multi-tiered application:
FetchOnDemand property
Determines whether or not a client dataset automatically fetches data as needed, or relies on the application to call the client dataset’s GetNextPacket, FetchBlobs, and FetchDetails functions to retrieve additional data.

PacketRecords property
Specifies the type or number of records to return in each data packet.

GetNextPacket method
Fetches the next data packet from the application server.

FetchBlobs method
Fetches any BLOB fields for the current record when the application server does not include BLOB data automatically.

FetchDetails method
Fetches nested detail datasets for the current record when the application server does not include these in data packets automatically.
By default, a client dataset retrieves all records from the application server. You can control how data is retrieved using PacketRecor…

Supporting state information in remote data modules

The IAppServer interface, which controls all communication between client datasets and providers on the application server, is mostly stateless. When an application is stateless, it does not “remember” anything that happened in previous calls by the client. This stateless quality is useful if you are pooling database connections in a transactional data module, because your application server does not need to distinguish between database connections for persistent information such as record currency. Similarly, this stateless quality is important when you are sharing remote data module instances between many clients, as occurs with just-in-time activation or object pooling.

However, there are times when you want to maintain state information between calls to the application server. For example, when requesting data using incremental fetching,the provider on the application server must “remember” information from previous calls (the current record).
This is not a problem if the remote da…

Applying updates for master/detail tables

When you apply updates for master/detail tables, the order in which you list datasets to update is significant. Generally you should always update master tables before detail tables, except when handling deleted records. In complex master/detail relationships where the detail table for one relationship is the master table for another detail table, the same rule applies.
You can update master/detail tables at the database or dataset component levels. For purposes of control (and of creating explicitly self-documented code), you should apply updates at the dataset level. The following example illustrates how you should code cached updates to two tables, Master and Detail, involved in a master/detail relationship:

Database1->StartTransaction();

try
{
Master->ApplyUpdates();
Detail->ApplyUpdates();
Database1->Commit();
}
catch(...)
{
Database1->Rollback();
throw;
}
Master->CommitUpdates();
Detail->CommitUpdates();

If an error occurs during the application of updates, this c…

Limiting records with parameters

When the provider on the application server represents the results of a table component, you can use Params property to limit the records that are provided to the Data property.
Each parameter name must match the name of a field in the TTable component on the application server. The provider component on the application server sends only those records whose values on the corresponding fields match the values assigned to the parameters.

For example, consider a client application that displays the orders for a single customer. When the user identifies the customer, the client dataset sets its Params property to include a single parameter named CustID (or whatever field in the server table is called) whose value identifies the customer whose orders it will display. When the client dataset requests data from the application server, it passes this parameter value. The application server then sends only the records for the identified customer. This is more efficient than letting the applicati…

Master/detail relationships: Two Drawbacks

1.The detail table must fetch and store all of its records from the application server even though it only uses one detail set at a time. This problem can be mitigated by using parameters.Limiting records with parameters
2.It is very difficult to apply updates, because client datasets apply updates at the dataset level and master/detail updates span multiple datasets. Even in a two-tiered environment, where you can use the database to apply updates for multiple tables in a single transaction, applying updates in master/detail forms is tricky.Applying updates for master/detail tables

In multi-tiered applications, you can avoid these problems by using nested tables to represent the master/detail relationship. To do this, set up a master/detail relationship between the tables on the application server. Then set the DataSet property of your provider component to the master table.
When clients call the GetRecords method of the provider, it automatically includes the detail datasets as a DataS…

Building an example master/detail form

The following steps create a simple form in which a user can scroll through customer records and display all orders for the current customer. The master table is the CustomersTable table, and the detail table is OrdersTable.

1 Place two TTable and two TDataSource components in a data module.
2 Set the properties of the first TTable component as follows:

DatabaseName: BCDEMOS
TableName: CUSTOMER
Name: CustomersTable

3 Set the properties of the second TTable component as follows:

DatabaseName: BCDEMOS
TableName: ORDERS
Name: OrdersTable

4 Set the properties of the first TDataSource component as follows:

Name: CustSource
DataSet: CustomersTable

5 Set the properties of the second TDataSource component as follows:

Name: OrdersSource
DataSet: OrdersTable

6 Place two TDBGrid components on a form.
7 Choose File|Include Unit Hdr to specify that the form should use the data module.
8 Set the DataSource property of the first grid component to
“CustSource”, and set the DataSource property of the second grid…

Supporting master/detail relationships

You can create master/detail relationships between client datasets in your client application in the same way you set up master/detail forms in one- and two-tiered applications.
Creating master/detail forms
A table component’s MasterSource and MasterFields properties can be used to establish one-to-many relationships between two tables.
The MasterSource property is used to specify a data source from which the table will get data for the master table. For instance, if you link two tables in a master/detail relationship, then the detail table can track the events occurring in the master table by specifying the master table’s data source component in this property.

The MasterFields property specifies the column(s) common to both tables used to establish the link. To link tables based on multiple column names, use a semicolon delimited list:

Table1->MasterFields = "OrderNo;ItemNo";

To help create meaningful links between two tables, you can use the Field Link designer.
example of a…

Managing transactions in multi-tiered applications

When client applications apply updates to the application server, the provider component automatically wraps the process of applying updates and resolving errors in a transaction. This transaction is committed if the number of problem records does not exceed the MaxErrors value specified as an argument to the ApplyUpdates method. Otherwise, it is rolled back.
In addition, you can add transaction support to your server application by adding a database component or using passthrough SQL. This works the same way that you would manage transactions in a two-tiered application.

If you have a transactional data module, you can broaden your transaction support by using MTS or COM+ transactions. These transactions can include any of the business logic on your application server, not just the database access. In addition, because they support two-phase commits, they can span multiple databases.
Only the BDE- and ADO-based data access components support two-phase commit. Do not use InterbaseExpress…

Transactions

A transaction is a group of actions that must all be carried out successfully on one or more tables in a database before they are committed (made permanent). If any of the actions in the group fails, then all actions are rolled back (undone).
Transactions protect against hardware failures that occur in the middle of a database command or set of commands. They also form the basis of multi-user concurrency control on SQL servers. When each user interacts with the database only through transactions, one user’s commands can’t disrupt the unity of another user’s transaction. Instead, the SQL server schedules incoming transactions, which either succeed as a whole or fail as a whole.

Although transaction support is not part of most local databases, the BDE drivers provide limited transaction support for some of these databases. For SQL servers and ODBC-compliant databases, the database transaction support is provided by the component that represents the database connection. In multi-tiered app…

Database security

Databases often contain sensitive information. Different databases provide security schemes for protecting that information. Some databases, such as Paradox and dBASE, only provide security at the table or field level. When users try to access protected tables, they are required to provide a password. Once users have been authenticated, they can see only those fields (columns) for which they have permission.
Most SQL servers require a password and user name to use the database server at all. Once the user has logged in to the database, that username and password determine which tables can be used. For information on providing passwords to SQL servers when using the BDE, see Controlling server login. For information on providing this information when using ActiveX Data Objects (ADO), see Controlling the connection login. For information on providing this information when using the InterBase direct access components, see the OnLogin event of TIBDatabase.

When designing database applicati…

Types of databases

You can connect to different types of databases, depending on what drivers you have installed with the Borland Database Engine (BDE) or ActiveX Data Objects (ADO).
These drivers may connect your application to local databases such as Paradox, Access, and dBASE or remote database servers like Microsoft SQL Server, Oracle, and Informix. Similarly, the InterBase Express components can access either a local or remote version of InterBase.

NB: Different versions of C++Builder come with the components that use these drivers (BDE or ADO), or with the InterBase Express components.

Choosing what type of database to use depends on several factors. Your data may already be stored in an existing database. If you are creating the tables of information your application uses, you may want to consider the following questions.

How much data will the tables hold?
How many users will be sharing these tables?
What type of performance (speed) do you require from the database?

Local databases
Local databases resid…

Designing database applications

Database applications allow users to interact with information that is stored in databases. Databases provide structure for the information, and allow it to be shared among different applications.
C++Builder provides support for relational database applications. Relational databases organize information into tables, which contain rows (records) and columns (fields). These tables can be manipulated by simple operations known as the relational calculus.
When designing a database application, you must understand how the data is structured. Based on that structure, you can then design a user interface to display data to the user and allow the user to enter new information or modify existing data.

Using databases
The components on the Data Access page, the ADO page, or the InterBase page of the Component palette allow your application to read from and write to databases. The components on the Data Access page use the Borland Database Engine (BDE) to access database information which they make…

The TPersistent Branch

Directly below TObject in the VCL hierarchy is TPersistent. TPersistent adds two very important methods to all classes based on it—SaveToStream and LoadFromStream. These methods supply persistence to objects.
For example, when the form designer needs to create a DFM file (a file used to store information about the components on the form), it loops through its components array and calls SaveToStream for all the components on the form. Each component “knows” how to write its changed properties out to a stream (in this case, a text file). Conversely, when the form designer needs to load the properties for components from the DFM file, it loops through the components array and calls LoadFromStream for each component. Thus, any class derived from TPersistent has the ability to save its state information and restore it on demand.

The types of classes in this branch include:

TGraphicsObject, an abstract base class for objects which encapsulate Windows graphics objects: TBrush, TFont, and TPen.

The TObject Branch

All VCL objects descend from TObject, an abstract class whose methods define fundamental behavior like construction, destruction, and message handling. Much of the powerful capability of VCL objects are established by the methods that TObject introduces. TObject encapsulates the fundamental behavior common to all objects in the VCL, by introducing methods that provide:

The ability to respond when objects are created or destroyed.
Class type and instance information on an object, and runtime type information (RTTI) about its published properties.
Support for message-handling.

TObject is the immediate ancestor of many simple classes. Classes that are contained within this branch have one common, important characteristic, they are transitory. What this means, is that these classes do not have a method to save the state that they are in prior to destruction, they are not persistent.
One of the main groups of classes in this branch is the Exception class. This class provides a large set of bu…

Types of events

The kinds of events that can occur can be divided into two main categories:

User events
System events

Regardless of how the event was called, C++Builder looks to see if you have assigned any code to handle that event. If you have, then that code is executed; otherwise, nothing is done.

User events

User events are actions that are initiated by the user. Examples of user events are OnClick (the user clicked the mouse), OnKeyPress (the user pressed a key on the keyboard), and OnDblClick (the user double-clicked a mouse button). These events are always tied to a user's actions.

System events

System events are events that the operating system fires for you. For example, the OnTimer event (the Timer component issues one of these events whenever a predefined interval has elapsed), the OnCreate event (the component is being created), the OnPaint event (a component or window needs to be redrawn), etc. Usually, system events are not directly initiated by a user action.

Understanding the VCL

The Visual Component Library (VCL) is based on the properties, methods, and events (PME) model. The PME model defines the data members (properties), the functions that operate on the data (methods), and a way to interact with users of the class (events). The VCL is a hierarchy of objects, written in Object Pascal and tied to the C++Builder IDE, that allows you to develop applications quickly. Using C++Builder’s Component palette and Object Inspector, you can place VCL components on forms and specify their properties without writing code.

Properties

Properties are characteristics of components. You can see and change properties at design time and get immediate feedback as the components react in the IDE. Well-designed properties make your components easier for others to use and easier for you to maintain.

Methods

Methods are functions that are members of a class. Class methods can access all the public, protected and private properties and data members of the class and are commonly referre…

The integrated development environment

When you start C++Builder, you are immediately placed within the integrated development environment, also called the IDE. This environment provides all the tools you need to design, develop, test, debug, and deploy applications.

C++Builder’s development environment includes a visual form designer, Object Inspector, Component palette, Project Manager, source code editor, debugger, and installation tool. You can move freely from the visual representation of an object (in the form designer), to the Object Inspector to edit the initial runtime state of the object, to the source code editor to edit the execution logic of the object. Changing code-related properties, such as the name of an event handler, in the Object Inspector automatically changes the corresponding source code. In addition, changes to the source code, such as renaming an event handler method in a form class declaration, is immediately reflected in the Object Inspector.

Designing applications
C++Builder includes all the tool…

Using the const Keyword in C++ Programs

C++ extends const to include classes and member functions. In a C++ class definition, use the const modifier following a member function declaration. The member function is prevented from modifying any data in the class.

A class object defined with the const keyword attempts to use only member functions that are also defined with const. If you call a member function that is not defined as const, the compiler issues a warning that a non-const function is being called for a const object. Using the const keyword in this manner is a safety feature of C++.

Warning: A pointer can indirectly modify a const variable, as in the following:

*(int *)&maxint = 35;

If you use the const modifier with a pointer parameter in a function's parameter list, the function cannot modify the variable that the pointer points to. For example,

int printf (const char *format, ...);

printf is prevented from modifying the format string.
volatile
Syntax

volatile ;

Description

Use the volatile modifier to indicate that…

C++Builder modifiers

Modifier Use with Description

const1 Variables Prevents changes to object.
volatile1 Variables Prevents register allocation and some optimization. Warns compiler that object might be subject to outside change during evaluation.
__cdecl2 Functions Forces C argument-passing convention. Affects linker and link-time names.
__cdecl2 Variables Forces global identifier case-sensitivity and leading underscores in C.
__pascal Function Forces Pascal argument-passing convention. Affects linker and link- time names.

__pascal Variables Forces global identifier case-insensitivity with no leading underscores in C.
__import Functions/classes Tells the compiler which functions or classes to import.
__export Functions/classes Tells the compiler which functions or classes to export.
__declspec(dllimport) Functions/classes Tells the compiler which functions or classes to…

Variable modifiers Mixed-language calling conventions

C++Builder allows your programs to easily call routines written in other languages, and vice versa. When you mix languages , you have to deal with two important issues: identifiers and parameter passing.

By default, C++Builder saves all global identifiers in their original case (lower, upper, or mixed) with an underscore "_" prepended to the front of the identifier. To remove the default, you can use the -u command-line option.

he following table summarizes the effects of a modifier applied to a called function. For every modifier, the table shows the order in which the function parameters are pushed on the stack. Next, the table shows whether the calling program (the caller) or the called function (the callee) is responsible for popping the parameters off the stack. Finally, the table shows the effect on the name of a global function.

Calling conventions

Modifier Push parameters Pop parameters Name change (only in C)

__cdecl1 Right to left Caller '_' prepended
_…

Declarations and declarators

A declaration is a list of names. The names are sometimes referred to as declarators or identifiers. The declaration begins with optional storage class specifiers, type specifiers, and other modifiers. The identifiers are separated by commas and the list is terminated by a semicolon.

Simple declarations of variable identifiers have the following pattern:

data-type var1” <=init1>, var2 <=init2>, ...;”

where var1, var2,... are any sequence of distinct identifiers with optional initializers. Each of the variables is declared to be of type data-type. For example,

int x = 1, y = 2;

creates two integer variables called x and y (and initializes them to the values 1 and 2, respectively).

These are all defining declarations; storage is allocated and any optional initializers are applied.

The initializer for an automatic object can be any legal expression that evaluates to an assignment-compatible value for the type of the variable involved. Initializers for static objects must be constant…

Arrays, structures, and unions

You initialize arrays and structures (at declaration time, if you like) with a brace-enclosed list of initializers for the members or elements of the object in question. The initializers are given in increasing array subscript or member order. You initialize unions with a brace-enclosed initializer for the first member of the union. For example, you could declare an array days, which counts how many times each day of the week appears in a month (assuming that each day will appear at least once), as follows:

int days[7] = { 1, 1, 1, 1, 1, 1, 1 }

The following rules initialize character arrays and wide character arrays:

You can initialize arrays of character type with a literal string, optionally enclosed in braces. Each character in the string, including the null terminator, initializes successive elements in the array. For example, you could declare

char name[] = { "Unknown" };

which sets up an eight-element array, whose elements are 'U' (for name[0]), 'n' (for …

Initializers

Initializers set the initial value that is stored in an object (variables, arrays, structures, and so on). If you don't initialize an object, and it has static duration, it will be initialized by default in the following manner:

To zero if it is an arithmetic type
To null if it is a pointer type

Note: If the object has automatic storage duration, its value is indeterminate.

Syntax for initializers

initializer
= expression
= {initializer-list} <,>}
(expression list)
initializer-list
expression
initializer-list, expression
{initializer-list} <,>}

Rules governing initializers

The number of initializers in the initializer list cannot be larger than the number of objects to be initialized.
The item to be initialized must be an object (for example, an array).
For C (not required for C++), all expressions must be constants if they appear in one of these places:

In an initializer for an object that has static duration.
In an initializer list for an array, structure, or union…

The Fundamental Types

The fundamental type specifiers are built from the following keywords:

char __int8 long
double __int16 signed
float __int32 short
int __int64 unsigned

From these keywords you can build the integral and floating-point types, which are together known as the arithmetic types. The modifiers long, short, signed, and unsigned can be applied to the integral types. The include file limits.h contains definitions of the value ranges for all the fundamental types.



Integral types

char, short, int, and long, together with their unsigned variants, are all considered integral data types. Integral types shows the integral type specifiers, with synonyms listed on the same line.

Integral types

char, signed char Synonyms if default char set to signed.
unsigned char
char, unsigned char Synonyms if default char set to unsigned.
signed char
int, signed int
unsigned, unsigned int
short, short int, signed short int
unsigned short, unsigned short int
long, long int, signed long int
unsigned long, unsigned lon…

Type categories

The four basic type categories (and their subcategories) are as follows:

Aggregate

Array
struct
union
class (C++ only)

Function
Scalar

Arithmetic
Enumeration
Pointer
Reference (C++ only)

void

Types can also be viewed in another way: they can be fundamental or derived types. The fundamental types are void, char, int, float, and double, together with short, long, signed, and unsigned variants of some of these. The derived types include pointers and references to other types, arrays of other types, function types, class types, structures, and unions.

A class object, for example, can hold a number of objects of different types together with functions for manipulating these objects, plus a mechanism to control access and inheritance from other classes

Given any nonvoid type type (with some provisos), you can declare derived types as follows
Declaring types

Declaration Description

type t; …