9   Classes                                          [class]


1 A class is a type.  Its  name  becomes  a  class-name  (_class.name_),
  within its scope.
  Class-specifiers  and elaborated-type-specifiers (_dcl.type.elab_) are
  used to make class-names.  An object of a class consists of a  (possi­
  bly empty) sequence of members and base class objects.
                  class-head { member-specificationopt }
                  class-key identifieropt base-clauseopt
                  class-key nested-name-specifier identifier base-clauseopt

2 The  name of a class can be used as a class-name even within the base-
  clause and member-specification of  the  class  specifier  itself.   A
  class-specifier  is  commonly  referred  to  as a class definition.  A
  class is considered defined after the  closing  brace  of  its  class-
  specifier  has  been seen even though its member functions are in gen­
  eral not yet defined.

3 Objects of an empty class have a nonzero size.

  +-------                 BEGIN BOX 1                -------+
  Bill Gibbons suggest that a base class subobject should be allowed  to
  occupy  zero bytes of the complete object.  This would permit two base
  class subobjects to have the same address, for example.
  +-------                  END BOX 1                 -------+

4 Class objects may be assigned, passed as arguments to  functions,  and
  returned by functions (except objects of classes for which copying has
  been restricted; see _class.copy_).  Other plausible  operators,  such
  as equality comparison, can be defined by the user; see _over.oper_.

5 A structure is a class declared with the class-key struct; its members
  and   base   classes   (_class.derived_)   are   public   by   default
  (_class.access_).   A  union  is  a  class declared with the class-key
  union; its members are public by default and it holds only one  member

  at a time (_class.union_).

  9.1  Class names                                          [class.name]

1 A class definition introduces a new type.  For example,
          struct X { int a; };
          struct Y { int a; };
          X a1;
          Y a2;
          int a3;
  declares three variables of three different types.  This implies that
          a1 = a2;        // error: Y assigned to X
          a1 = a3;        // error: int assigned to X
  are type mismatches, and that
          int f(X);
          int f(Y);
  declare  an  overloaded  (_over_) function f() and not simply a single
  function f() twice.  For the same reason,
          struct S { int a; };
          struct S { int a; };  // error, double definition
  is ill-formed because it defines S twice.

