Declarações
Declarações introduzem (ou re-introduzem) nomes ao programa C++. Cada tipo de entidade é declarado diferentemente. Definições são declarações que são suficientes para usar a entidade identificada pelo nome.
Uma declaração é uma das seguintes:
- Definição de função
- Declaração de template (incluindo especialização de template parcial)
- Instanciação de
- Especialização de template explícita
- Definição de namespace
- Especificação de ligação
- Declaração de atributo (attr
;
) (desde C++11) - Declaração vazia (
;
) (desde C++11) - Uma declaração de função sem uma decl-specifier-seq:
attr(opcional) declarator ;
|
|||||||||
attr (desde C++11) | - | sequência de qualquer número de atributos |
declarator | - | Um declarador de função. |
- Esta declaração deve declarar um construtor, destrutor, ou função de conversão de tipo definido por usuário. Ela só pode ser usada como parte de uma declaração de template, especialização explícita, ou instanciação explícita.
- block-declaration (uma declaração que pode aparecer dentro de um bloco), que, por sua vez, pode ser um das seguintes:
- declaração asm
- declaração de alias de tipo (desde C++11)
- declaração de alias de namespace
- declaração using
- diretiva using
- using-enum-declaration (desde C++20)
- declaração
static_assert
(desde C++11) - de claração de enum opaca (desde C++11)
- declaração simples
Índice |
[editar] Declaração simples
Uma declaração simples é uma instrução que introduz, cria, e opcionalmente inicializa um ou vários identificadores, tipicamente variáveis.
decl-specifier-seq init-declarator-list(opcional) ;
|
(1) | ||||||||
attr decl-specifier-seq init-declarator-list;
|
(2) | ||||||||
attr (desde C++11) | - | sequência de qualquer número de atributos |
decl-specifier-seq | - | sequência de especificadores (veja abaixo). |
init-declarator-list | - | lista separada por vírgula de declaradores com inicializadores opcionais. init-declarator-list é opcional quando declarando uma classe/struct/union nomeada ou uma enumeração nomeada |
Uma declaração de binding estruturado também é uma declaração simples. (desde C++17)
[editar] Especificadores
Especificadores de declaração (decl-specifier-seq) é uma sequência dos seguintes especificadores separados por whitespace, em qualquer ordem:
- o especificador
typedef
. Se presente, a declaração inteira é uma declaração de typedef e cada declarador introduz um novo nome de tipo, não um objeto ou uma função. - especificadores de função (
inline
,virtual
,explicit
), somente permitidos em declarações de função
|
(desde C++17) |
- o especificador
friend
, permitido em declarações de classe e função.
|
(desde C++11) |
|
(desde C++20) |
- especificador de classe de armazenamento (register, static, thread_local (desde C++11), extern, mutable). Somente um especificador de classe de armazenamento é permitido, exceto que
thread_local
pode aparecer junto comextern
oustatic
. - Especificadores de tipo (type-specifier-seq), uma sequência de especificadores que nomeia um tipo. O tipo de toda entidade introduzida pela declaração é este tipo, opcionalmente modificado pelo declarador (veja abaixo). Esta sequência de especificadores também é usada por type-id. Somente os seguintes especificadores são parte de type-specifier-seq, em qualquer ordem:
- especificador classe
- especificador enum
- especificador de tipo simples
(desde C++11) |
- nome de classe previamente declarado (opcionalmente qualificado)
- nome de enum previamente declarado (opcionalmente qualificado)
- typedef-name ou type alias (desde C++11) previamente declarado (opcionalmente qualificado)
- nome de template com argumentos de template (opcionalmente qualificado, opcionalmente usando desambiguador de template)
|
(desde C++17) |
-
- a palavra chave class, struct, ou union, seguida pelo identificador (opcionalmente qualificado), previamente definida como o nome de uma classe, struct, ou união.
- a palavra chave class, struct, ou union, seguida por nome de template com argumentos de template (opcionalmente qualificado, opcionalmente usando desambiguador de template), previamente definida como o nome de um template de classe.
- a palavra chave enum seguida pelo identificador (opcionalmente qualificado), previamente declarada como o nome de uma enumeração.
- somente um especificador de tipo é permitido numa decl-specifier-seq, com as seguintes exceções:
- -
const
pode ser combinado com qualquer especificador de tipo exceto ele mesmo. - -
volatile
pode ser combinado com qualquer especificador de tipo exceto ele mesmo. - -
signed
ouunsigned
pode ser combinado comchar
,long
,short
, ouint
. - -
short
oulong
pode ser combinado comint
. - -
long
pode ser combinado comdouble
.
|
(desde C++11) |
Atributos podem aparecer em decl-specifier-seq, em tal caso eles se aplicam ao tipo determinado pelos especificadores precedentes.
O único especificador que é permitido aparecer duas vezes numa decl-specifier-seq é |
(desde C++17) |
[editar] Declaradores
init-declarator-list é uma sequência separada por vírgula de um ou mais init-declarators, que têm a seguinte sintaxe:
declarator initializer(opcional) | (1) | ||||||||
declarator requires-clause | (2) | (desde C++20) | |||||||
declarator | - | o declarador |
initializer | - | inicializador opcional (exceto onde requerido, tal como ao inicializar referências ou objetos const). Veja Inicialização para detalhes. |
requires-clause(C++20) | - | uma requires-clause, que adiciona uma restrição/constraint a uma declaração de função |
Cada init-declarator numa sequência de init-declarator S D1, D2, D3; é processado como se fosse uma declaração autônoma com os mesmos especificadores: S D1; S D2; S D3;.
Cada declarador introduz exatamente um objeto, referência, função, ou (para declarações de typedef) alias de tipo, cujo tipo é provido por decl-specifier-seq e opcionalmente modificado por operadores tais como & (referência a) ou [] (array de) ou () (função retornando) no declarador. Estes operadores podem ser aplicados recursivamente, como mostrado abaixo.
Um declarador (declarator) é um dos seguintes:
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 [ constexpr(opcional) ] attr(opcional)
|
(8) | ||||||||
noptr-declarator ( parameter-list ) cv(opcional) ref(opcional) except(opcional) attr(opcional)
|
(9) | ||||||||
D
como um pointer para um tipo determinado por decl-specifier-seq S
.D
como um pointer para membro de C
de tipo determinado por decl-specifier-seq S
. nested-name-specifier é uma sequência de nomes e operadores de resolução de escopo ::
D
como uma referência lvalue ao tipo determinado por decl-specifier-seq S
.D
coo uma referência rvalue ao tipo determinaddo por decl-specifier-seq S
.Em todos os casos, attr é uma sequência de atributos. Quando aparecendo imediatamente depois do identificador, ele se aplica ao objeto sendo declarado.
cv é uma sequência de qualificadores const e volatile qualifiers, onde qualquer um desses qualificadores pode aparecer ao máximo uma vez na sequência.
Esta seção está incompleta Motivo: explicar regras de ocultação de nome de declaração; como uma declaração de variável/função esconde uma classe (mas não um typedef) com o mesmo nome |
[editar] Notas
Quando uma block-declaration aparece dentro de um bloco, e um identificador introduzido por uma declaração foi anteriorente declarado num outro ploco mais externo, a declaração mais externa é escondida pelo o resto do bloco.
Se uma declaração introduz uma variável com duração de armazenamento automática, ela é inicializada quando sua instrução de declaração é executada. Todas as variáveis automáticas declaradas num bloco são destruídas na saída do bloco (não importa como o bloco é saído: via exceção, goto, ou ao alcançar seu fim), em ordem oposta a sua ordem de inicialização.
[editar] Exemplos
#include <string> class C { std::string membro; // decl-specifier-seq é "std::string" // declarator é "membro" } obj, *pObj(&obj); // decl-specifier-seq é "class C { std::string membro; }" // declarator "obj" define um objeto de tipo C // declarator "*pObj(&obj)" declara e inicializa um pointer para C int a = 1, *p = nullptr, f(), (*pf)(double); // decl-specifier-seq é int // declarator a = 1 define e inicializa uma variável de tipo int // declarator *p = nullptr define e inicializa uma variável de tipo int* // declarator (f)() declara (mas não define) // uma função levando nenhuns argumentos e retornando int // declarator (*pf)(double) define um pointer para função // levando double e retornando int int (*(*foo)(double))[3] = nullptr; // decl-specifier-seq é int // 1. declarator "(*(*foo)(double))[3]" é um declarador de array: // o tipo declarado é "array /declarador ninhado/ de 3 int" // 2. o declarador ninhado é "(*(*foo)(double))", que é um declarador de pointer // o tipo declarado é "pointer /declarador ninhado/ para array de 3 int" // 3. o declarador ninhado é "(*foo)(double)", que é um declarador de função // o tipo declarado é "função /declarador ninhado/ levando double e retornando // pointer para array de 3 int" // 4. o declarador ninhado é "(*foo)" que é um declarador de pointer (parentesizado, como requerido por sintaxe de declarador de função). // o tipo declarado é "pointer /declarador ninhado/ para função levando double // e retornando pointer para array de 3 int" // 5. o declarador ninhado é "foo", que é um identificador. // A declaração declara o objeto foo de tipo "pointer para função levando double // e retornando pointer para array de 3 int" // O inicializador "= nullptr" provê o valor inicial deste pointer.
[editar] Veja também
Documentação C para Declarações
|