Home > Articles

This chapter is from the book

VCL Overview

Supplied with C++Builder is a chart that schematically represents the Visual Component Library (VCL) object hierarchy. Not surprisingly, this chart has expanded with each new version of C++Builder. What you can't see, however, is the true complexity of the VCL. The explanation is simple: The VCL is much more than objects descending from other objects.

The VCL is based on what is known as the PME model, including properties, methods, and events. This architecture is joined with the Component Palette, Object Inspector, and IDE, giving developers a rapid approach to building applications known as Rapid Application Development (RAD). A developer can drop components onto a form and have a working Windows application almost without writing a single line of code. Obviously, writing code is required to make the application fully functional, but the VCL handles most of the work for you, making application development very expedient and more enjoyable. You can spend more time building the working blocks of your application rather than having to spend repetitive time with the framework of each Windows application you develop.

The remainder of this topic will take a very brief look at the hierarchy of VCL objects in general.

It All Starts at TObject

The VCL is fundamentally a group of objects that descend from the abstract class TObject. This class provides the capability to respond to the creation and destruction of objects, supports message handling, and contains class type and Runtime Type Information (RTTI) of its published properties.

RTTI enables you to determine the type of an object at runtime even when the code uses a pointer or reference to that object. As an example, C++Builder passes a TObject pointer to each of its events. This might be a mouse-click event or an object obtaining focus. Through the use of RTTI it is possible to perform a cast (dynamic_cast) to either use the object or determine the object type. The RTTI mechanism also enables testing an object type by using the typeid operator. The dynamic_cast operator is demonstrated later in this chapter. The C++Builder Language Guide online help provides additional information on this topic.

Descending from TObject are many simple nonpersistent data classes, wrappers, and streams, such as TList, TStack, TPrinter, TRegistry, and TStream, to name a few.

Persistent data, in terms of the VCL, refers to the mechanism of storing property values. The simplest example is the caption of a button or label. At design time you enter the caption in the Object Inspector. This caption is maintained between programming sessions and is available at runtime. The data is persistent. Nonpersistent classes, therefore, refers to simple classes designed to perform particular functions, but unable to save their state between sessions.

A wrapper can be described as a means of placing an envelope around the more complex Windows API. Wrappers allow for the creation of objects or components that are easier to use and can be used across multiple projects. Components, and other objects to some extent, shield you from the API and at the same time provide the convenience of using its powerful features in an easy-to-use fashion. Later chapters will provide additional information on these topics.

Another commonly used descendant of TObject is the Exception class, which provides many built-in exception classes for handling conditions such as, divide-by-zero and stream errors. With very minimal work this class can also be used to create custom classes for use in your own applications.

The other major branches of TObject include TPersistent, TComponent, TControl, TGraphicControl, and TWinControl.

TPersistent adds methods to TObject that enable the object to save its state prior to destruction, and reload that state when it is created again. This class is important in the creation of components that contain custom classes as properties. If the property needs to be streamed, it must descend from TPersistent rather than TObject. This branch includes many types of classes with the most common being TCanvas, TClipboard, TGraphic, TGraphicsObject, and TStrings. TPersistent descends to provide TComponent, the common base for all VCL components.

Property streaming refers to the mechanism by which the object's property values are written to the form's file. When the project is reopened, the property values are streamed (or read) back, thereby restoring their previous values.

TComponent objects provide the foundation for building C++Builder applications. Components have the capability to appear on the Component Palette, become parents for other components, control other components, and perform streaming operations.

There are two types of components—visual and nonvisual. Nonvisual components require no visual interface and are, therefore, derived directly from TComponent. Visual components are required to have the capability to been seen and interact with the user at runtime. TControl adds the drawing routines and window events required for defining a visual component. These visual components are divided into two groups: windowed (TWinControl) and nonwindowed (TGraphicControl).

TGraphicControl components are responsible for drawing themselves, but never receive focus. Examples include TImage, TLabel, TBevel, and TShape.

