9 Classes [class]

9.2 Class members [class.mem]

member-specification:
    member-declaration member-specificationopt
    access-specifier : member-specificationopt
member-declaration:
    attribute-specifier-seqopt decl-specifier-seqopt member-declarator-listopt ;
    function-definition ;opt
    using-declaration
    static_assert-declaration
    template-declaration
    alias-declaration
member-declarator-list:
    member-declarator
    member-declarator-list , member-declarator
member-declarator:
    declarator virt-specifier-seqopt pure-specifieropt
    declarator brace-or-equal-initializeropt
    identifieropt attribute-specifier-seqopt : constant-expression
virt-specifier-seq:
    virt-specifier
    virt-specifier-seq virt-specifier
virt-specifier:
    override
    final
pure-specifier:
    = 0

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 enumerators. Data members and member functions are static or non-static; 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 unscoped enumeration ([dcl.enum]) defined in the class are members of the class. Except when used to declare friends ([class.friend]) or to introduce the name of a member of a base class into a derived class ([namespace.udecl]), member-declarations declare members of the class, and each such member-declaration shall declare at least one member name of the class. A member shall not be declared twice in the member-specification, except that a nested class or member class template can be declared and then later defined, and except that an enumeration can be introduced with an opaque-enum-declaration and later redeclared with an enum-specifier.

A class is considered a completely-defined object type ([basic.types]) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

Note: A single name can denote several function members provided their types are sufficiently different (Clause [over]).  — end note ]

A member can be initialized using a constructor; see [class.ctor]. [ Note: See Clause [special] for a description of constructors and other special member functions.  — end note ]

A member can be initialized using a brace-or-equal-initializer. (For static data members, see [class.static.data]; for non-static data members, see [class.base.init]).

A member shall not be declared with the extern or register storage-class-specifier. Within a class definition, a member shall not be declared with the thread_local storage-class-specifier unless also declared static.

The decl-specifier-seq may be omitted in constructor, destructor, and conversion function declarations only; when declaring another kind of member the decl-specifier-seq shall contain a type-specifier that is not a cv-qualifier. The member-declarator-list can be omitted only after a class-specifier or an enum-specifier or in a friend declaration ([class.friend]). A pure-specifier shall be used only in the declaration of a virtual function ([class.virtual]).

The optional attribute-specifier-seq in a member-declaration appertains to each of the entities declared by the member-declarators; it shall not appear if the optional member-declarator-list is omitted.

A virt-specifier-seq shall contain at most one of each virt-specifier. A virt-specifier-seq shall appear only in the declaration of a virtual member function ([class.virtual]).

Non-static ([class.static]) data members shall not have incomplete types. In particular, a class C shall not contain a non-static member of class C, but it can contain a pointer or reference to an object of class C.

Note: See [expr.prim] for restrictions on the use of non-static data members and non-static member functions.  — end note ]

Note: The type of a non-static member function is an ordinary function type, and the type of a non-static data member is an ordinary object type. There are no special member function types or data member types.  — end note ]

Example: 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 objects of the same type. 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 object to which sp points; s.left refers to the left subtree pointer of the object s; and s.right->tword[0] refers to the initial character of the tword member of the right subtree of s.  — end example ]

Nonstatic data members of a (non-union) class with the same access control (Clause [class.access]) are allocated so that later members have higher addresses within a class object. The order of allocation of non-static data members with different access control is unspecified ([class.access]). Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other; so might requirements for space for managing virtual functions ([class.virtual]) and virtual base classes ([class.mi]).

If T is the name of a class, then each of the following shall have a name different from T:

  • every static data member of class T;

  • every member function of class TNote: This restriction does not apply to constructors, which do not have names ([class.ctor])  — end note ];

  • every member of class T that is itself a type;

  • every enumerator of every member of class T that is an unscoped enumerated type; and

  • every member of every anonymous union that is a member of class T.

In addition, if class T has a user-declared constructor ([class.ctor]), every non-static data member of class T shall have a name different from T.

Two standard-layout struct (Clause [class]) types are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in declaration order) have layout-compatible types ([basic.types]).

Two standard-layout union (Clause [class]) types are layout-compatible if they have the same number of non-static data members and corresponding non-static data members (in any order) have layout-compatible types ([basic.types]).

If a standard-layout union contains two or more standard-layout structs that share a common initial sequence, and if the standard-layout union object currently contains one of these standard-layout structs, it is permitted to inspect the common initial part of any of them. Two standard-layout structs share a common initial sequence if corresponding members have layout-compatible types and either neither member is a bit-field or both are bit-fields with the same width for a sequence of one or more initial members.

A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa. [ Note: There might therefore be unnamed padding within a standard-layout struct object, but not at its beginning, as necessary to achieve appropriate alignment.  — end note ]