Home > Articles > Programming > C/C++

  • Print
  • + Share This
This chapter is from the book

3.6 Namespaces

An earlier section ("Storage Classes" on page 124) explains scope rules for variables in C++. Program variables may be:

  1. Local (declared inside functions without static and exist in local stack frames)

  2. External static with file scope (declared outside functions with static)

  3. Global with program scope (declared outside functions without static)

  4. Internal static (declared inside functions with static and exist in the data area)

With program scope (3), separately compiled modules require access to function names, structures, and objects, often placed in global namespace. Global namespace includes all names from global declarations; that is, declarations appearing outside of function definitions. What is the proper way to deal with global namespaces? This problem can be significant, especially with applications and libraries. Let's investigate how namespaces can help.

Why Use Namespaces?

When programmers use separately compiled modules, name conflicts may occur in the global namespace. Consider the following geometry.h include file, for instance.

 // geometry.h
 struct Point { double x, y; };    // global structure name
 double slope(Point, Point);      // global function prototype

The compiler enters the names for the Point structure and slope() function into the global namespace. Suppose a separate geometry.C module contains the slope() implementation and defines origin, a global variable.

 // geometry.C
 #include "geometry.h"

 Point origin = { 0, 0 };        // global variable name
 double slope(Point a1, Point a2)    // function implementation
 { . . . }

Another module mymath.C includes geometry.h. This file contains functions that call slope(), but it also defines its own variable origin as global.

 // mymath.C
 #include "geometry.h"

 Point origin = { 10, 10 };       // link error, name defined twice
 . . .

There are no compilation errors with these modules. At link time, however, errors occur because the global name origin is defined twice. Note that type Point is not the problem here; rather, the global name (origin) can only be seen once by the linker.

We can easily fix the problem by renaming origin in mymath.C.

 Point myorigin = { 10, 10 };    // global variable name 

However, this solution is not always possible or desirable. Renaming origin could affect more than one function defined in mymath.C. With namespaces, we have more choices. Instead of only two options for names (global and nonglobal), we divide a global namespace into separate "named" scopes. This approach lets us access variables from these namespaces with a special syntax.

The following sections show you how to define namespaces, access members of namespaces, and bring namespace variables into local scope. Namespaces also let you create shorthand names (aliases) for longer namespace qualifiers. Namespaces are particularly helpful with resolving name conflicts when you create class libraries. We examine this use of namespaces in "Namespaces and Classes" on page 254.

Namespace Definitions

The keyword namespace defines a namespace.

 namespace name {
  namespace_body
 }

This format creates a namespace with qualifier name. Within the braces, namespace_body may include variables, function definitions and prototypes, structures, classes (see "Classes" on page 177), enums, typedefs, or other namespace definitions (see "Nested Namespaces" on page 139). Note that a namespace definition does not terminate with a semicolon.

Namespace definitions appear in header files and in separate modules with function definitions. Here's an example.

 namespace Red {     // define namespace Red
  int j;        // j is a member of namespace Red
  void print(int i)   // print() is a member of namespace Red
    { cout << "Red::print() = " << i << endl; }
 }

 namespace Blue {     // define namespace Blue
  int j;        // j is a member of namespace Blue
  void print(int);   // print() is a member of namespace Blue
 }

 void sub1() { . . . }  // may access Blue and Red namespaces

 void sub2() { . . . }  // may access Blue and Red namespaces

Namespace Red has two members: integer j and function print(). Namespace Blue has two members with the same names. Normally, these definitions clash in global namespace, but separate namespace qualifiers (Red and Blue) eliminate the problem. Note that a namespace may include function definitions and function prototypes. The function definitions for sub1() and sub2() have access to all of the Red and Blue namespace members, as you will see shortly.

NOTE

Namespace definitions cannot appear inside functions; that is, they must appear outside functions at global scope.

 int sub3() {
  namespace Green {     // error, defined inside function
    char ch;
    char buffer[1024];
  }
  . . .
 }
 

Namespace Extensions

Namespaces are extensible; that is, you can append subsequent declarations to previously defined namespaces. Namespace extensions may also appear in files separate from the original namespace definition. The following two definitions of namespace Blue are equivalent to the definition of namespace BigBlue.

 namespace Blue {      // original namespace definition
  int j;
  void print(int);
 }

 namespace Blue {      // namespace extension
  char ch;
  char buffer[20];
 }
 . . .

 namespace BigBlue {     // equivalent to the above
  int j;
  void print(int);
  char ch;
  char buffer[20];
 }

