Namespaces
Variants

Class declaration

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Class/struct types
Union types

Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Las clases son tipos definidos por el usuario, definidos por un especificador de clase, que aparece en la decl-specifier-seq de la sintaxis de declaración .

Contenidos

Sintaxis

El especificador de clase tiene la siguiente sintaxis:

class-key attr  (opcional) class-head-name class-property-specs  (opcional) base-clause  (opcional)
{ member-specification }
(1)
class-key attr  (opcional) base-clause  (opcional)
{ member-specification }
(2)
1) Definición de clase con nombre
2) Definición de clase sin nombre
class-key - uno de class , struct y union . Las palabras clave class y struct son idénticas excepto por el acceso a miembros predeterminado y el acceso a clase base predeterminado. Si es union , la declaración introduce un tipo union .
attr - (desde C++11) cualquier número de atributos , puede incluir el especificador alignas
class-head-name - el nombre de la clase que se está definiendo, opcionalmente calificado
class-property-specs - Una lista de los siguientes especificadores, cada especificador se permite como máximo una vez en cada secuencia.
Especificador Efecto
final
(desde C++11)
Especifica que la clase no puede ser derivada
trivially_relocatable_if_eligible
(desde C++26)
Marca la clase como trivialmente reubicable si es elegible
replaceable_if_eligible
(desde C++26)
Marca la clase como reemplazable si es elegible
base-clause - lista de una o más clases base y el modelo de herencia utilizado para cada una (ver clase derivada )
member-specification - lista de especificadores de acceso, declaraciones y definiciones de objetos y funciones miembro ( ver abajo )

Declaración anticipada

Una declaración de la siguiente forma

class-key attr identifier ;

Declara un tipo de clase que será definido posteriormente en este ámbito. Hasta que aparezca la definición, este nombre de clase tiene tipo incompleto . Esto permite que clases que se referencian entre sí:

class Vector; // declaración anticipada
class Matrix
{
    // ...
    friend Vector operator*(const Matrix&, const Vector&);
};
class Vector
{
    // ...
    friend Vector operator*(const Matrix&, const Vector&);
};

y si un archivo fuente particular solo utiliza punteros y referencias a la clase, esto hace posible reducir #include dependencias:

// En MyStruct.h
#include <iosfwd> // contiene declaración anticipada de std::ostream
struct MyStruct
{
    int value;
    friend std::ostream& operator<<(std::ostream& os, const S& s);
    // definición proporcionada en archivo MyStruct.cpp que usa #include <ostream>
};

Si la declaración adelantada aparece en un ámbito local, oculta la clase, variable, función previamente declarada, y todas las demás declaraciones del mismo nombre que puedan aparecer en ámbitos envolventes:

struct s { int a; };
struct s; // no hace nada (s ya está definido en este ámbito)
void g()
{
    struct s; // declaración anticipada de una nueva estructura local "s"
              // esto oculta la estructura global s hasta el final de este bloque
    s* p; // puntero a la estructura local s
    struct s { char* p; }; // definición de la estructura local s
}

Tenga en cuenta que un nuevo nombre de clase también puede ser introducido por un elaborated type specifier que aparece como parte de otra declaración, pero solo si name lookup no puede encontrar una clase previamente declarada con el mismo nombre.

class U;
namespace ns
{
    class Y f(class T p); // declara la función ns::f y declara ns::T y ns::Y
    class U f(); // U se refiere a ::U
    // se pueden usar punteros y referencias a T y Y
    Y* p;
    T* q;
}

Especificación de miembros

La especificación de miembros, o el cuerpo de una definición de clase, es una secuencia entre llaves de cualquier número de los siguientes:

1) Las declaraciones de miembros de la forma
attr  (opcional) decl-specifier-seq  (opcional) member-declarator-list  (opcional) ;
attr - (desde C++11) cualquier número de atributos
decl-specifier-seq - secuencia de especificadores . Solo es opcional en las declaraciones de constructores, destructores y funciones de conversión de tipos definidas por el usuario
member-declarator-list - similar a una init-declarator-list , pero adicionalmente permite declaración de campo de bits , pure-specifier , y virt-specifier ( override o final ) (desde C++11) , y no permite sintaxis de direct-non-list-initialization .

Esta declaración puede declarar static y no estáticos data members y member functions , member typedefs , member enumerations , y nested classes . También puede ser una friend declaration .

