Declarations
Declaraciones son cómo los nombres se introducen (o reintroducen) en el programa C++. No todas las declaraciones realmente declaran algo, y cada tipo de entidad se declara de manera diferente. Definiciones son declaraciones que son suficientes para usar la entidad identificada por el nombre.
Una declaración es una de las siguientes:
- Definición de función
- Declaración de plantilla (incluyendo Especialización parcial de plantilla )
- Instanciación explícita de plantilla
- Especialización explícita de plantilla
- Definición de espacio de nombres
- Especificación de vinculación
|
(desde C++11) |
-
Declaración vacía (
;) - Una declaración de función sin una decl-specifier-seq :
attr
(opcional)
declarator
;
|
|||||||||
| attr | - | (since C++11) secuencia de cualquier número de atributos |
| declarator | - | un declarador de función |
- Esta declaración debe declarar un constructor, destructor o función de conversión de tipo definida por el usuario conversion function . Solo puede utilizarse como parte de una template declaration , explicit specialization , o explicit instantiation.
- block-declaration (una declaración que puede aparecer dentro de un bloque ), que, a su vez, puede ser una de las siguientes:
| (desde C++11) |
| (desde C++20) | |
|
(desde C++11) |
-
- declaración simple
Contenidos |
Declaración simple
Una declaración simple es una sentencia que introduce, crea y opcionalmente inicializa uno o varios identificadores, típicamente variables.
decl-specifier-seq
init-declarator-list
(opcional)
;
|
(1) | ||||||||
attr
decl-specifier-seq
init-declarator-list
;
|
(2) | (desde C++11) | |||||||
| decl-specifier-seq | - | secuencia de especificadores |
| init-declarator-list | - | lista separada por comas de init-declarator s (ver abajo) |
| attr | - | secuencia de cualquier número de atributos |
init-declarator-list
solo puede omitirse al declarar una clase con nombre o una enumeración con nombre.
|
Una declaración de enlace estructurado también es una declaración simple. |
(desde C++17) |
La sintaxis de
init-declarator
se define de la siguiente manera:
| declarador inicializador | (1) | ||||||||
| declarador cláusula-requires (opcional) especificaciones-contrato (opcional) | (2) | ||||||||
| declarator | - | un declarator |
| initializer | - | un initializer |
| requires-clause | - | (since C++20) una requires clause |
| contract-specs | - | (since C++26) una lista de function contract specifiers |
|
requires-clause solo puede aparecer si declarator declara una función con plantilla . |
(since C++20) |
|
contract-specs solo puede aparecer si declarator declara una función o plantilla de función. |
(since C++26) |
Especificadores
Especificadores de declaración ( decl-specifier-seq ) es una secuencia de los siguientes especificadores separados por espacios, en cualquier orden:
-
el
typedefespecificador. Si está presente, toda la declaración es una declaración typedef y cada declarador introduce un nuevo nombre de tipo, no un objeto o una función. -
especificadores de función (
inline,virtual,explicit), solo permitidos en declaraciones de función .
|
(desde C++17) |
-
el
friendespecificador, permitido en declaraciones de clases y funciones.
|
(desde C++11) |
|
(desde C++20) |
- especificador de clase de almacenamiento ( register , (hasta C++17) static , thread_local , (desde C++11) extern , mutable ). Solo se permite un especificador de clase de almacenamiento , excepto que thread_local puede aparecer junto con extern o static (desde C++11) .
- Especificadores de tipo ( type-specifier-seq ), una secuencia de especificadores que nombra un tipo. El tipo de cada entidad introducida por la declaración es este tipo, opcionalmente modificado por el declarador (ver abajo). Esta secuencia de especificadores también es utilizada por type-id . Solo los siguientes especificadores son parte de type-specifier-seq , en cualquier orden:
-
- especificador de clase
- especificador de enumeración
- especificador de tipo simple
| (desde C++11) | |
| (desde C++26) |
-
-
- nombre de clase previamente declarado (opcionalmente calificado )
- nombre de enumeración previamente declarado (opcionalmente calificado )
- nombre de typedef o alias de tipo (desde C++11) previamente declarado (opcionalmente calificado )
- nombre de plantilla con argumentos de plantilla (opcionalmente calificado , opcionalmente usando desambiguador de plantilla )
-
|
(desde C++17) |
-
-
- la palabra clave class , struct , o union , seguida del identificador (opcionalmente calificado ), previamente definido como el nombre de una clase.
- la palabra clave class , struct , o union , seguida del nombre de plantilla con argumentos de plantilla (opcionalmente calificado , opcionalmente usando template desambiguador ), previamente definido como el nombre de una plantilla de clase.
- la palabra clave enum seguida del identificador (opcionalmente calificado ), previamente declarado como el nombre de una enumeración.
-
-
solo se permite un especificador de tipo en una secuencia de especificadores de declaración, con las siguientes excepciones:
- const puede combinarse con cualquier especificador de tipo excepto consigo mismo.
- volatile puede combinarse con cualquier especificador de tipo excepto consigo mismo.
- signed o unsigned pueden combinarse con char , long , short , o int .
- short o long pueden combinarse con int .
- long puede combinarse con double .
|
(desde C++11) |
Atributos pueden aparecer en decl-specifier-seq , en cuyo caso se aplican al tipo determinado por los especificadores precedentes.
Las repeticiones de cualquier especificador en una decl-specifier-seq , como const static const , o virtual inline virtual son errores , excepto que long puede aparecer dos veces (desde C++11) .
Declaradores
Cada init-declarator en una init-declarator-list S D1, D2, D3 ; se procesa como si fuera una declaración independiente con los mismos especificadores: S D1 ; S D2 ; S D3 ; .
Cada declarador introduce exactamente un objeto, referencia, función o (para declaraciones typedef) alias de tipo, cuyo tipo es proporcionado por decl-specifier-seq y opcionalmente modificado por operadores como & (referencia a) o [ ] (arreglo de) o ( ) (función que retorna) en el declarador. Estos operadores pueden aplicarse recursivamente, como se muestra a continuación.
Un declarador es uno de los siguientes:
| unqualified-id attr (opcional) | (1) | ||||||||
| qualified-id attr (opcional) | (2) | ||||||||
...
identifier
attr
(opcional)
|
(3) | (desde C++11) | |||||||
*
attr
(opcional)
cv
(opcional)
declarator
|
(4) | ||||||||
nested-name-specifier
*
attr
(opcional)
cv
(opcional)
declarator
|
(5) | ||||||||
&
attr
(opcional)
declarator
|
(6) | ||||||||
&&
attr
(opcional)
declarator
|
(7) | (desde C++11) | |||||||
noptr-declarator
[
constant-expression
(opcional)
]
attr
(opcional)
|
(8) | ||||||||
noptr-declarator
(
parameter-list
)
cv
(opcional)
ref
(opcional)
except
(opcional)
attr
(opcional)
|
(9) | ||||||||
(
declarator
)
|
(10) | ||||||||
D
como un puntero al tipo determinado por
decl-specifier-seq
S
.
D
como un puntero a miembro de
C
de tipo determinado por
decl-specifier-seq
S
.
nested-name-specifier
es una
secuencia de nombres y operadores de resolución de ámbito
::
D
como una referencia Lvalue al tipo determinado por
decl-specifier-seq
S
.
D
como una referencia a valor derecho al tipo determinado por
decl-specifier-seq
S
.
|
En todos los casos, attr es una secuencia opcional de attributes . Cuando aparece inmediatamente después del identificador, se aplica al objeto que se está declarando. |
(since C++11) |
cv es una secuencia de calificadores const y volatile , donde cada calificador puede aparecer como máximo una vez en la secuencia.
|
Esta sección está incompleta
Razón: explicar las reglas de ocultamiento de nombres en declaraciones; cómo una declaración de variable/función oculta una clase (pero no un typedef) con el mismo nombre |
Notas
Cuando una block-declaration aparece dentro de un bloque , y un identificador introducido por una declaración fue previamente declarado en un bloque externo, la declaración externa queda oculta durante el resto del bloque.
Si una declaración introduce una variable con duración de almacenamiento automático, se inicializa cuando se ejecuta su sentencia de declaración. Todas las variables automáticas declaradas en un bloque se destruyen al salir del bloque (independientemente de cómo se abandone el bloque: mediante exception , goto , o al alcanzar su final), en orden inverso a su orden de inicialización.
Ejemplo
Nota: este ejemplo demuestra cómo se analizan algunas declaraciones complejas en términos de la gramática del lenguaje. Otras reglas mnemotécnicas populares son: la regla espiral , lectura de adentro hacia afuera , y la declaración refleja el uso . También existe un analizador automatizado en https://cdecl.org .
#include <type_traits> struct S { int member; // decl-specifier-seq is "int" // declarator is "member" } obj, *pObj(&obj); // decl-specifier-seq is "struct S { int member; }" // declarator "obj" declares an object of type S // declarator "*pObj" declares a pointer to S, // and initializer "(&obj)" initializes it int i = 1, *p = nullptr, f(), (*pf)(double); // decl-specifier-seq is "int" // declarator "i" declares a variable of type int, // and initializer "= 1" initializes it // declarator "*p" declares a variable of type int*, // and initializer "= nullptr" initializes it // declarator "f()" declares (but doesn't define) // a function taking no arguments and returning int // declarator "(*pf)(double)" declares a pointer to function // taking double and returning int int (*(*var1)(double))[3] = nullptr; // decl-specifier-seq is "int" // declarator is "(*(*var1)(double))[3]" // initializer is "= nullptr" // 1. declarator "(*(*var1)(double))[3]" is an array declarator: // Type declared is: "(*(*var1)(double))" array of 3 elements // 2. declarator "(*(*var1)(double))" is a pointer declarator: // Type declared is: "(*var1)(double)" pointer to array of 3 elements // 3. declarator "(*var1)(double)" is a function declarator: // Type declared is: "(*var1)" function taking "(double)", // returning pointer to array of 3 elements. // 4. declarator "(*var1)" is a pointer declarator: // Type declared is: "var1" pointer to function taking "(double)", // returning pointer to array of 3 elements. // 5. declarator "var1" is an identifier. // This declaration declares the object var1 of type "pointer to function // taking double and returning pointer to array of 3 elements of type int" // The initializer "= nullptr" provides the initial value of this pointer. // C++11 alternative syntax: auto (*var2)(double) -> int (*)[3] = nullptr; // decl-specifier-seq is "auto" // declarator is "(*var2)(double) -> int (*)[3]" // initializer is "= nullptr" // 1. declarator "(*var2)(double) -> int (*)[3]" is a function declarator: // Type declared is: "(*var2)" function taking "(double)", returning "int (*)[3]" // ... int main() { static_assert(std::is_same_v<decltype(var1), decltype(var2)>); }
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.
| DR | Se aplica a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| CWG 482 | C++98 | los declaradores de redeclaraciones no podían estar calificados | se permiten declaradores calificados |
| CWG 569 | C++98 | un punto y coma independiente no era una declaración válida |
es una declaración vacía,
que no tiene efecto |
| CWG 1830 | C++98 | se permitía la repetición de un especificador de función en una decl-specifier-seq | la repetición está prohibida |
Véase también
|
Documentación de C
para
Declarations
|