Home > Articles > Programming > C/C++

Separate Compilation and Namespaces in C++

📄 Contents

  1. Separate Compilation
  2. Namespaces
  3. Summary
Organizing a C++ program into separate parts (by using separate compilation and namespaces) is covered in this article by expert Walter Savitch.
This article is derived from Absolute C++ (Addison-Wesley, 2002), by Walter Savitch.
This chapter is from the book

This chapter is from the book

From mine own library with volumes that I prize above my dukedom.
—William Shakespeare, The Tempest

This article covers two topics that have to do with how you organize a C++ program into separate parts. In the first part, "Separate Compilation," we discuss how a C++ program can be distributed across a number of files so that when some parts of the program change, only those parts need to be recompiled, and the separate parts can be more easily reused in other applications.

In the second section, we discuss namespaces, which are a way of allowing you to reuse the names of classes, functions, and other items by qualifying the names to indicate different uses of the names. Namespaces divide your code into sections, so that the different sections may reuse the same names with differing meanings. It is a kind of local meaning for names that is more general than local variables.

Separate Compilation

Your "if" is the only peacemaker; much virtue in "if."
—William Shakespeare, As You Like It

C++ has facilities for dividing a program into parts that are kept in separate files, compiled separately, and then linked together when (or just before) the program is run. You can place the definition for a class (and its associated function definitions) in files that are separate from the programs that use the class. That way, you can build up a library of classes so that many programs can use the same class. You can compile the class once and then use it in many different programs, just like you use the predefined libraries such as those with header files iostream and cstdlib. Moreover, you can define the class itself in two files so that the specification of what the class does is separate from how the class is implemented. If you only change the implementation of the class, then you need only recompile the file with the class implementation. The other files, including the files with the programs that use the class, need not be changed or even recompiled. In this section, we tell you how to carry out this separate compilation of classes.

Encapsulation Reviewed

The principle of encapsulation says that you should separate the specification of how the class is used by a programmer from the details of how the class is implemented. The separation should be so complete that you can change the implementation and any program that uses the class should not need to be changed at all. The way to ensure this separation can be summarized in three rules:

  • Make all the member variables private members of the class.

  • Make each of the basic operations for the class either a public member function of the class, a friend function, an ordinary function, or an overloaded operator. Group the class definition and the function and operator declarations (prototypes) together. This group, along with its accompanying comments, is called the interface for the class. Fully specify how to use each such function or operator in a comment given with the class or with the function or operator declaration.

  • Make the implementation of the basic operations unavailable to the programmer who uses the class. The implementation consists of the function definitions and overloaded operator definitions (along with any helping functions or other additional items these definitions require).

In C++, the best way to ensure that you follow these rules is to place the interface and the implementation of the class in separate files. As you might guess, the file that contains the interface is often called the interface file, and the file that contains the implementation is called the implementation file. The exact details of how to set up, compile, and use these files will vary slightly from one version of C++ to another, but the basic scheme is the same in all versions of C++. In particular, the details of what goes into the files are the same in all systems. The only things that vary are what commands you use to compile and link these files. The details about what goes into these files are illustrated in the next subsection.

A typical class has private member variables. Private member variables (and private member functions) present a problem to our basic philosophy of placing the interface and the implementation of a class in separate files. The public part of the class definition for a class is part of the interface for the class, but the private part is part of the implementation. This is a problem because C++ will not allow you to split the class definition across two files. Thus, some sort of compromise is needed. The only sensible compromise is to place the entire class definition in the interface file. Since a programmer who is using the class cannot use any of the private members of the class, the private members will, in effect, still be hidden from the programmer.

Header Files and Implementation Files

Display 1 contains the interface file for a class called DigitalTime.

Display 1—Interface File for the DigitalTime class

//This is the header file dtime.h. This is the interface for the class DigitalTime.
//Values of this type are times of day. The values are input and output in 24 hour
//notation as in 9:30 for 9:30 AM and 14:45 for 2:45 PM.
#include <iostream>
using namespace std;

class DigitalTime
{
public:
  DigitalTime(int theHour, int theMinute);
  DigitalTime( );
  //Initializes the time value to 0:00 (which is midnight).

  getHour( ) const;
  getMinute( ) const;
  void advance(int minutesAdded);
  //Changes the time to minutesAdded minutes later.

  void advance(int hoursAdded, int minutesAdded);
  //Changes the time to hoursAdded hours plus minutesAdded minutes later.

  friend bool operator ==(const DigitalTime& time1, 
              const DigitalTime& time2);

  friend istream& operator >>(istream& ins, DigitalTime& theObject);

  friend ostream& operator <<(ostream& outs, const DigitalTime& theObject);

private:
 
