Share via


Escopo (C++)

Quando você declara um elemento de programa, como uma classe, função ou variável, seu nome só pode ser "visto" e usado em determinadas partes do programa. O contexto no qual um nome é visível é chamado de escopo. Por exemplo, se você declarar uma variável x dentro de uma função, x só estará visível dentro desse corpo da função. Ele tem escopo local. Você pode ter outras variáveis com o mesmo nome em seu programa; Desde que estejam em escopos diferentes, eles não violam a Regra de Definição de Uma e nenhum erro é gerado.

Para variáveis não estáticas automáticas, o escopo também determina quando elas são criadas e destruídas na memória do programa.

Há seis tipos de escopo:

  • Escopo global Um nome global é aquele declarado fora de qualquer classe, função ou namespace. No entanto, no C++ até esses nomes existem com um namespace global implícito. O escopo de nomes globais estende-se do ponto de declaração até o final do arquivo no qual eles são declarados. Para nomes globais, a visibilidade também é regida pelas regras de vinculação que determinam se o nome está visível em outros arquivos no programa.

  • Escopo do namespace Um nome declarado dentro de um namespace, fora de qualquer definição de classe ou enumeração ou bloco de funções, fica visível do ponto de declaração até o final do namespace. Um namespace pode ser definido em vários blocos em arquivos diferentes.

  • Escopo local Um nome declarado dentro de uma função ou lambda, incluindo os nomes de parâmetro, tem escopo local. Eles são frequentemente chamados de "locais". Elas só ficam visíveis do ponto de declaração até o final da função ou do corpo lambda. O escopo local é uma espécie de escopo de bloco, que é discutido posteriormente neste artigo.

  • Escopo da classe Os nomes dos membros da classe têm escopo de classe, que se estende por toda a definição de classe, independentemente do ponto de declaração. A acessibilidade de membro de classe é ainda mais controlada pelas palavras-chaves public, private e protected. Membros públicos ou protegidos só podem ser acessados usando os operadores de seleção de membro (. ou ->) ou operadores de ponteiro para membro (.* ou ->*).

  • Escopo da instrução Os nomes declarados em uma instrução for, if, while ou switch ficam visíveis até o final do bloco de instrução.

  • Escopo da função Um rótulo tem escopo de função, o que significa que ele é visível em todo o corpo da função antes mesmo de seu ponto de declaração. O escopo da função possibilita gravar instruções como goto cleanup antes de o rótulo cleanup ser declarado.

Ocultando nomes

Você pode ocultar um nome declarando-o em um bloco fechado. Na figura a seguir, i é redeclarado dentro do bloco interno, ocultando assim a variável associada a i no escopo do bloco externo.

Diagram that shows block scope name hiding.
Ocultamento do nome e escopo do bloco

O resultado do programa mostrado na figura é:

i = 0
i = 7
j = 9
i = 0

Observação

O argumento szWhat é considerado como presente no escopo da função. Portanto, ele será tratado como se tivesse sido declarado no bloco externo da função.

Ocultando nomes de classe

É possível ocultar nomes de classe declarando uma função, um objeto, uma variável ou um enumerador no mesmo escopo. No entanto, o nome de classe ainda poderá ser acessado quando precedido pela palavra-chave class.

// hiding_class_names.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;

// Declare class Account at global scope.
class Account
{
public:
    Account( double InitialBalance )
        { balance = InitialBalance; }
    double GetBalance()
        { return balance; }
private:
    double balance;
};

double Account = 15.37;            // Hides class name Account

int main()
{
    class Account Checking( Account ); // Qualifies Account as
                                       //  class name

    cout << "Opening account with a balance of: "
         << Checking.GetBalance() << "\n";
}
//Output: Opening account with a balance of: 15.37

Observação

Em qualquer lugar em que o nome de classe (Account) for chamado, a palavra-chave class deve ser usadas para diferenciá-lo da variável Account com escopo global. Essa regra não se aplica quando o nome de classe ocorre no lado esquerdo do operador de resolução de escopo (::). Os nomes no lado esquerdo do operador de resolução de escopo são sempre considerados nomes de classe.

O exemplo a seguir demonstra como declarar um ponteiro para um objeto do tipo Account usando a palavra-chave class:

class Account *Checking = new class Account( Account );

O Account no inicializador (entre parênteses) na instrução anterior tem escopo de arquivo; é do tipo double.

Observação

A reutilização de nomes de identificadores como mostrada neste exemplo é considerada um estilo de programação ruim.

Para obter informações sobre declaração e inicialização de objetos de classe, consulte Classes, estruturas e uniões. Para obter informações sobre como usar os operadores de armazenamento livre new e delete, consulte Operadores new e delete.

Ocultar nomes com escopo global

Você pode ocultar nomes com escopo global declarando explicitamente o mesmo nome no escopo do bloco. No entanto, os nomes de escopo global podem ser acessados usando o operador de resolução de escopo (::).

#include <iostream>

int i = 7;   // i has global scope, outside all blocks
using namespace std;

int main( int argc, char *argv[] ) {
   int i = 5;   // i has block scope, hides i at global scope
   cout << "Block-scoped i has the value: " << i << "\n";
   cout << "Global-scoped i has the value: " << ::i << "\n";
}
Block-scoped i has the value: 5
Global-scoped i has the value: 7

Confira também

Conceitos básicos