2 A class definition introduces the class name into the scope  where  it
  is defined and hides any class, object, function, or other declaration
  of that name in an enclosing scope (_basic.scope_).  If a  class  name
  is declared in a scope where an object, function, or enumerator of the
  same name is also declared, then when both declarations are in  scope,
  the  class  can be referred to only using an elaborated-type-specifier
  (_dcl.type.elab_).  For example,
          struct stat {
              // ...
          stat gstat;             // use plain `stat' to
                                  // define variable

          int stat(struct stat*); // redefine `stat' as function
          void f()
              struct stat* ps;    // `struct' prefix needed
                                  // to name struct stat
              // ...
              stat(ps);           // call stat()
              // ...
  A declaration consisting solely of class-key identifier ; is either  a
  redeclaration  of  the name in the current scope or a forward declara­
  tion of the identifier as a class name.  It introduces the class  name
  into the current scope.  For example,

          struct s { int a; };

          void g()
              struct s;               // hide global struct `s'
              s* p;                   // refer to local struct `s'
              struct s { char* p; };  // declare local struct `s'
              struct s;               // receclaration, has no effect
  Such  declarations  allow  definition  of  classes  that refer to each
  other.  For example,
          class vector;

          class matrix {
              // ...
              friend vector operator*(matrix&, vector&);
          class vector {
              // ...
              friend vector operator*(matrix&, vector&);
  Declaration of friends is described in _class.friend_, operator  func­
  tions in _over.oper_.

3 An elaborated-type-specifier (_dcl.type.elab_) can also be used in the
  declarations of objects and functions.  It differs from a class decla­
  ration in that if a class of the elaborated name is in scope the elab­
  orated name will refer to it.  For example,
          struct s { int a; };

          void g(int s)
              struct s* p = new struct s;    // global `s'
              p->a = s;                      // local `s'

4 A name declaration takes effect immediately after  the  identifier  is
  seen.  For example,
          class A * A;
  first  specifies  A to be the name of a class and then redefines it as
  the name of a pointer to an object of that class.  This means that the
  elaborated  form  class  A  must  be used to refer to the class.  Such
  artistry with names can be confusing and is best avoided.

5 A typedef-name (_dcl.typedef_) that names a class is a class-name, but
  shall   not   be   used  in  an  elaborated-type-specifier;  see  also

  9.2  Class members                                         [class.mem]
                  member-declaration member-specificationopt
                  access-specifier : member-specificationopt

                  decl-specifier-seqopt member-declarator-listopt ;
                  function-definition ;opt
                  qualified-id ;
                  member-declarator-list , member-declarator
                  declarator pure-specifieropt
                  declarator constant-initializeropt
                  identifieropt : constant-expression
                   = 0
                   = constant-expression

1 The member-specification in a class definition declares the  full  set
  of members of the class; no member can be added elsewhere.  Members of
  a class are data  members,  member  functions  (_class.mfct_),  nested
  types,  and  member  constants.  Data members and member functions are
  static or nonstatic; see _class.static_.   Nested  types  are  classes
  (_class.name_,  _class.nest_) and enumerations (_dcl.enum_) defined in
  the class, and arbitrary types declared as members by use of a typedef
  declaration   (_dcl.typedef_).   The  enumerators  of  an  enumeration
  (_dcl.enum_) defined in the class are member constants of  the  class.
  Except  when used to declare friends (_class.friend_) or to adjust the
  access to a member  of  a  base  class  (_class.access.dcl_),  member-
  declarations  declare  members  of  the  class,  and each such member-
  declaration must declare at least one member name  of  the  class.   A
  member  may  not be declared twice in the member-specification, except
  that a nested class may be declared and then later defined.

2 Note that a single name can denote several function  members  provided
  their types are sufficiently different (_over_).

3 A  member-declarator  can  contain  a  constant-initializer only if it
  declares a static member (_class.static_) of integral  or  enumeration
  type.   In  that  case,  the  member  can  appear in integral constant
  expressions (_expr.const_) within its  declarative  region  after  its
  declaration.   The  member  must  still  be  defined elsewhere and the
  declarator that defines the member shall not contain an initializer.

4 A member can be initialized using a constructor; see _class.ctor_.

5 A member may not be auto, extern, or register.

6 The decl-specifier-seq can be omitted in constructor, destructor,  and
  conversion function declarations only.  The member-declarator-list can
  be omitted only after a class-specifier, an enum-specifier, or a decl-
  specifier-seq  of  the form friend elaborated-type-specifier.  A pure-
  specifier may be used only in the declaration of  a  virtual  function

7 Non-static  (_class.static_)  members  that  are class objects must be
  objects of previously declared classes.  In particular, a class cl may
  not  contain  an  object  of class cl, but it may contain a pointer or
  reference to an object of class cl.  When an array is used as the type
  of a nonstatic member all dimensions must be specified.

8 A simple example of a class definition is
          struct tnode {
              char tword[20];
              int count;
              tnode *left;
              tnode *right;
  which  contains  an  array  of  twenty characters, an integer, and two
  pointers to similar structures.  Once this definition has been  given,
  the declaration
          tnode s, *sp;
  declares  s  to  be  a  tnode and sp to be a pointer to a tnode.  With
  these declarations, sp->count refers to the count member of the struc­
  ture  to which sp points; s.left refers to the left subtree pointer of
  the structure s; and s.right->tword[0] refers to the initial character
  of the tword member of the right subtree of s.

9 Nonstatic  data  members  of  a  class declared without an intervening
  access-specifier are allocated  so  that  later  members  have  higher
  addresses within a class object.  The order of allocation of nonstatic
  data members separated by an access-specifier is implementation depen­
  dent (_class.access.spec_).  Implementation alignment requirements may
  cause two adjacent members not to be allocated immediately after  each
  other;  so  may  requirements for space for managing virtual functions
  (_class.virtual_) and virtual  base  classes  (_class.mi_);  see  also

10If  two  types T1 and T2 are the same type, then T1 and T2 are layout-
  compatible types.

11Two POD-struct (_dcl.init.aggr_) types are layout-compatible  if  they
  have  the same number of members, and corresponding members (in order)
  have layout-compatible types.

12Two POD-union (_dcl.init.aggr_) types are  layout-compatible  if  they
  have  the  same  number  of members, and corresponding members (in any
  order) have layout-compatible types.

  +-------                 BEGIN BOX 2                -------+
  Shouldn't this be the same set of types?
  +-------                  END BOX 2                 -------+

13Two enumeration types are layout-compatible if they have the same sets
  of enumerator values.

  +-------                 BEGIN BOX 3                -------+
  Shouldn't this be the same underlying type?

  +-------                  END BOX 3                 -------+

14If  a  POD-union contains several POD-structs that share a common ini­
  tial sequence, and if the POD-union object currently contains  one  of
  these  POD-structs, it is permitted to inspect the common initial part
  of any of them.  Two POD-structs share a common  initial  sequence  if
  corresponding  members  have  layout-compatible  types  (and, for bit-
  fields, the same widths) for a sequence of one or  more  initial  mem­

15A  pointer  to  a POD-struct object, suitably converted, points to its
  initial member (or if that member is a bit-field, then to the unit  in
  which  it  resides)  and  vice  versa.  There may therefore be unnamed
  padding within a POD-struct object, but not at its beginning, as  nec­
  essary to achieve appropriate alignment.

16The  range  of  nonnegative values of a signed integral type is a sub­
  range of the corresponding unsigned integral type, and the representa­
  tion of the same value in each type is the same.

17Even if the implementation defines two or more basic types to have the
  same representation, they are nevertheless different types.

18The representations of integral types shall define values by use of  a
  pure binary numeration system.

  +-------                 BEGIN BOX 4                -------+
  Does this mean two's complement?  Is there a definition of pure binary
  numeration system?
  +-------                  END BOX 4                 -------+

19The qualified or unqualified versions of a  type  are  distinct  types
  that have the same representation and alignment requirements.

20A  qualified  or  unqualified void* shall have the same representation
  and alignment requirements as a qualified or unqualified char*.

21Similarly, pointers to qualified or unqualified  versions  of  layout-
  compatible  types  shall  have  the  same representation and alignment

22If the program attempts to  access  the  stored  value  of  an  object
  through an lvalue of other than one of the following types:

  --the dynamic type of the object,

  --a qualified version of the declared type of the object,

  --a  type  that  is  the  signed or unsigned type corresponding to the
    declared type of the object,

  --a type that is the  signed  or  unsigned  type  corresponding  to  a

    qualified version of the declared type of the object,

  --an  aggregate  or union type that includes one of the aforementioned
    types among its members (including, recursively, a member of a  sub­
    aggregate or contained union), or

  --a character type.1) the result is undefined.

23A function member (_class.mfct_) with the same name as its class is  a
  constructor  (_class.ctor_).  A static data member, enumerator, member
  of an anonymous union, or nested type may not have the  same  name  as
  its class.

  9.3  Scope rules for classes                            [class.scope0]

1 The following rules describe the scope of names declared in classes.

    1)The  scope  of a name declared in a class consists not only of the
      text following the name's declarator, but  also  of  all  function
      bodies,  default  arguments,  and constructor initializers in that
      class (including such things in nested classes).

    2)A name N used in a class S must refer to the same declaration when
      re-evaluated in its context and in the completed scope of S.

    3)If  reordering  member declarations in a class yields an alternate
      valid program under (1) and (2), the program's  meaning  is  unde­

    4)A  declaration  in a nested declarative region hides a declaration
      whose declarative region contains the nested declarative region.

    5)A declaration within a member function hides a  declaration  whose
      scope extends to or past the end of the member function's class.

    6)The  scope  of  a declaration that extends to or past the end of a
      class definition also extends to the regions defined by its member
      definitions,  even  if  defined  lexically outside the class (this
      includes both function member bodies  and  static  data  member  i

2   For example:
              typedef int  c;
              enum { i = 1 };

  1)  The intent of this list is to specify those circumstances in which
  an object may or may not be aliased.

              class X {
                  char  v[i];  // error: 'i' refers to ::i
                               // but when reevaluated is X::i
                  int  f() { return sizeof(c); }  // okay: X::c
                  char  c;
                  enum { i = 2 };
              typedef char*  T;
              struct Y {
                  T  a;    // error: 'T' refers to ::T
                           // but when reevaluated is Y::T
                  typedef long  T;
                  T  b;
              struct Z {
                  int  f(const R);  // error: 'R' is parameter name
                                    // but swapping the two declarations
                                    // changes it to a type
                  typedef int  R;

    9.4  Member functions                                   [class.mfct]

1   A  function  declared  as  a  member  (without the friend specifier;
    _class.friend_) is called a member function, and is  called  for  an
    object using the class member syntax (_expr.ref_).  For example,
              struct tnode {
                  char tword[20];
                  int count;
                  tnode *left;
                  tnode *right;
                  void set(char*, tnode* l, tnode* r);
    Here set is a member function and can be called like this:
              void f(tnode n1, tnode n2)

2   The  definition  of a member function is considered to be within the
    scope of its class.  This  means  that  (provided  it  is  nonstatic
    _class.static_)  it  can use names of members of its class directly.
    Such names then refer to the members of the  object  for  which  the
    function was called.

3   A  static  local  variable in a member function always refers to the
    same object.  A static member function can use  only  the  names  of
    static members, enumerators, and nested types directly.  If the def­
    inition of a member function is lexically outside the class  defini­
    tion,  the  member function name must be qualified by the class name
    using the :: operator.  For example,

              void tnode::set(char* w, tnode* l, tnode* r)
                  count = strlen(w+1);
                  if (sizeof(tword)<=count)
                      error("tnode string too long");
                  left = l;
                  right = r;
    The notation tnode::set specifies that the function set is a  member
    of  and in the scope of class tnode.  The member names tword, count,
    left, and right refer to members of the object for which  the  func­
    tion  was  called.   Thus,  in  the  call n1.set("abc",&n2,0), tword
    refers to n1.tword, and in the call n2.set("def",0,0) it  refers  to
    n2.tword.   The functions strlen, error, and strcpy must be declared

4   Members may be defined (_basic.def_) outside their class  definition
    if they have already been declared but not defined in the class def­
    inition; they may not be redeclared.  See also _basic.link_.   Func­
    tion  members  may  be  mentioned in friend declarations after their
    class has been defined.  Each member function that  is  called  must
    have  exactly one definition in a program, (no diagnostic required).

5   The effect of calling a nonstatic member  function  (_class.static_)
    of a class X for something that is not an object of class X is unde­

    9.4.1  The this pointer                                 [class.this]

1   In a nonstatic (_class.mfct_) member function, the keyword this is a
    non-lvalue  expression  whose value is the address of the object for
    which the function is called.  The type of this in a member function
    of  a  class X is X* unless the member function is declared const or
    volatile; in those cases, the type of this is const X*  or  volatile
    X*, respectively.  A function declared const and volatile has a this
    with the type const volatile X*.  See also _diff.this_.   For  exam­
              struct s {
                  int a;
                  int f() const;
                  int g() { return a++; }
                  int h() const { return a++; } // error

              int s::f() const { return a; }
    The a++ in the body of s::h is ill-formed because it tries to modify
    (a part of) the object for which s::h()  is  called.   This  is  not
    allowed in a const member function where this is a pointer to const,
    that is, *this is a const.

2   A const member function (that is, a member  function  declared  with
    the  const qualifier) may be called for const and non-const objects,
    whereas a non-const member function may be called only  for  a  non-

    const object.  For example,
              void k(s& x, const s& y)
                  y.g();      // error
    The call y.g() is ill-formed because y is const and s::g() is a non-
    const member function that could (and does) modify  the  object  for
    which it was called.

3   Similarly,  only  volatile member functions (that is, a member func­
    tion declared with  the  volatile  specifier)  may  be  invoked  for
    volatile objects.  A member function can be both const and volatile.

4   Constructors (_class.ctor_) and destructors  (_class.dtor_)  may  be
    invoked for a const or volatile object.  Constructors (_class.ctor_)
    and destructors (_class.dtor_) cannot be declared const or volatile.

    9.4.2  Inline member functions                        [class.inline]

1   A  member function may be defined (_dcl.fct.def_) in the class defi­
    nition, in which case it is  inline  (_dcl.fct.spec_).   Defining  a
    function  within  a  class  definition is equivalent to declaring it
    inline and defining it immediately after the class definition;  this
    rewriting  is  considered  to be done after preprocessing but before
    syntax analysis and type checking of the function definition.  Thus
              int b;
              struct x {
                  char* f() { return b; }
                  char* b;
    is equivalent to
              int b;
              struct x {
                  inline char* f();
                  char* b;

              inline char* x::f() { return b; } // moved
    Thus the b used in x::f() is X::b and not the global  b.   See  also

2   Member  functions can be defined even in local or nested class defi­
    nitions where this rewriting would be syntactically incorrect.   See
    _class.local_ for a discussion of local classes and _class.nest_ for
    a discussion of nested classes.

    9.5  Static members                                   [class.static]

1   A data or function member of a class may be declared static  in  the
    class  definition.   There is only one copy of a static data member,
    shared by all objects of the class and  any  derived  classes  in  a

    program.  A static member is not part of objects of a class.  Static
    members of a global class have external linkage (_basic.link_).  The
    declaration of a static data member in its class definition is not a
    definition and may be  of  an  incomplete  type.   A  definition  is
    required elsewhere; see also _diff.anac_.  A static data member can­
    not be mutable.

2   A static member function does not have a  this  pointer  so  it  can
    access  nonstatic  members  of  its  class only by using . or ->.  A
    static member function cannot be virtual.  There cannot be a  static
    and  a  nonstatic  member  function  with the same name and the same
    parameter types.

3   Static members of a local class (_class.local_) have no linkage  and
    cannot  be  defined outside the class definition.  It follows that a
    local class cannot have static data members.

4   A static member mem of class  cl  can  be  referred  to  as  cl::mem
    (_expr.prim_), that is, independently of any object.  It can also be
    referred to using the . and -> member access operators (_expr.ref_).
    The  static  member  mem  exists even if no objects of class cl have
    been created.  For example, in the following, run_chain,  idle,  and
    so on exist even if no process objects have been created:
              class process {
                  static int no_of_processes;
                  static process* run_chain;
                  static process* running;
                  static process* idle;
                  // ...
                  // ...
                  int state();
                  static void reschedule();
                  // ...
    and reschedule can be used without reference to a process object, as
              void f()

5   Static members of a global class are initialized exactly like global
    objects and only in file scope.  For example,
              void process::reschedule() { /* ... */ };
              int process::no_of_processes = 1;
              process* process::running = get_main();
              process* process::run_chain = process::running;
    Static   members   obey   the   usual   class  member  access  rules
    (_class.access_) except  that  they  can  be  initialized  (in  file
    scope).   The initializer of a static member of a class has the same
    access rights as a member function, as in process::run_chain  above.

6   The  type  of  a static member does not involve its class name; thus
    the type of process :: no_of_processes is int and the type of  &pro­
    cess :: reschedule is void(*)().

    9.6  Unions                                            [class.union]

1   A  union may be thought of as a class whose member objects all begin
    at offset zero and whose size is sufficient to contain  any  of  its
    member  objects.  At most one of the member objects can be stored in
    a union at any time.  A union may have member  functions  (including
    constructors  and  destructors),  but  not virtual (_class.virtual_)
    functions.  A union may not have base classes.  A union may  not  be
    used  as a base class.  An object of a class with a constructor or a
    destructor or a user-defined assignment operator (_over.ass_) cannot
    be a member of a union.  A union can have no static data members.

  +-------                 BEGIN BOX 5                -------+
    Shouldn't we prohibit references in unions?
  +-------                  END BOX 5                 -------+

2   A union of the form
              union { member-specification } ;
    is  called an anonymous union; it defines an unnamed object (and not
    a type).  The names of the members of an  anonymous  union  must  be
    distinct  from  other  names  in  the  scope  in  which the union is
    declared; they are used directly in that  scope  without  the  usual
    member access syntax (_expr.ref_).  For example,
              void f()
                  union { int a; char* p; };
                  a = 1;
                  // ...
                  p = "Jennifer";
                  // ...
    Here a and p are used like ordinary (nonmember) variables, but since
    they are union members they have the same address.

3   A global anonymous union must  be  declared  static.   An  anonymous
    union  may  not  have private or protected members (_class.access_).
    An anonymous union may not have function members.

4   A union for which objects or pointers are declared is not an  anony­
    mous union.  For example,
              union { int aa; char* p; } obj, *ptr = &obj;
              aa = 1;       // error
              ptr->aa = 1;  // ok
    The  assignment  to  plain aa is ill formed since the member name is
    not associated with any particular object.

5   Initialization of unions that do not have constructors is  described
    in _dcl.init.aggr_.

    9.7  Bit-fields                                          [class.bit]

1   A member-declarator of the form
              identifieropt : constant-expression
    specifies a bit-field; its length is set off from the bit-field name
    by a colon.  Allocation of  bit-fields  within  a  class  object  is
    implementation  dependent.   Fields are packed into some addressable
    allocation unit.  Fields straddle allocation units on some  machines
    and not on others.  Alignment of bit-fields is implementation depen­
    dent.  Fields are assigned right-to-left on some machines,  left-to-
    right on others.

2   An unnamed bit-field is useful for padding to conform to externally-
    imposed layouts.  Unnamed fields are not members and cannot be  ini­
    tialized.   As  a special case, an unnamed bit-field with a width of
    zero specifies alignment of the next bit-field at an allocation unit

3   A bit-field may not be a static member.  A bit-field must have inte­
    gral or enumeration type (_basic.fundamental_).  It  is  implementa­
    tion  dependent  whether  a  plain  (neither  explicitly  signed nor
    unsigned) int field is signed or unsigned.  The address-of  operator
    &  may  not  be  applied to a bit-field, so there are no pointers to
    bit-fields.  Nor are there references to bit-fields.

    9.8  Nested class declarations                          [class.nest]

1   A class may be defined within another class.  A class defined within
    another  is  called  a  nested class.  The name of a nested class is
    local to its enclosing class.  The nested class is in the  scope  of
    its enclosing class.  Except by using explicit pointers, references,
    and object names, declarations in a nested class can use  only  type
    names, static members, and enumerators from the enclosing class.
              int x;
              int y;

              class enclose {
                  int x;
                  static int s;
                  class inner {
                      void f(int i)
                          x = i;   // error: assign to enclose::x
                          s = i;   // ok: assign to enclose::s
                          ::x = i; // ok: assign to global x
                          y = i;       // ok: assign to global y
                      void g(enclose* p, int i)
                          p->x = i;   // ok: assign to enclose::x


              inner* p = 0;   // error `inner' not in scope
    Member functions of a nested class have no special access to members
    of  an  enclosing  class;  they  obey   the   usual   access   rules
    (_class.access_).   Member  functions  of an enclosing class have no
    special access to members of a nested class;  they  obey  the  usual
    access rules.  For example,
              class E {
                  int x;
                  class I {
                      int y;
                      void f(E* p, int i)
                          p->x = i;   // error: E::x is private
                  int g(I* p)
                      return p->y;    // error: I::y is private
    Member  functions  and  static data members of a nested class can be
    defined in the global scope.  For example,
              class enclose {
                  class inner {
                      static int x;
                      void f(int i);
              typedef enclose::inner ei;
              int ei::x = 1;

              void enclose::inner::f(int i) { /* ... */ }
    A nested class may be declared in a class and later defined  in  the
    same or an enclosing scope.  For example:
              class E {
                  class I1;      // forward declaration of nested class
                  class I2;
                  class I1 {};  // definition of nested class
              class E::I2 {};   // definition of nested class
    Like  a member function, a friend function defined within a class is
    in the lexical scope of that class; it obeys the same rules for name
    binding   as   the   member   functions   (described  above  and  in
    _class.scope_) and like them has no special access rights to members
    of  an  enclosing  class or local variables of an enclosing function

    9.9  Local class declarations                          [class.local]

1   A class can be defined within a function definition; such a class is
    called  a  local  class.   The name of a local class is local to its
    enclosing scope.  The local class is in the scope of  the  enclosing
    scope.   Declarations  in  a  local  class  can use only type names,
    static variables, extern variables and  functions,  and  enumerators
    from the enclosing scope.  For example,
              int x;
              void f()
                  static int s ;
                  int x;
                  extern int g();
                  struct local {
                      int g() { return x; }    // error: `x' is auto
                      int h() { return s; }    // ok
                      int k() { return ::x; }  // ok
                      int l() { return g(); }  // ok
                  // ...

              local* p = 0;   // error: `local' not in scope

2   An  enclosing function has no special access to members of the local
    class; it obeys the usual  access  rules  (_class.access_).   Member
    functions  of a local class must be defined within their class defi­
    nition.  A local class may not have static data members.

    9.10  Nested type names                          [class.nested.type]

1   Type names obey exactly the same scope rules  as  other  names.   In
    particular,  type  names defined within a class definition cannot be
    used outside their class without qualification.  For example,
              class X {
                  typedef int I;
                  class Y { /* ... */ };
                  I a;

              I b;     // error
              Y c;     // error
              X::Y d;  // ok
              X::I e;  // ok