TWinControl components are similar to TGraphicControl except that they can receive focus, allowing for user interaction. These components are known as windowed controls, have a window handle, and can contain (or be the parent of) other controls.

Building on Existing Objects

The C++Builder object-oriented architecture means faster application development through reuse of existing objects and supporting classes. Giving the component objects the capability to present their published properties to the developer via the Object Inspector provides the extra dimension that further improves the development cycle.

But, the Object Inspector does more than simply present the component's published properties for review or editing. In Figure 3.1 you can see the Object Inspector showing the common properties of TLabel, TEdit, TButton, and TCheckBox controls. Looking at the hierarchy of these controls, you can see that TLabel descends from TGraphicControl, and the remainder descend from TWinControl. The common ancestor for all four controls is therefore TControl (because TGraphicControl and TWinControl descend from TControl).

Figure 3.1Figure 3.1 Common properties of multiple selected components.

Figure 3.1 is, therefore, displaying all the common properties the components have inherited from TControl. If you change one of these properties while they are all selected, this change will be reflected in all the controls simultaneously.

Building objects from existing classes or objects enables you to develop additional functionality into the descendants while at the same time enabling the base classes to remain available for new descendants that require a common base with some additional unique features. Some developers might argue that this additional class and the associated RTTI contained within the hierarchy are only adding to the overhead of the application. This overhead is well worth the benefits this object model provides. Each of the objects and components provided with C++Builder can appear quite differently, but share common features that are inherited from ancestor objects, making the development process more streamlined.

Using the VCL

It is important to understand how the VCL differs from regular classes and objects. The VCL originates from Delphi. As a result, all VCL objects are created on the free store and referenced as pointers rather than static objects. Only VCL objects need to be created and used in this fashion. All standard C/C++ objects can be used in either fashion.

An example will illustrate this. The following code first shows how a standard C++ class can be created on the stack, and then on the heap. Then, it shows how VCL objects must be created.

The C++ class code is as follows:

class MyClass
{
private:
  int MyVar;
public:
  MyClass(void);
};

Creating an instance of this class on the stack is shown next. When the class goes out of scope, the memory allocated for the object is released automatically.

MyClass Tmp;
Tmp.MyVar = 10;
// do something

Next, you look at creating an instance of this class on the heap. It is the responsibility of the creator to destroy the object before it goes out of scope. Otherwise, the memory is not released, resulting in a memory leak.

MyClass *Tmp;
Tmp = new MyClass;
Tmp->MyVar = 10;
// do something
delete Tmp;

VCL objects are like the second example, created on the heap. If you attempt to create a VCL object on the stack, the compiler will complain with the error message, VCL style classes must be constructed using operator new.

C++Builder has also made provisions for automatic destruction of objects that have owners. Let's assume you create a TLabel object dynamically and pass this as the owner:

TLabel *MyLabel = new TLabel(this);

When MyLabel goes out of scope, you at first assume a memory leak has occurred. Objects of this nature don't have to worry about freeing themselves explicitly because the VCL has a built-in mechanism to free all child objects before an owner object is destroyed. The term parent object was carefully avoided. This will be explained further.

Nonvisual components have owners, whereas visual components have owners and parents. The easiest way to distinguish the two terms is to think of the owner as the creator and the parent as the container allowing the component to exist. Suppose you have a TPanel component on a form, and on this component are three label components. There are two possible scenarios, depending on who created the labels.

In the first scenario, you have the labels being dropped onto the panel at design time. In this case, the panel is the parent for each of the labels, but the application is the owner. When the application is closed, the VCL ensures that each of the child objects (the panel and the three labels) are all destroyed before the application itself is destroyed.

In another case, you might drop an aggregate component (a component made up of many components) onto a form. For this example you assume it is a panel with three labels on it. The component creates the panel, and then creates three labels to sit on that panel. The panel is still the parent of the labels, but now the owner of the panel and the three labels is the component that was dropped onto the form. If the component is destroyed, the panel and labels also will be automatically destroyed.