When you create a namespace, avoid placing include files inside the namespace definition.

 // myfile.C
 namespace math {
 #include "geometry.h"      // not a good idea
  Point origin = { 3, 5 };
  . . .
 }

This approach creates link errors with other modules that do not include geometry.h in the same namespace. Instead, define a namespace in the include file itself, and use namespace extensions for modules that need to add to it.

 // geometry.h
 namespace math {      // define namespace
  struct Point { double x, y; };
  double slope(Point, Point);
 }

 // myfile.C
 #include "geometry.h"
 namespace math {       // namespace extension
  Point origin = { 3, 5 };
  . . .
 }

Accessing Namespace Members

The scope resolution operator (page 67) provides access to namespace members.

 namespace_name::member_name 

namespace_name is a previously defined namespace qualifier, and member_name must be declared inside namespace_name. Here's an example with our Red and Blue namespaces.

 namespace Red {     // define namespace Red
  int j;        // j is a member of namespace Red
  void print(int i)   // print() is a member of namespace Red
    { cout << "Red::print() = " << i << endl; }
 }

 namespace Blue {     // define namespace Blue
  int j;        // j is a member of namespace Blue
  void print(int);   // print() is a member of namespace Blue
 }

 void Blue::print(int k) {
  cout << "Blue::print() = " << k << endl;
 }

Outside the Blue namespace definition, the scope resolution operator associates print() with namespace Blue. Without it, the compiler defines print() as a global function. Here are several more examples with variables and function calls.

 void sub() {
  Red::j = 0;           // member of namespace Red
  Red::print(5);          // member of namespace Red
  j = 5;              // illegal, no local j defined
  int j = 10;           // legal, j is a local variable
  Blue::j = 5;           // member of namespace Blue
 }

Inside sub(), the scope operator qualifies the first assignment to j and the call to print() from namespace Red. The last assignment uses j from namespace Blue. Without the scope operator and a namespace qualifier, the compiler reports an error in the second assignment. Note that we may declare and initialize a local j inside sub() without any conflict from namespace Red or Blue.

Unnamed Namespaces

A variable or function defined outside function definitions with the specifier static creates a name in file scope; that is, an external static known only within the file where it's declared (see "static" on page 125). External statics do not conflict with the same names defined in different translation units at link time. (A translation unit is a source code file with include files after preprocessing.) Unnamed namespaces make external statics obsolete in ANSI C++. Here's the format.

 namespace {
  namespace_body
 }

A left brace immediately follows the keyword namespace without an intervening name qualifier. All members defined in namespace_body are in an unnamed namespace that is guaranteed to be unique for each translation unit. At link time, member names in one unnamed namespace do not conflict with equivalent member names from other unnamed namespaces in separate translation units.

The following example shows why unnamed namespaces are useful.

 namespace {                // unnamed namespace
  const int Max = 20;
  int buffer[Max];
  int counter;
 }

 void sub1() {
  counter = 0;              // counter in unnamed namespace
  for (int i = 0; i < Max; i++)     // Max in unnamed namespace
    buffer[i] = i*2;          // buffer in unnamed namespace
  . . .
 }

Unnamed namespaces permit access to Max, buffer, and counter without the scope resolution operator. An unnamed namespace also solves our linkage problem in mymath.C (page 134).

 // mymath.C
 #include "geometry.h"

 namespace {
  Point origin = { 10, 10 };          // no conflict with geometry.h
 }
 . . .

Unnamed namespace extensions are possible, but only within the same translation unit.

 // file.C
 namespace {         // unnamed namespace
  int j;
  void print(int);     // prototype
 }

 namespace {         // same unnamed namespace
  void print(int i) { cout << i << endl; }
 }

 void sub() {
  j = 3;
  print(j);        // no ambiguity
 }

Inside file.C, the prototype and definition for print() are members of the same unnamed namespace. The second unnamed namespace extension surrounding the print() definition is important because it tells the compiler that print() is not global. Without it, calls to print() are ambiguous because the compiler cannot distinguish between a global function name and a member of an unnamed namespace.

NOTE

With unnamed namespaces, make sure your function implementations are either inside the namespace definition directly or a member of an unnamed namespace extension in the same translation unit.

Here's another example that shows you how global variable scope differs from unnamed namespace scope.

 namespace {            // unnamed namespace
  const int Max = 20;
  char buffer[Max];
  int counter;
 }

 int counter = 1;          // legal - global variable

 void sub2() {
  counter++;           // illegal - ambiguous (global or unnamed)?
  ::counter = 5;         // legal - global
  int counter = 0;        // legal - hides global and unnamed member
  counter = 10;          // legal - local variable
  . . .
 }