  int hour;
  int minute;
 
  static void readHour(int& theHour);
  //Precondition: Next input in to be read from the keyboard is 
  //a time in notation, like 9:45 or 14:45.
  //Postcondition: theHour has been set to the hour part of the time. 
  //The colon has been discarded and the next input to be read is the minute.

Display 1 	Interface File for the DigitalTime class (part 2 of 2)

  static void readMinute(int& theMinute);
  //Reads the minute from the keyboard after readHour has read the hour.

  static int digitToInt(char c);
  //Precondition: c is one of the digits '0' through '9'.
  //Returns the integer for the digit; for example, digitToInt('3') returns 3.

};

The private members are part of the implementation, even though they are in the interface file. The label private: warns you that these private members are not part of the public interface. Everything that a programmer needs to know in order to use the class DigitalTime is explained in the comment at the start of the file and in the comments in the public section of the class definition. As noted in the comment at the top of the interface file, this class uses 24-hour notation, so, for instance, 1:30 PM is input and output as 13:30. This and the other details you must know in order to effectively use the class DigitalTime are included in the comments given with the member functions.

We have placed the interface in a file named dtime.h. The suffix .h indicates that this is a header file. An interface file is always a header file and so always ends with the suffix .h. Any program that uses the class DigitalTime must contain an include directive like the following, which names this file:

#include "dtime.h"

When you write an include directive, you must indicate whether the header file is a predefined header file that is provided for you, or is a header file that you wrote. If the header file is predefined, you write the header file name in angular brackets, like <iostream>. If the header file is one that you wrote, then you write the header file name in quotes, like "dtime.h". This distinction tells the compiler where to look for the header file. If the header file name is in angular brackets, the compiler looks wherever the predefined header files are kept in your implementation of C++. If the header file name is in quotes, the compiler looks in the current directory or wherever programmer-defined header files are kept on your system.

Any program that uses our DigitalTime class must contain the above include directive that names the header file dtime.h. That is enough to allow you to compile the program, but is not enough to allow you to run the program. In order to run the program you must write (and compile) the definitions of the member functions and the overloaded operators. We have placed these function and operator definitions in another file, which is called the implementation file. Although it is not required by most compilers, it is tradition to give the interface file and the implementation file the same name. The two files do, however, end in different suffixes. We have placed the interface for our class in the file named dtime.h and the implementation for our class in a file named dtime.cpp. The suffix you use on the implementation file depends on your version of C++. Use the same suffix on the implementation file as you normally use on files that contain C++ programs. (Other common suffixes are .cxx, and .hxx.) The implementation file for our DigitalTime class is given in Display 2.

Display 2—Implementation File

//This is the implementation file: dtime.cpp of the class DigitalTime.
//The interface for the class DigitalTime is in the header file dtime.h.
#include <iostream>
#include <cctype>
#include <cstdlib>
using namespace std;
#include "dtime.h"

//Uses iostream and cstdlib:
DigitalTime::DigitalTime(int theHour, int theMinute)
{
  if (theHour < 0 || theHour > 24 || theMinute < 0 || theMinute > 59)
  {
    cout << "Illegal argument to DigitalTime constructor.";
    exit(1);
  }
  else
  {
    hour = theHour;
    minute = theMinute;
  }

  if (hour == 24)
    hour = 0; //standardize midnight as 0:00
}

DigitalTime::DigitalTime( )
{
  hour = 0;
  minute = 0;
}

int DigitalTime::getHour( ) const
{
  return hour;
}

int DigitalTime::getMinute( ) const
{
  return minute;
}

void DigitalTime::advance(int minutesAdded)
{
  int grossMinutes = minute + minutesAdded;
  minute = grossMinutes%60;

  int hourAdjustment = grossMinutes/60;
  hour = (hour + hourAdjustment)%24;
}

void DigitalTime::advance(int hoursAdded, int minutesAdded)
{
  hour = (hour + hoursAdded)%24;
  advance(minutesAdded);
}

bool operator ==(const DigitalTime& time1, const DigitalTime& time2)
{
  return (time1.hour == time2.hour && time1.minute == time2.minute);
}

//Uses iostream:
ostream& operator <<(ostream& outs, const DigitalTime& theObject)
{
  outs << theObject.hour << ':';
  if (theObject.minute < 10)
    outs << '0';
  outs << theObject.minute;
  return outs;
}

Any file that uses the class DigitalTime must contain the include directive:

#include "dtime.h"

This means that both the implementation file and the program file must contain this include directive that names the interface file. The file that contains the program (that is, the file that contains the main function) is often called the application file or driver file. Display 3 contains an application file with a very simple program that uses and demonstrates the DigitalTime class.

