A class in C++ is a user-defined type or data structure declared with any of the keywords class, struct or union (the first two are collectively referred to as non-union classes) that has data and functions (also called member variables and member functions) as its members whose access is governed by the three access specifiers private, protected or public. By default access to members of a C++ class declared with the keyword class is private. The private members are not accessible outside the class; they can be accessed only through member functions of the class. The public members form an interface to the class and are accessible outside the class.

Instances of a class data type are known as objects and can contain member variables, constants, member functions, and overloaded operators defined by the programmer.

Differences between a struct and a class in C++ In C++, a class defined with the class keyword has private members and base classes by default. A structure is a class defined with the struct keyword.ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §9 Classes [class] para. 4 Its members and base classes are public by default. In practice, structs are typically reserved for data without functions. When deriving a struct from a class/struct, default access-specifier for a base class/struct is public. And when deriving a class, default access specifier is private.

Aggregate classes

An aggregate class is a class with no user-declared constructors, no private or protected non-static data members, no base classes, and no virtual functions.ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §8.5.1 Aggregates [dcl.init.aggr] para. 1 Such a class can be initialized with a brace-enclosed comma-separated list of initializer-clauses.ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §8.5.1 Aggregates [dcl.init.aggr] para. 2 The following code has the same semantics in both C and C++. Since C++20, aggregate types may also be initialized with C99-style designated initializers, but unlike in C, these fields cannot be reordered in declaration.

using std::string;