Inside sub2(), counter++ is ambiguous because the compiler cannot distinguish between a global name and an unnamed member with the same name. Furthermore, the scope resolution operator without a namespace qualifier (::counter) refers to a global name, not an unnamed member. It's also possible to declare a local counter name, but be careful with this technique. Here, the local counter hides both the global counter and the unnamed member.

NOTE

Unnamed namespaces restrict global variables to file scope. Use unnamed namespaces in place of external static. Don't use :: to refer to unnamed members, and don't mix globals with unnamed members if they have the same name.

Nested Namespaces

Namespace definitions are illegal inside functions, but they may appear inside other namespace definitions. This approach nests namespaces for better data hiding. Here's an example.

 namespace Outer {              // namespace definition
  int i, j;
  namespace Inner {            // nested namespace
    const int Max = 20;
    char ch;
    char buffer[Max];
    void print();
  }
 }

For proper access to members of a nested namespace, the scope resolutions operator (::) becomes very important.

 void Outer::Inner::print() {
  for (int i = 0; i < Max; i++)        // i is local to for loop
    cout << buffer[i] << ' ';
  cout << endl;
 }

Two levels of scope resolution are necessary to define the print() function of Inner. Note that we can access ch, buffer, and Max without the scope operator inside print().

The following sub() function shows more examples of accessing members of Outer and its nested Inner namespace.

 void sub() {
  Outer::i = 10;
  Outer::Inner::ch = 'a';
  for (int i = 0; i < Outer::Inner::Max; i++)    // i is local
    Outer::Inner::buffer[i] = Outer::Inner::ch + i;
  Outer::Inner::print();
  cout << "Max = " << Outer::Inner::Max << endl;
 }

Using Directives

Accessing namespace members can be cumbersome, especially with long namespace qualifiers and nested namespaces. Fortunately, there are several ways to bypass namespace qualifiers and make access to namespace members more convenient. Using directives provide access to all namespace members without a namespace qualifier and the scope operator. Here is the format.

 using namespace name; 

The qualifier name following the keywords using and namespace must be a previously defined namespace. Using directives may appear at global scope and local scope (inside blocks, functions, and namespace definitions).

Global Using Directives

Let's return to our Blue namespace to show you a using directive at global scope.

 namespace Blue {          // define namespace Blue
  int j;              // j is a member of namespace Blue
  void print(int);         // print() is a member of namespace Blue
 }

 using namespace Blue;        // global using directive

 void sub1() {
  j = 0;              // legal - Blue::j
  print(j);            // legal - Blue::print()
  . . .
 }

 void sub2() {
  j = 1;             // legal - Blue::j
  print(j);            // legal - Blue::print()
  . . .
 }

The global using directive provides access to j and print() from namespace Blue without a qualifier and without the scope operator. Note that j in sub1() and sub2() are not local variables.

NOTE

Be careful with local variables in functions that hide namespace members.

 void sub3() {
  j = 2;          // legal - Blue::j
  print(j);         // legal - Blue::print()

  int j = 10;        // legal - local j hides Blue::j
  Blue::j = 5;       // must qualify
  . . .
 }
 

A local declaration for j hides the Blue namespace member. Consequently, a qualification is necessary to access j from namespace Blue.

Local Using Directives

Local using directives appear inside blocks, functions, and namespace definitions. Here's an example of a function with a local using directive.

 namespace Blue {         // define namespace Blue
  int j;             // j is a member of namespace Blue
  void print(int);        // print() is a member of namespace Blue
 }

 void sub1() {
  using namespace Blue;     // local using directive
  j = 0;             // legal - Blue::j
  print(j);           // legal - Blue::print()
  . . .
 }

 void sub2() {
  j = 1;             // illegal - j not defined
  print(j);           // illegal - print() not defined
  . . .
 }

The local using directive provides access to j and print() from namespace Blue only within sub1(). Inside sub2(), j and print() generate compilation errors because no local using directive provides access.

NOTE

The scope of a local using directive is valid only inside the block where it appears.