Display 3—Application File Using DigitalTime Class

//This is the application file: timedemo.cpp which demonstrates use of DigitalTime.
#include <iostream>
using namespace std;
#include "dtime.h"

int main( )
{
  DigitalTime clock, oldClock;

  cout << "You may write midnight as either 0:00 or 24:00,\n"
     << "but, I will always write it as 0:00.\n"
     << "Enter the time in 24 hour notation: ";
  cin >> clock;

  oldClock = clock;
  clock.advance(15);
  if (clock == oldClock)
    cout << "Something is wrong.";
  cout << "You entered " << oldClock << endl;
  cout << "15 minutes later the time will be "
     << clock << endl;

  clock.advance(2, 15);
  cout << "2 hours and 15 minutes after that\n"
     << "the time will be "
     << clock << endl;

  return 0;
}
Sample Screen Dialogue
You may write midnight as either 0:00 or 24:00,
but, I will always write it as 0:00.
Enter the time in 24 hour notation: 11:15
You entered 11:15
15 minutes later the time will be 11:30
2 hours and 15 minutes after that
the time will be 13:45

Compiling your program automatically invokes a preprocessor that reads this include directive and replaces this include directive with the text in the file dtime.h. Thus, the compiler sees the contents of dtime.h, and so the file dtime.h does not need to be compiled separately. (In fact, the compiler sees the contents of dtime.h twice: once when you compile the implementation file and once when you compile the application file.) This copying of the file dtime.h is only a conceptual copying. The compiler acts as if the contents of dtime.h were copied into each file that has the include directive. However, if you look in that file after it is compiled, you will only find the include directive; you will not find the contents of the file dtime.h.

Once the implementation file and the application file are compiled, you still need to connect these files so that they can work together. This is called linking the files, and is done by a separate utility called a linker. The details for how you call the linker depends on what system you are using. Often, the command to run a program automatically invokes the linker, so you need not explicitly call the linker at all. After the files are linked, you can run your program.

This sounds like a complicated process, but many systems have facilities that manage much of this detail for you automatically or semiautomatically. On any system, the details quickly become routine. On Unix systems, these details are handled by the make facility. In most IDEs (Integrated Development Environments) these various files are combined into something called a project.

Displays 1, 2, and 3 contain one complete program divided into pieces and placed in three different files. You could instead combine the contents of these three files into one file, and then compile and run this one file without all this fuss about include directives and linking separate files. Why bother with three separate files? There are several advantages to dividing your program into separate files. Since you have the definition and the implementation of the class DigitalTime in files separate from the application file, you can use this class in many different programs without needing to rewrite the definition of the class in each of the programs. Moreover, you need to compile the implementation file only once, no matter how many programs use the class DigitalTime. But there are more advantages than that. Since you have separated the interface from the implementation of your DigitalTime class, you can change the implementation file and will not need to change any program that uses the class. In fact, you will not even need to recompile the program. If you change the implementation file, you only need to recompile the implementation file and to relink the files. Saving a bit of recompiling time is nice, but the big advantage is not having to rewrite code. You can use the class in many programs without writing the class code into each program. You can change the implementation of the class and you need not rewrite any part of any program that uses the class.

The details of the implementation of the class DigitalTime are discussed in the next subsection.

Programming Example: DigitalTime Class

In the previous section, we described how the files in Displays 1, 2, and 3 divide a program into three files, the interface for the class DigitalTime, the implementation of the class DigitalTime, and an application that uses the class. In this section, we discuss the details of the class implementation. There is no new material in this section, but if some of the details in the implementation (Display 2) are not completely clear to you, this section may shed some light on your confusion.

Most of the implementation details are straightforward, but there are two things that merit comment. Notice that the member function name advance is overloaded so that it has two function definitions. Also notice that the definition for the overloaded extraction (input) operator >> uses two "helping functions" called readHour and readMinute, and these two helping functions themselves use a third helping function called digitToInt. Let's discuss these points.

The class DigitalTime (Displays 1, 2) has two member functions called advance. One version takes a single argument; that is, an integer giving the number of minutes to advance the time. The other version takes two arguments, one for a number of hours and one for a number of minutes, and advances the time by that number of hours plus that number of minutes. Notice that the definition of the two-argument version of advance includes a call to the one-argument version of advance. Look at the definition of the two-argument version that is given in Display 2. First, the time is advanced by hoursAdded hours and then the single argument version of advance is used to advance the time by an additional minutesAdded minutes. At first, this may seem strange, but it is perfectly legal. The two functions named advance are two different functions that, as far as the compiler is concerned, just coincidentally happen to have the same name.