class S
{
    int d1;             // non-static data member
    int a[10] = {1, 2}; // non-static data member with initializer (C++11)
    static const int d2 = 1; // static data member with initializer
    virtual void f1(int) = 0; // pure virtual member function
    std::string d3, *d4, f2(int); // two data members and a member function
    enum { NORTH, SOUTH, EAST, WEST };
    struct NestedS
    {
        std::string s;
    } d5, *d6;
    typedef NestedS value_type, *pointer_type;
};
2) Definiciones de funciones, que tanto declaran como definen member functions o friend functions . Un punto y coma después de una definición de función miembro es opcional. Todas las funciones que se definen dentro del cuerpo de una clase son automáticamente inline , a menos que estén asociadas a un named module (since C++20) .
class M
{
    std::size_t C;
    std::vector<int> data;
public:
    M(std::size_t R, std::size_t C) : C(C), data(R*C) {} // constructor definition
    int operator()(std::size_t r, std::size_t c) const // member function definition
    {
        return data[r * C + c];
    }
    int& operator()(std::size_t r, std::size_t c) // another member function definition
    {
        return data[r * C + c];
    }
};
3) Especificadores de acceso public: , protected: , y private:
class S
{
public:
    S();          // public constructor
    S(const S&);  // public copy constructor
    virtual ~S(); // public virtual destructor
private:
    int* ptr; // private data member
};
4) Declaraciones using :
class Base
{
protected:
    int d;
};
class Derived : public Base
{
public:
    using Base::d;    // hacer que el miembro protegido d de Base sea un miembro público de Derived
    using Base::Base; // heredar todos los constructores de las clases base (C++11)
};
5) static_assert declaraciones:
template<typename T>
struct Foo
{
    static_assert(std::is_floating_point<T>::value, "Foo<T>: T must be floating point");
};
6) declaraciones de plantillas de miembro :
struct S
{
    template<typename T>
    void f(T&& n);
    template<class CharT>
    struct NestedS
    {
        std::basic_string<CharT> s;
    };
};
7) declaraciones de alias :
template<typename T>
struct identity
{
    using type = T;
};
(desde C++11)
8) guías de deducción de plantillas de clases miembro:
struct S
{
    template<class CharT>
    struct NestedS
    {
        std::basic_string<CharT> s;
    };
    template<class CharT>
    NestedS(std::basic_string<CharT>) -> NestedS<CharT>;
};
(desde C++17)
9) Declaraciones using-enum :
enum class color { red, orange, yellow };
struct highlight
{
    using enum color;
};
(desde C++20)

Clases locales

Una declaración de clase puede aparecer dentro del cuerpo de una función, en cuyo caso define una clase local . El nombre de dicha clase solo existe dentro del ámbito de la función, y no es accesible fuera.

  • Los miembros de una clase local solo pueden declararse en la definición de esa clase, excepto que los miembros que son clases anidadas también pueden declararse en el ámbito de bloque más cercano que encierra a esa clase.
  • Una clase anidada dentro de una clase local también es una clase local.
  • Una clase local no puede tener miembros de datos estáticos.
  • Las funciones miembro de una clase local no tienen vinculación.
  • Las funciones miembro de una clase local deben definirse completamente dentro del cuerpo de la clase.
  • Las clases locales distintas de los tipos de clausura (desde C++14) no pueden tener plantillas de miembros.
  • Las clases locales no pueden tener plantillas amigas .
  • Las clases locales no pueden definir funciones amigas dentro de la definición de la clase.
  • Una clase local dentro de una función (incluyendo función miembro) puede acceder a los mismos nombres a los que puede acceder la función envolvente.
  • Las clases locales no podían usarse como argumentos de plantilla.
(until C++11)

#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
    std::vector<int> v{1, 2, 3};
    struct Local
    {
        bool operator()(int n, int m)
        {
            return n > m;
        }
    };
    std::sort(v.begin(), v.end(), Local()); // since C++11
    for (int n : v)
        std::cout << n << ' ';
    std::cout << '\n';
}

Salida:

3 2 1

Palabras clave

class , struct , union

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.

DR Se aplica a Comportamiento publicado Comportamiento correcto
CWG 1693 C++98 las declaraciones de miembros no podían estar vacías se permite la declaración vacía
CWG 1930 C++98 member-declarator-list podría estar vacía cuando decl-specifier-seq
contiene un especificador de clase de almacenamiento o calificador cv
la lista no debe estar vacía
CWG 2890 C++98 no estaba claro dónde pueden declararse los miembros de clases anidadas se aclaró

Véase también

Documentación de C para Declaración de struct