Class declaration
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) | ||||||||
| 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.
|
||||||||
| 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:
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; };
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]; } };
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 };
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) };
static_assert
declaraciones:
template<typename T> struct Foo { static_assert(std::is_floating_point<T>::value, "Foo<T>: T must be floating point"); };
struct S { template<typename T> void f(T&& n); template<class CharT> struct NestedS { std::basic_string<CharT> s; }; };
| (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.
|
(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
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
|