Potential conflicts may occur with global and local using directives when members of different namespaces have the same name or match global names. The compiler flags the ambiguity when you use the name, not at the using directive. Here's an example with local using directives.

 namespace Black {             // define namespace Black
  int j;
  void print(int);
  char ch;
 }

 namespace White {             // define namespace White
  int j;
  void print(int);
  double vision;
 }

 int j;                  // global j

 void sub3() {
  using namespace Black;         // local using directive for Black
  using namespace White;         // local using directive for White
  j = 0;                 // illegal - Black::j, White::j, or ::j?
  print(5);               // illegal - Black or White print()?
  ch = 'a';               // legal - Black::ch
  vision = 7.65;             // legal - White::vision

  int j = 10;              // local j, hides all others
  ::j = 5;                // legal - global j
  White::j = 5;             // legal - White::j from White
  Black::print(j);            // legal - Black::print(), local j
 }

The local using directives for namespaces Black and White make unqualified access to j and print() ambiguous. Access to variables ch and vision are not ambiguous, however. Note that the local j in sub3() makes qualification necessary to access the global j and the j member in White.

Local using directives are also legal inside namespace definitions. These using directives are transitive, as shown in the following example.

 namespace Black {          // define namespace Black
  int j;
  void print(int);
  char ch;
 }

 namespace Gray {          // define namespace Gray
  using namespace Black;      // local using directive
  int j;              // separate from Black::j
  double talk;
 }

 namespace Black {          // namespace extension
  bool contrast;
 }

 void sub3() {
  using namespace Gray;      // local using directive
  print(5);            // legal - Black::print()
  ch = 'a';            // legal - Black::ch
  talk = 5.67;           // legal - Gray::talk
  j = 22;             // illegal - Black::j or Gray::j?
  Black::j = 22;          // legal - Black::j
  contrast = true;         // legal - Black::contrast
  . . .
 }

Namespace Gray contains a local using directive for namespace Black, making Black members j, print(), and ch available inside Gray. Note that Gray::j and Black::j are separate namespace members. Without a qualification inside sub3(), the compiler reports ambiguity errors in the assignment to j.

A namespace extension adds contrast to the Black namespace, but contrast is not accessible inside Gray. All of Black's members are accessible in sub3() because the namespace extension for Black appears before the local using directive.

Using Declarations

Using directives make all namespace members accessible without qualification. In contrast, using declarations qualify only individual namespace members. Using declarations are declarations and, as such, create declarations in the current scope. Here is the format.

 using namespace_name::member_name; 

The previously defined namespace qualifier namespace_name follows the keyword using. member_name must be declared inside namespace_name. Using declarations may appear at global scope and local scope (inside blocks, functions, and namespace definitions).

Here are several examples of using declarations.

 namespace Black {           // define namespace Black
  int j;
  void print(int);
  char ch;
 }

 namespace White {           // define namespace White
  int j;
  void print(int);
  double vision;
 }
 using White::vision;         // global using declaration

 void sub1() {
  using Black::print;        // local using declaration
  ch = 'a';             // illegal - ch not defined
  vision = 7.65;           // legal - White::vision
  print(5);             // legal - Black::print()
  . . .
 }

 void sub2() {
  print(5);             // illegal - print() not defined
  vision = 3.45;          // legal - White::vision
  . . .
 }

A global using declaration for White::vision makes this namespace member accessible to both sub1() and sub2() without qualification. The local using declaration brings Black::print() into local scope for only sub1(). Invoking print(5), therefore, calls Black::print(5) in sub1() but is illegal in sub2().

NOTE

Be careful when mixing using directives and using declarations in the same scope.

 void sub3() {
  using namespace White;         // local using directive
  using Black::print;          // local using declaration
  print(5);               // legal - Black::print()
  j = 2;                 // legal - White::j
  using Black::j;            // local using declaration
  j = 3;                 // legal - Black::j;
  int j = 10;              // illegal - j already defined
  . . .
 }

The local using directive inside sub3() makes all of White's members accessible. The local using declaration makes print() the only member accessible from Black. The assignment j=2 uses White::j because Black::j is not in local scope at this point. When we bring Black::j into local scope with a using declaration, subsequent assignments modify the j member in Black. The declaration for j is illegal because it is already in local scope.

Using declarations are also convenient with libraries from different sources. Consider the following math_lib and geo_lib namespaces, which both define Point but have different initial values for their origin members.

 namespace math_lib {           // Math Library
  struct Point { double x, y; };
  Point origin = { 0, 0 };
  double slope(Point, Point);
  double max(double a, double b);
  int max(int a, int b);
 }

 namespace geo_lib {           // Geometry Library
  struct Point { double x, y; };
  struct Line { . . . };
  struct Angle { . . . };
  Point origin = { 10, 10 };
 }