struct Address { string city; int zip;

struct Person { string name; int age; Address addr;

// Ordinary initializer list Address addr1 = {"Los Angeles", 12345}; Address addr2{"Seattle", 10001};

// Designated initializer Address addr3 = { .city = "Toronto", .zip = 13853

// Designated initializers also work with another aggregate as member: Person john{ .name = "John", .age = 20, .address = { .city = "New York", .zip = 54321

Just as in C, a semicolon must follow the definition of a struct/class. Between the definition of the struct/class and the semicolon, instances of it may be declared. // Declares two Points, named a and b // a = {1, 2} and b = {3, 4} struct Point { int x; int y; } a{1, 2}, b{3, 4};

POD-structs A POD-struct (Plain Old Data Structure) is a non-union aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-defined assignment operator and no user-defined destructor. A POD-struct could be said to be the C++ equivalent of a C struct. In most cases, a POD-struct will have the same memory layout as a corresponding struct declared in C. For this reason, POD-structs are sometimes colloquially referred to as "C-style structs".

Properties shared between structs in C and POD-structs in C++ Data members are allocated so that later members have higher addresses within an object, except where separated by an access-specifier.ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §9.2 Class members [class.mem] para. 12 Two POD-struct types are layout-compatible if they have the same number of nonstatic data members, and corresponding nonstatic data members (in order) have layout-compatible types.ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §9.2 Class members [class.mem] para. 14 A POD-struct may contain unnamed padding.ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §9.2 Class members [class.mem] para. 17 A pointer to a POD-struct object, suitably converted using a reinterpret cast, points to its initial member and vice versa, implying that there is no padding at the beginning of a POD-struct. A POD-struct may be used with the offsetof macro.ISO/IEC (2003). ISO/IEC 14882:2003(E): Programming Languages - C++ §18.1 Types [lib.support.types] para. 5

Declaration and usage

C++ classes have their own members. These members include variables (including other structures and classes), functions (specific identifiers or overloaded operators) known as member functions, constructors and destructors. Members are declared to be either publicly or privately accessible using the public: and private: access specifiers respectively. Any member encountered after a specifier will have the associated access until another specifier is encountered. There is also inheritance between classes which can make use of the protected: specifier.

The this keyword

To facilitate classes' ability to reference themselves, C++ implements the this keyword for all member functions. The this keyword acts as a pointer to the current object. Its type is that of a pointer to the current object.

The this keyword is especially important for member functions with the class itself as the return value:

class Point { private: double x; double y; public: // ...

Point& operator+=(const Point& rhs) noexcept { this->x += rhs.x; this->y += rhs.y; return *this;

As stated above, this is a pointer, so the use of the asterisk (*) is necessary to convert it into a reference to be returned. The type of this for a class X is X* const; if the member function is const-qualified, the type is const X* const.

Global and local class A class defined outside all functions is a global class because its objects can be created from anywhere in the program. If it is defined within a function body then it's a local class because objects of such a class are local to the function scope.

Basic declaration and member variables Non-union classes are declared with the class or struct keyword. Declaration of members are placed within this declaration. using std::string;

struct Person { string name; int age;

using std::string;

class Person { public: string name; int age; }; The above definitions are functionally equivalent. Either code will define objects of type Person as having two public data members, name and age. The semicolons after the closing braces are mandatory.

After one of these declarations (but not both), Person can be used as follows to create newly defined variables of the Person datatype:

import std;

using std::string;

struct Person { string name; int age;

int main() { Person a; Person b; a.name = "Calvin"; b.name = "Hobbes"; a.age = 30; b.age = 20; std::println("{}: {}", a.name, a.age); std::println("{}: {}", b.name, b.age); }

Executing the above code will output Calvin: 30 Hobbes: 20

Member functions An important feature of the C++ class are member functions. Each datatype can have its own built-in functions (referred to as member functions) that have access to all (public and private) members of the datatype. In the body of these non-static member functions, the keyword this can be used to refer to the object for which the function is called. This is commonly implemented by passing the address of the object as an implicit first argument to the function. Take the above Person type as an example again:

import std;

using std::string;

class Person { private: string name; int age = 5; public: // "name" and "age" are the member variables. The "this" keyword is an // expression whose value is the address of the object for which the member // was invoked. Its type is "const Person*", because the function is declared // const. void printData() const { std::println("{}: {}", name, age);

In the above example the printData method is declared in the body of the class and defined by qualifying it with the name of the class followed by ::. Both name and age are private (default for class) and printData is declared as public which is necessary if it is to be used from outside the class.

With the member function printData, printing can be simplified into: a.printData(); b.printData();

where a and b above are called senders, and each of them will refer to their own member variables when the printData() function is executed.

Prior to the introduction of modules (i.e. using headers), one would usually separate the class or structure declaration (called its interface) and the definition (called its implementation) into separate units. The interface, needed by the user, would be kept in a header file and the implementation would be kept separately in either source or compiled form.

Inheritance

The layout of non-POD classes in memory is not specified by the C++ standard. For example, many popular C++ compilers implement single inheritance by concatenation of the parent class fields with the child class fields, but this is not required by the standard. This choice of layout makes referring to a derived class via a pointer to the parent class type a trivial operation.

For example, consider struct Scalar { int x;

struct Vec2 : public Scalar { int y; }; An instance of Scalar with a Scalar* p pointing to it might look like this in memory: ┏━━━━━━━━━┓ ┃Scalar::x┃ ┗━━━━━━━━━┛ ↑ p An instance of Vec2 with a Scalar* p pointing to it might look like this: ┏━━━━━━━━━┳━━━━━━━┓ ┃Scalar::x┃Vec2::y┃ ┗━━━━━━━━━┻━━━━━━━┛ ↑ p Therefore, any code that manipulates the fields of a Scalar object can manipulate the Scalar fields inside the Vec2 object without having to consider anything about the definition of Vec2's fields. A properly written C++ program shouldn't make any assumptions about the layout of inherited fields, in any case. Using the static_cast or dynamic_cast type conversion operators will ensure that pointers are properly converted from one type to another.

Multiple inheritance is not as simple. If a class Z extends classes X and Y, then the fields of both parents need to be stored in some order, but (at most) only one of the parent classes can be located at the front of the derived class. Whenever the compiler needs to convert a pointer from the Z type to either X or Y, the compiler will provide an automatic conversion from the address of the derived class to the address of the base class fields (typically, this is a simple offset calculation).

The final keyword limits the ways in which a class can be subclassed.ISO International Standard ISO/IEC 14882:2020(E) – Programming Language C++. Subclasses of a class are prevented from overriding methods marked as final by the parent class. Final classes cannot be inherited. This allows devirtualization, the removal of the use of vtables for method lookup, thus allowing the inlining of method calls on final classes.

// final in a class declaration declares that a class cannot be extended class Z final : public X, public Y { public: // final in a method signature declares that a method cannot be overridden further void someOperation() override final { // do something here

final is not a reserved word in C++, and is instead defined as a contextual keyword, in order to not conflict with uses of the identifier 'final' in existing codebases.

Anonymous class A class may be anonymous, that is, without an identifier or name.

Anonymous structs had first existed in C11: struct { int x; int y; } coords;

coords.x = 5;

In C++, anonymous classes may be defined in a similar manner. However, these classes may not have constructors, as they have no name. Their types, which are compiler-generated, may be retrieved using . class { private: int value; public: int getValue() { return value;

void setValue(int x) { value = x;

void display() { std::println("Value: {}", value);