Now let's discuss the helping functions. The helping functions readHour and readMinute read the input one character at a time and then convert the input to integer values that are placed in the member variables hour and minute. The functions readHour and readMinute read the hour and minute one digit at a time, so they are reading values of type char. This is more complicated than reading the input as int values, but it allows us to perform error-checking to see whether the input is correctly formed and to issue an error message if the input is not well-formed. These helping functions readHour and readMinute use another helping function named digitToInt. The function digitToInt converts a digit, such as '3', to a number, such as 3.

Programming Tip: Reusable Components

A class developed and coded into separate files is a software component that can be used again and again in a number of different programs. A reusable component saves effort because it does not need to be redesigned, recoded, and retested for every application. A reusable component is also likely to be more reliable than a component that is used only once. It is likely to be more reliable for two reasons. First, you can afford to spend more time and effort on a component if it will be used many times. Second, if the component is used again and again, it is tested again and again. Every use of a software component is a test of that component. Using a software component many times in a variety of contexts is one of the best ways to discover any remaining bugs in the software.

Using #ifndef

We have given you a method for placing a program in three (or more) files: two for the interface and implementation of each class and one for the application part of the program. A program can be kept in more than three files. For example, a program might use several classes and each class might be kept in a separate pair of files. Suppose you have a program spread across a number of files and more than one file has an include directive for a class interface file such as the following:

#include "dtime.h"

Under these circumstances, you can have files that include other files, and these other files may in turn include yet other files. This can easily lead to a situation in which a file, in effect, contains the definitions in dtime.h more than once. C++ does not allow you to define a class more than once, even if the repeated definitions are identical. Moreover, if you are using the same header file in many different projects, it becomes close to impossible to keep track of whether or not you included the class definition more than once. To avoid this problem, C++ provides a way of marking a section of code to say "if you have already included this stuff once before, do not include it again." The way this is done is quite intuitive, although the notation may look a bit weird until you get used to it. We will go through an example, explaining the details as we go.

The following directive defines DTIME_H:

#define DTIME_H

What this means is that the compiler's preprocessor puts DTIME_H on a list to indicate that DTIME_H has been seen. Defined is perhaps not the best word for this, since DTIME_H is not defined to mean anything but merely put on a list. The important point is that you can use another directive to test whether or not DTIME_H has been defined, and so test whether or not a section of code has already been processed. You can use any (nonkeyword) identifier in place of DTIME_H, but you will see that there are standard conventions for which identifier you should use.

The following directive tests to see whether or not DTIME_H has been defined:

#ifndef DTIME_H

If DTIME_H has already been defined, then everything between this directive and the first occurrence of the following directive is skipped:

#endif

(An equivalent way to state this, which may clarify the way the directives are spelled, is the following: If DTIME_H is not defined, then the compiler processes everything up to the next #endif. That is not why there is an n in #ifndef. This may lead you to wonder whether there is a #ifdef directive as well as a #ifndef directive. There is, and it has the obvious meaning, but we will have no occasion to use #ifdef.)

Now consider the code

#ifndef DTIME_H
 #define DTIME_H
 <a class definition>
#endif

If this code is in a file named dtime.h, then no matter how many times your program contains

#include "dtime.h"

the class will be defined only one time.

The first time

#include "dtime.h"

is processed, the flag DTIME_H is defined and the class is defined. Now, suppose the compiler again encounters

#include "dtime.h"

When the include directive is processed this second time, the directive

#ifndef DTIME_H

says to skip everything up to

#endif

and so the class is not defined again.

In Display 4, we have rewritten the header file dtime.h shown in Display 1.

Display 4—Avoiding Multiple Definitions of a Class

//This is the header file dtime.h. This is the interface for the class DigitalTime.
//Values of this type are times of day. The values are input and output in
//24 hour notation as in 9:30 for 9:30 AM and 14:45 for 2:45 PM.

#ifndef DTIME_H
#define DTIME_H

#include <iostream>
using namespace std;

class DigitalTime
{

    <The definition of the class DigitalTime is the same as in Display 1.>

};

#endif //DTIME_H

You may use some other identifier in place of DTIME_H, but the normal convention is to use the name of the file written in all uppercase letters with the underscore used in place of the period. You should follow this convention so that others can more easily read your code and so that you do not have to remember the flag name. This way, the flag name is determined automatically and there is nothing arbitrary to remember.

These same directives can be used to skip over code in files other than header files, but we will not have occasion to use these directives except in header files.

Programming Tip: Defining Other Libraries

You need not define a class in order to use separate compilation. If you have a collection of related functions that you want to make into a library of your own design, you can place the function declarations (prototypes) and accompanying comments in a header file and the function definitions in an implementation file, just as we outlined for classes. After that, you can use this library in your programs the same way you would use a class that you placed in separate files.

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