parts/4.2.TypeSystem.md

4.2 Type System

Mix-ins (6.20, 6.40, 6.41)

Inheritance

C++ supports user-defined class types with one or more base classes. Dynamic polymorphism requires public bases defining virtual member functions.

C++ provides access specifiers that allow inheritance to restrict the visibility of inherited members in their subclasses.

A member declared in a class hides all members of the same name in any of its base classes. Such names can be reintroduced by the using declaration. For example:

    struct Base {
       int f(int i);
    };

    struct Derived : public Base {
       // using Base::f;
       int f(char c);
       int g() {
          return f(123); // Surprise, f(char) is called
      }
};

If the using declaration is uncommented above, then Base::f(int) is called.

For multiple inheritance users can request virtual inheritance, which causes data members inherited from the same ancestor class along multiple inheritance paths to be present only once; otherwise the data members are replicated and referring to them is ambiguous unless qualified by the name of the base class from which they are inherited. When members of equal name are inherited from multiple sources, C++ rejects an unqualified use of the common name as ambiguous as long as they are not hidden.

THIS REQUIRES MORE WORK

A particular area that is misunderstood is integral promotion. It can be confusing because promotion can result in changing the internal representation of an unsigned type to/from a signed type. For expressions formed with operands of unscoped enumeration type or integral types with a conversion rank smaller than int, integral promotion occurs before further implicit conversions happen. Integral promotion on unsigned types can convert these to the signed type int. Undefined behavior can occur due to signed integer arithmetic overflow even when the operands are of an unsigned type. Assume for example, - signed and unsigned short occupies 16 bits - signed and unsigned int occupies 32 bits then the following code causes undefined behavior:

   unsigned short const x = 0xfff0;
   x * x;                           // signed integer overflow, result will not fit in signed 32 bit int

Note: C++ also uses the term promotion to apply to a subset of conversion that apply to intergral and floating point types.

Implicit, i.e., automatic, conversions to a type T can be performed, for example, in the following situations:

  1. If the declaration, T t=e;, is defined for some expression, e, and some invented variable, t [C++17, Clause 7 [conv], para 3];

  2. In expressions involving operands of operators (e.g., +, -, *, /, etc.) subject to the requirements of each operators' operands [C++20, Clause 7.3 [conv], para 2.1];

  3. For example, the expression, 5 + 6.5, has operands of type int and double. Per language rules, the integer operand will be implicitly converted to double, i.e., the expression becomes double(5) + 6.5, i.e., 5.0 + 6.5.

  4. In boolean contexts, such as

  5. In the expression of a switch statement: the implicit conversion will be to an integral type [C++17, Clause 7 [conv], para 2.3];

  6. In an expression that initializes an object (e.g., an argument to a function call, the expression in a return statement) [C++17, Clause 7 [conv], para 2.4];

  7. When a non-explicit class/struct/union constructor can be invoked on an object resulting in some desired type, T, from initial objects passed to the constructor; and

  8. When a conversion operator has not been declared explicit, it can be implicitly invoked on an object resulting in some desired type, T, from an initial type.