This is a great feature for design time objects, but if you create objects at runtime, you should delete them explicitly. You won't have any memory leaks if you don't, but it makes the code more readable and documents the intention of the code. The following code demonstrates creating these objects at runtime.

TPanel *Panel1;
TLabel *Label1, *Label2, *Label3;
Panel1 = new TPanel(this);
Panel1->Parent = Form1;
Label1 = new TLabel(this);
Label1->Parent = Panel1;
Label2 = new TLabel(this);
Label2->Parent = Panel1;
Label3 = new TLabel(this);
Label3->Parent = Panel1;
// set other properties such as caption, position, etc
// do something
delete Label1;
delete Label2;
delete Label3;
delete Panel1;

The panel is created with the application as the owner and the form as the parent. The labels are then created similarly, with the difference being that the panel is made the parent of the labels. You could move the labels to another panel just by changing the Parent property. It is possible to delete the panel so that the labels would be deleted automatically, but I prefer to delete everything explicitly. This becomes more important when dealing with real-world applications in which global pointers are shared. It is also good practice to set the pointers to NULL (or zero) after they have been deleted (unless they are about to go out of scope). If another part of your application tries to delete the object after it has been destroyed, and you haven't nulled the pointer, an access violation is certain.

As mentioned earlier, the use of std::auto_ptr offers a mechanism for exception safe, class, and function local allocation of VCL objects.

The C++ Extensions

C++Builder has added extensions to the C++ language to make it a powerful product capable of utilizing the VCL and fitting seamlessly into the PME model. Some programmers consider the issue of C++ extensions controversial, but they can be useful, so long as they make the product powerful, maintain compatibility with ANSI standards, and provide for a shorter development cycle. In all cases, C++Builder manages this very well.

The extensions are listed next with a brief description. Please note that each of the extensions is prefixed with two underscores.

The __automated Class Extension

Object linking and embedding (OLE) does not provide type information in a type library. The automated section of a class that is derived from TAutoObject or a descendant of TAutoObject is used by applications supporting OLE automation. The required OLE automation information is generated for member functions and properties declared in this section.

class TMyAutoClass : public TAutoObject
{
public:
  virtual __fastcall TMyAutoClass(void);

__automated:
   AnsiString __fastcall GetClassName(void) { return("MyAutoClass"); }
};

The last point to make is that the declared method is of type __fastcall (described a little later). This is required for automated functions and causes the compiler to attempt to pass the parameters in the registers rather than on the stack.

The __classid(class) Class Extension

The __classid extension is used to bridge the gap between the VCL, RTTI functions, and the C++ language. It is used when an RTTI function requires class information as a parameter.

As an example, the RegisterComponentEditor() method enables you to create and register a custom editor for your components. My business produces a security component package (MJFSecurity) specifically for C++Builder. This package includes a number of custom components designed for protecting applications from piracy. One of these components is called TAppLock, and it uses a custom editor called TAppLockEditor. As part of the Register() method of the package, the editor is registered using the following code:

namespace Applock
{
  void __fastcall PACKAGE Register()
  {
    // ... code omitted from here
    RegisterComponentEditor(__classid(TAppLock), __classid(TAppLockEditor));
  }
}