Using declarations specify which namespace members a sub1() function may access.

 math_lib::Point origin = { 5, 5 };      // global declaration

 void sub1() {
  using math_lib::Point;           // Point from math_lib
  using geo_lib::Line;            // Line from geo_lib
  using geo_lib::origin;           // origin from geo_lib
  using math_lib::slope;           // slope() from math_lib
  using math_lib::origin ;          // error, multiple declaration

  cout << origin.x << endl;         // legal - geo_lib::origin
  cout << ::origin.x << endl;        // legal - global origin
  . . .
 }

The global declaration for origin uses type Point from math_lib. Inside sub1(), local using declarations specify which members we want from each namespace. The using declaration for math_lib::origin is illegal because origin is already in local scope from namespace geo_lib. Note that the scope operator is necessary to access the global origin in the last cout statement. Otherwise, we refer to the origin member in geo_lib.

NOTE

Using declarations specify names without type information. The following using declaration, for instance, brings both max() functions from namespace math_lib into the local scope of sub2().

 void sub2() {
  using math_lib::max;            // all max functions
  cout << max(10, 20) << endl;        // max(int, int)
  cout << max(5.6, 7.8) << endl;       // max(double, double)
 }

When more than one function has the same name, all functions with that name are brought into local scope (see "Overloading and Namespaces" on page 286).

Namespace Aliases

Namespace aliases create synonym names for namespaces. You'll want to use aliases when a namespace has a long name. Here's the format.

 namespace alias_name = namespace_name; 

Follow the keyword namespace with your alias (alias_name). namespace_name must be a previously defined namespace. You can use more than one alias for the same namespace qualifier, but you can't alias an existing alias. Aliases apply only to the translation unit where they appear; the linker sees the original name.

Namespace aliases are convenient shorthand names.

 namespace A_Very_Long_Library_Name {
  struct Point { double x, y; };
  Point origin = { 10, 10 };
 }

 namespace ALN = A_Very_Long_Library_Name;   // alias

 void sub() {
  using ALN::Point;              // using declaration
  Point first = ALN::origin;         // namespace member
  . . .
 }

Namespace aliases may appear in using directives, using declarations, and qualified namespace members.

Namespaces with Program Development

Let's put namespaces to work in a complete program. The following geometry.h header file defines a namespace for a geometry library.

Listing 3.14 geometry.h definitions

 #ifndef GEOMETRYH
 #define GEOMETRYH
 // geometry.h - geometry definitions

 namespace Geometry {       // namespace definition
  struct Point {
    double x, y;
  };
  double slope(Point, Point);
 }
 #endif

Namespace Geometry includes a Point type and a slope() function. Additional definitions appear in geometry.C.

Listing 3.15 geometry.C implementations

 // geometry.C - geometry implementations
 #include "geometry.h"

 namespace Geometry {       // namespace extension
  Point origin = { 0, 0 };
 }

 double Geometry::slope(Point a1, Point a2) {
  double dy = a2.y - a1.y;
  double dx = a2.x - a1.x;
  if (dx == 0)
    throw "slope(): undefined slope";
  return dy / dx;
 }

A namespace extension adds an origin member to Geometry. The slope() function calculates slopes from Point values and throws character string exceptions if the slope denominator is zero.

Here's an application that uses this Geometry namespace to calculate slopes for Point variables.

Listing 3.16 mymath3.C — geometry application

 // mymath3.C - namespaces with program development
 #include <iostream.h>
 #include "geometry.h"

 namespace Geo = Geometry;      // alias

 using Geo::Point;          // using declaration
 using Geo::slope;          // using declaration

 namespace {             // unnamed namespace
  Point origin = { 10, 10 };
 }

 int main()
 {
  try {
    Point a = { 3, 5 };
    Point b = { 6, 10 };
    cout << "Line a_b has slope " << slope(a, b) << endl;
    cout << "Line origin_a has slope " << slope(origin, a) << endl;
  }
  catch (char *msg) {        // catch handler
    cout << msg << endl;
    return 1;
  }
  return 0;
 }

 $ CC mymath3.C geometry.C -o mymath3
 $ mymath3
 Line a_b has slope 1.66667
 Line origin_a has slope 0.714286

The program creates a Geo alias for the Geometry namespace qualifier. Global using declarations use alias Geo to bring Point and slope() from the Geometry namespace to global scope. An unnamed namespace defines a global origin that does not conflict with the origin member in Geometry. Inside the try block, we define Point variables a and b before calculating their slopes. The catch handler displays error messages from character string exceptions thrown by slope().

  • + Share This
  • 🔖 Save To Your Account

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