The RegisterComponentEditor() method takes two parameters as pointers to TMetaClass (C++Builder's representation of the Delphi class-reference type). The TMetaClass for a given class can be acquired by using the __classid operator. The compiler uses the __classid operator to generate a pointer to the vtable (virtual table) for the given class name.

For further information on MJFSecurity, go to http://www.mjfreelancing.com/.

The __closure Class Extension

Standard C++ enables you to assign a derived class instance to a base class pointer, but does not enable you to assign a derived class's member function to a base class member function pointer. Listing 3.1 demonstrates this problem.

Listing 3.1 Illegal Assignment of a Derived Class Member Function

enum HandTypes {htHour, htMinute, htSecond};

class TWatch
{
public:
  void MoveHand(HandTypes HandType);
};

class TWatchBrand : public TWatch
{
public:
  void NewFeature(bool Start);
};

void (TWatch::*Wptr)(bool);    // declare a base class member
                  // function pointer
Wptr = &TWatchBrand::NewFeature;  // illegal assignment of derived
                  // class member function

C++Builder includes the __closure keyword to permit the previous situation. Listing 3.2 uses the classes from Listing 3.1 to demonstrate how this is done.

Listing 3.2 Assigning a Derived Class Member Function to a Base Member Function Pointer by Using __closure

TWatchBrand *WObj = new TWatchBrand; // create the object
void (__closure *Wptr)(bool);     // define a closure pointer
Wptr = WObj->NewFeature;      // set it to the NewFeature member function
Wptr(false);             // call the function, passing false
Wptr = 0;               // set the pointer to NULL
delete WObj;             // delete the object

Note that you can also assign closure pointers to the base class member functions, as Listing 3.3 shows.

Listing 3.3 Assigning Closure Pointers to Base Class Member Functions

void (__closure *Wptr2)(HandTypes);
Wptr2 = WObj->MoveHand;
Wptr2(htSecond);

The __closure keyword is predominantly used for events in C++Builder.

The __declspec Class Extension

VCL classes have the following restrictions imposed on them:

  • No virtual base classes are allowed.

  • No multiple inheritance is allowed.

  • They must be dynamically allocated on the heap by using the global new operator.

  • They must have a destructor.

  • Copy constructors and assignment operators are not compiler generated for VCL-derived classes.

The __declspec keyword is provided for language support with the VCL to overcome the previously mentioned items. The sysmac.h file provides macros that you should use if you need to use this keyword. The __declspec variations are discussed next.

__declspec(delphiclass, package)

sysmac.h defines the macro DELPHICLASS as __declspec(delphiclass, package). The delphiclass argument is used for the declaration of classes derived from TObject. If a class is translated from Delphi, the compiler needs to know that the class is derived from TObject. Hence, this modifier is used.

Similarly, if you create a new class that is to be used as a property type in a component, and you need to forward declare the class, you need to use the __declspec (delphiclass, package) keyword for the compiler to understand. Listing 3.4 shows an example of forward declaring a class where a new component has a pointer to that class type.

Listing 3.4 Forward Declaring a Class to Use as a Member of Another Class

class TMyObject;

class TMyClass : public TComponent
{
private:
  TMyObject *FMyNewObject;

public:
 __fastcall TMyClass(TComponent *Owner) : TComponent(Owner){}
 __fastcall ~TMyClass(void);

};

class TMyObject : public TPersistent
{
public:
 __fastcall TMyObject(void){}
 __fastcall ~TMyObject(void);
};

Listing 3.4 will compile because the compiler only has a reference to the TMyObject class. If you need to include a property of type TMyObject, you need to tell the compiler the class is derived from a descendant of TObject. The modified code is shown in Listing 3.5.

Listing 3.5 Using DELPHICLASS to Forward Declare a Class Required as a Property of Another Class

class DELPHICLASS TMyObject;

class TMyObject;

class TMyClass : public TComponent
{
private:
 TMyObject *FMyNewObject;

public:
 __fastcall TMyClass(TComponent *Owner) : TComponent(Owner){}
 __fastcall ~TMyClass(void);

__published:
 __property TMyObject *NewObject = {read = FMyNewObject};
};

class TMyObject : public TPersistent
{
public:
 __fastcall TMyObject(void){}
 __fastcall ~TMyObject(void);
};

sysmac.h also defines a closely related macro RTL_DELPHICLASS as __declspec (delphiclass). This macro is used when nonpackaged RTL (runtime library) functionality is required in a class. Because components are created in design time packages or runtime/design time packages, you will find the DELPHICLASS macro used.

__declspec(delphireturn, package)

sysmac.h defines the macro DELPHIRETURN as __declspec(delphireturn, package).

The delphireturn parameter is used internally by C++Builder to enable classes created with C++Builder to support Delphi's built-in data types and language constructs. Examples include Currency, AnsiString, Variant, TDateTime, and Set.

Similar to __declspec(delphiclass), there is also a macro defined for __declspec(delphireturn). This macro, RTL_DELPHIRETURN, is used when Delphi's semantics are required in nonpackaged classes.

__declspec(dynamic)

sysmac.h defines the macro DYNAMIC as __declspec(dynamic). The dynamic argument is used for dynamic functions and is valid only for classes derived from TObject. These are similar to virtual functions except that the vtable information is stored only in the object that created the functions. If you call a dynamic function that doesn't exist, the ancestor vtables are searched until the function is found. Dynamic functions effectively reduce the size of the vtables at the expense of a short delay to look up the ancestor tables.

Dynamic functions cannot be redeclared as virtual and vice versa.

__declspec(hidesbase)

sysmac.h defines the macro HIDESBASE as __declspec(hidesbase). The hidesbase parameter is used to preserve Delphi semantics. Imagine a class called C1; derived from it is another class called C2. If both classes contain a function called foo, C++ interprets C2::foo() as a replacement for C1::foo(). In Delphi, C2::foo() is a different function to C1::foo(). To preserve this in C++ classes, you use the HIDESBASE macro. Listing 3.6 demonstrates its use.

Listing 3.6 Using HIDESBASE to Override Class Methods in Descendant Classes

class TMyObject : public TPersistent
{
public:
 __fastcall TMyObject(void){}
 __fastcall ~TMyObject(void);
  void __fastcall Func(void){}
};

class TMyObject2 : public TMyObject
{
public:
 __fastcall TMyObject2(void){}
 __fastcall ~TMyObject2(void);
  HIDESBASE void __fastcall Func(void){}
};

__declspec(hidesbase, dynamic)

sysmac.h defines the macro HIDESBASEDYNAMIC as __declspec(hidesbase, dynamic). This is used when Delphi's semantics need to be preserved for dynamic functions. The HIDESBASE macro is used when you need to preserve the way Pascal overrides methods in descendant classes. The HIDESBASEDYNAMIC macro does the same for dynamic methods.

__declspec(package)

sysmac.h defines the macro PACKAGE as __declspec(package). The package argument in __declspec(package) indicates that the code defining the class can be compiled in a package. This enables classes to be imported and exported from the resulting BPL file.

__declspec(pascalimplementation)

sysmac.h defines the macro PASCALIMPLEMENTATION as __declspec(pascalimplementation). The pascalimplementation argument indicates that the code defining the class was implemented in Delphi. This modifier appears in a Delphi portability header file with an .hpp extension.

The __fastcall Keyword

The __fastcall keyword is used to declare functions that expect parameters to be passed in registers. If the parameter is a floating-point or struct type, the registers are not used.

In general, use the __fastcall keyword only when declaring VCL class member functions. Using this modifier in all other cases will, more often than not, result in reduced performance. Typical examples of its use are found in all form class and component member functions. You should also note that the __fastcall modifier is used in name mangling.

The __property Keyword

The __property keyword is used to declare properties in classes, even non-VCL classes. Properties are data members, with the following additional features:

  • They have associated read and write methods.

  • They can indicate default values.

  • They can be streamed to and from a form file.

  • They can extend a property defined in a base class.

  • They can make the data member read-only or write-only.

Refer to Chapter 4, "Creating Custom Components," for a more detailed look at properties.

The __published Keyword

The __published keyword is permitted only in classes descendant from TObject. Visibility rules for the __published section of a VCL class are the same as the public section, with the addition of RTTI being generated for data members and properties declared. RTTI enables you to query the data members, properties, and member functions of a class.

This RTTI is useful in event handlers. All standard events have a parameter passed of type TObject*. This parameter can be queried when the type of sender is unknown. The following example shows how this is done when the OnButtonClick event is called from either a button click or a manual call such as Button1Click(NULL). Note that you can also do a manual call, passing the pointer of another button such as Button1Click(Button2). Listing 3.7 shows how this can be implemented.

Listing 3.7 Using RTTI to Query an Object Type

void __fastcall TForm1::Button1Click(TObect *Sender)
{
TButton *Button = dynamic_cast<TButton *>(Sender);
if (Button)
  {
  // do something if a button was pressed.
  }
else
  {
  // do something when a call was made
  // passing a NULL value for *Sender)
  }
}

VCL and CLX

Although the underpinnings of VCL and CLX are very different (which is why VCL is not portable across platforms), from a usage perspective they are almost identical, providing largely the same components in the same hierarchy with the same methods and properties. Look in the help to see if a component is VCL, CLX, or both.

NOTE

If you create a new CLX Application or new CLX MDI Application, you get a project that only supplies CLX components on the component palette. These projects are available from the File, New menu, or from the dialog that is presented when you pick File, New, Other (CLX Application is on the New page and CLX MDI Application is on the Projects page).

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.

Overview


Pearson Education, Inc., 221 River Street, Hoboken, New Jersey 07030, (Pearson) presents this site to provide information about products and services that can be purchased through this site.

This privacy notice provides an overview of our commitment to privacy and describes how we collect, protect, use and share personal information collected through this site. Please note that other Pearson websites and online products and services have their own separate privacy policies.

Collection and Use of Information


To conduct business and deliver products and services, Pearson collects and uses personal information in several ways in connection with this site, including:

Questions and Inquiries

For inquiries and questions, we collect the inquiry or question, together with name, contact details (email address, phone number and mailing address) and any other additional information voluntarily submitted to us through a Contact Us form or an email. We use this information to address the inquiry and respond to the question.

Online Store

For orders and purchases placed through our online store on this site, we collect order details, name, institution name and address (if applicable), email address, phone number, shipping and billing addresses, credit/debit card information, shipping options and any instructions. We use this information to complete transactions, fulfill orders, communicate with individuals placing orders or visiting the online store, and for related purposes.

Surveys

Pearson may offer opportunities to provide feedback or participate in surveys, including surveys evaluating Pearson products, services or sites. Participation is voluntary. Pearson collects information requested in the survey questions and uses the information to evaluate, support, maintain and improve products, services or sites, develop new products and services, conduct educational research and for other purposes specified in the survey.

Contests and Drawings

Occasionally, we may sponsor a contest or drawing. Participation is optional. Pearson collects name, contact information and other information specified on the entry form for the contest or drawing to conduct the contest or drawing. Pearson may collect additional personal information from the winners of a contest or drawing in order to award the prize and for tax reporting purposes, as required by law.

Newsletters

If you have elected to receive email newsletters or promotional mailings and special offers but want to unsubscribe, simply email information@informit.com.

Service Announcements

On rare occasions it is necessary to send out a strictly service related announcement. For instance, if our service is temporarily suspended for maintenance we might send users an email. Generally, users may not opt-out of these communications, though they can deactivate their account information. However, these communications are not promotional in nature.

Customer Service

We communicate with users on a regular basis to provide requested services and in regard to issues relating to their account we reply via email or phone in accordance with the users' wishes when a user submits their information through our Contact Us form.

Other Collection and Use of Information


Application and System Logs

Pearson automatically collects log data to help ensure the delivery, availability and security of this site. Log data may include technical information about how a user or visitor connected to this site, such as browser type, type of computer/device, operating system, internet service provider and IP address. We use this information for support purposes and to monitor the health of the site, identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents and appropriately scale computing resources.

Web Analytics

Pearson may use third party web trend analytical services, including Google Analytics, to collect visitor information, such as IP addresses, browser types, referring pages, pages visited and time spent on a particular site. While these analytical services collect and report information on an anonymous basis, they may use cookies to gather web trend information. The information gathered may enable Pearson (but not the third party web trend services) to link information with application and system log data. Pearson uses this information for system administration and to identify problems, improve service, detect unauthorized access and fraudulent activity, prevent and respond to security incidents, appropriately scale computing resources and otherwise support and deliver this site and its services.

Cookies and Related Technologies

This site uses cookies and similar technologies to personalize content, measure traffic patterns, control security, track use and access of information on this site, and provide interest-based messages and advertising. Users can manage and block the use of cookies through their browser. Disabling or blocking certain cookies may limit the functionality of this site.

Do Not Track

This site currently does not respond to Do Not Track signals.

Security


Pearson uses appropriate physical, administrative and technical security measures to protect personal information from unauthorized access, use and disclosure.

Children


This site is not directed to children under the age of 13.

Marketing


Pearson may send or direct marketing communications to users, provided that

  • Pearson will not use personal information collected or processed as a K-12 school service provider for the purpose of directed or targeted advertising.
  • Such marketing is consistent with applicable law and Pearson's legal obligations.
  • Pearson will not knowingly direct or send marketing communications to an individual who has expressed a preference not to receive marketing.
  • Where required by applicable law, express or implied consent to marketing exists and has not been withdrawn.

Pearson may provide personal information to a third party service provider on a restricted basis to provide marketing solely on behalf of Pearson or an affiliate or customer for whom Pearson is a service provider. Marketing preferences may be changed at any time.

Correcting/Updating Personal Information


If a user's personally identifiable information changes (such as your postal address or email address), we provide a way to correct or update that user's personal data provided to us. This can be done on the Account page. If a user no longer desires our service and desires to delete his or her account, please contact us at customer-service@informit.com and we will process the deletion of a user's account.

Choice/Opt-out


Users can always make an informed choice as to whether they should proceed with certain services offered by InformIT. If you choose to remove yourself from our mailing list(s) simply visit the following page and uncheck any communication you no longer want to receive: www.informit.com/u.aspx.

Sale of Personal Information


Pearson does not rent or sell personal information in exchange for any payment of money.

While Pearson does not sell personal information, as defined in Nevada law, Nevada residents may email a request for no sale of their personal information to NevadaDesignatedRequest@pearson.com.

Supplemental Privacy Statement for California Residents


California residents should read our Supplemental privacy statement for California residents in conjunction with this Privacy Notice. The Supplemental privacy statement for California residents explains Pearson's commitment to comply with California law and applies to personal information of California residents collected in connection with this site and the Services.

Sharing and Disclosure


Pearson may disclose personal information, as follows:

  • As required by law.
  • With the consent of the individual (or their parent, if the individual is a minor)
  • In response to a subpoena, court order or legal process, to the extent permitted or required by law
  • To protect the security and safety of individuals, data, assets and systems, consistent with applicable law
  • In connection the sale, joint venture or other transfer of some or all of its company or assets, subject to the provisions of this Privacy Notice
  • To investigate or address actual or suspected fraud or other illegal activities
  • To exercise its legal rights, including enforcement of the Terms of Use for this site or another contract
  • To affiliated Pearson companies and other companies and organizations who perform work for Pearson and are obligated to protect the privacy of personal information consistent with this Privacy Notice
  • To a school, organization, company or government agency, where Pearson collects or processes the personal information in a school setting or on behalf of such organization, company or government agency.

Links


This web site contains links to other sites. Please be aware that we are not responsible for the privacy practices of such other sites. We encourage our users to be aware when they leave our site and to read the privacy statements of each and every web site that collects Personal Information. This privacy statement applies solely to information collected by this web site.

Requests and Contact


Please contact us about this Privacy Notice or if you have any requests or questions relating to the privacy of your personal information.

Changes to this Privacy Notice


We may revise this Privacy Notice through an updated posting. We will identify the effective date of the revision in the posting. Often, updates are made to provide greater clarity or to comply with changes in regulatory requirements. If the updates involve material changes to the collection, protection, use or disclosure of Personal Information, Pearson will provide notice of the change through a conspicuous notice on this site or other appropriate way. Continued use of the site after the effective date of a posted revision evidences acceptance. Please contact us if you have questions or concerns about the Privacy Notice or any objection to any revisions.

Last Update: November 17, 2020