Escopo em C ++

Escopo em C ++

Uma entidade em C ++ tem um nome, que pode ser declarado e/ou definido. Uma declaração é uma definição, mas uma definição não é necessariamente uma declaração. Uma definição aloca memória para a entidade nomeada, mas uma declaração pode ou não alocar memória para a entidade nomeada. Uma região declarativa é a maior parte de um programa em que o nome de uma entidade (variável) é válido. Essa região é chamada de escopo ou um escopo em potencial. Este artigo explica o escopo em C++. Além disso, o conhecimento básico do C ++ é necessário para entender este artigo.

Conteúdo do artigo

  • Região declarativa e escopo
  • Âmbito global
  • Variáveis ​​globais e escopo global
  • Bloquear o escopo
  • Escopo da função
  • Escopo da classe
  • Escopo de enumeração
  • Variável global
  • Escopo de parâmetro de modelo
  • Nome escondido
  • Possibilidade de repetir a declaração no mesmo escopo
  • Escopo de namespace
  • Escopo em diferentes porções
  • Conclusão

Região declarativa e escopo

Uma região declarativa é a maior parte de um texto do programa no qual o nome de uma entidade é válido. A região onde o nome não qualificado pode ser usado (visto) para se referir à mesma entidade. Considere o seguinte programa curto:

#incluir
usando namespace std;
void fn ()

int var = 3;
se (1 == 1)

cout<

int main ()

fn ();
retornar 0;

A função fn () possui dois blocos: um bloco interno para a condição if e um bloco externo para o corpo da função. O identificador, var, é introduzido e visto no bloco externo. Também é visto no bloco interno, com a declaração Cout. Os blocos externos e internos são o escopo para o nome, var.

No entanto, o nome, var, ainda pode ser usado para declarar uma entidade diferente, como um flutuador, no bloco interno. O código a seguir ilustra o seguinte:

#incluir
usando namespace std;
void fn ()

int var = 3;
se (1 == 1)

flutuar var = 7.5;
cout<

int main ()

fn ();
retornar 0;

A saída é

7.5

Nesse caso, o nome, var, não pode mais ser usado no bloco interno para se referir ao número inteiro do valor 3, que foi introduzido (declarado) no bloco externo. Tais blocos internos são chamados de escopo potencial para entidades declaradas no bloco externo.

Nota: Uma entidade do mesmo tipo, como o bloco externo, ainda pode ser declarada no bloco interno. No entanto, neste caso, a nova declaração e seu significado são válidos no bloco interno, enquanto a antiga declaração e o significado fora do bloco interno permanecem válidos apenas no bloco externo.

Uma declaração de mesmo nome em um bloco interno normalmente substitui a declaração do mesmo nome fora daquele bloco interno. Blocos internos podem aninhar outros blocos internos.

Âmbito global

Quando um programador começa a digitar um arquivo, esse é o escopo global. O programa curto a seguir ilustra o seguinte:

#incluir
usando namespace std;
flutuar var = 9.4;
int main ()

cout <cout <<::var<<'\n';
retornar 0;

A saída é:

9.4
9.4

Nesse caso, a região declarativa ou o escopo para VAR começa a partir do ponto de declaração para VAR e continua para baixo até o final do arquivo (unidade de tradução).

O bloco da função principal () é um escopo diferente; É um escopo aninhado para o escopo global. Para acessar uma entidade do escopo global de um escopo diferente, o identificador é usado diretamente ou precedido pelo operador de resolução de escopo, :: .

Nota: A entidade, main (), também é declarada no escopo global.

Bloquear o escopo

O IF, enquanto, faz, para ou switch declarações pode definir um bloco. Essa declaração é uma declaração composta. O nome de uma variável declarada em um bloco tem o escopo de um bloco. Seu escopo começa em seu ponto de declaração e termina no final de seu bloco. O programa curto a seguir ilustra isso para a variável, identificador:

#incluir
usando namespace std;
int main ()

se (1 == 1)

/*Algumas declarações*/
int identd = 5;
cout</*Algumas declarações*/

retornar 0;

Uma variável, como o identificador, declarado no escopo do bloco é uma variável local.

Uma variável declarada fora do escopo do bloco e acima pode ser vista no cabeçalho do bloco (e.g., condição para se bloqueio) e dentro do bloco. O programa curto a seguir ilustra isso para a variável, Identif:

#incluir
usando namespace std;
int main ()

int identif = 8;
if (identif == 8)

cout<
retornar 0;

A saída é,

8

Existem dois escopos de bloco: o bloco para a função principal () e a instrução if-composta aninhada. O bloco aninhado é o escopo potencial do bloco de função principal ().

Uma declaração introduzida em um escopo de bloco não pode ser vista fora do bloco. O programa curto a seguir, que não compila, ilustra isso com a variável, variab:

#incluir
usando namespace std;
int main ()

se (1 == 1)

int variab = 15;

cout<retornar 0;

O compilador produz uma mensagem de erro para variab.

Uma entidade introduzida, declarada no cabeçalho de uma função composta, não pode ser vista fora (abaixo) a declaração composta. O seguinte código de loop não compilará, resultando em uma mensagem de erro:

#incluir
usando namespace std;
int main ()

para (int i = 0; i<4; ++i)

cout<
cout<retornar 0;

A variável de iteração, i, é vista dentro do bloco de loop, mas não fora do bloco de loop for.

Escopo da função

Um parâmetro de função é visto no bloco de funções. Uma entidade declarada em um bloco de funções é vista do ponto de declaração até o final do bloco de funções. O programa curto a seguir ilustra o seguinte:

#incluir
#incluir
usando namespace std;
string fn (string str)

char stri [] = "bananas";
/*Outras declarações*/
String totalstr = str + stri;
return toTalstr;

int main ()

String totSTR = fn ("comendo");
cout<retornar 0;

A saída é:

Comer bananas

Nota: Uma entidade declarada fora da função (acima dela) pode ser vista na lista de parâmetros de função e no bloco de funções.

Rótulo

O escopo de um rótulo é a função em que parece. O código a seguir ilustra o seguinte:

#incluir
usando namespace std;
void fn ()

goto labl;
/*Outras declarações*/
labl: int intere = 2;
cout<
int main ()

fn ();
retornar 0;

A saída é

2

Escopo da classe

Com o escopo normal, a região declarativa começa de um ponto do programa, continua e para em um ponto diferente. O escopo existe em uma região contínua. Com a classe, o escopo de uma entidade pode estar em diferentes regiões que não são unidas. As regras para blocos aninhados ainda se aplicam. O programa a seguir ilustra o seguinte:

#incluir
usando namespace std;
// classe base
CLA CLA

privado:
int memp = 5;
protegido:
int mempro = 9;
público:
void fn ()

cout<
;
//Classe derivada
Classe Dercla: Public CLA

público:
int dermem = mempro;
;
int main ()

CLA OBJ;
obj.fn ();
Dercla DeRobj;
cout<retornar 0;

A saída é:

5
9

No CLA da classe, a variável MEMP, é vista no ponto de declaração. Depois disso, a parte curta de "protegida" é ignorada e vista novamente no bloco de funções de membro da classe. A classe derivada é ignorada e vista novamente no escopo da função principal () (bloco).

No CLA da classe, a variável, mempro, é vista no ponto de declaração. A parte da função pública fn () é ignorada e depois vista no bloco de descrição de classe derivada. É visto novamente na função principal ().

Operador de resolução de escopo

O operador de resolução de escopo em C ++ é :: . É usado para acessar um membro estático da classe. O programa a seguir ilustra o seguinte:

#incluir
usando namespace std;
CLA CLA

público:
estático int const Mem = 5;
público:
estático void fn ()

cout<
;
int main ()

cout<Cla :: fn ();
retornar 0;

A saída é:

5
5

Os membros estáticos são vistos no bloco de função principal (), acessados ​​usando o operador de resolução de escopo.

Escopo de enumeração

Enumeração não esclarecida

Considere o seguinte IF-Block:

se (1 == 1)

enum a, b, c = b+2;
cout<

A saída é:

0 1 3

A primeira linha no bloco é uma enumeração; A, B e C são seus enumeradores. O escopo de um enumerador começa desde o ponto de sua declaração, até o final do bloco anexante da enumeração.

A declaração a seguir não será compilada porque o ponto de declaração de C é depois da de A:

enum a = c+2, b, c;

O segmento de código a seguir não será compilado porque os enumeradores são acessados ​​após o bloco anexante da enumeração:

se (1 == 1)

enum a, b, c = b+2;

cout<

A enumeração anterior é descrita como uma enumeração não escondida, e seus enumeradores são definidos como enumeradores não escondidos. Isso ocorre porque começa apenas com a palavra reservada, enum. As enumerações que começam com a classe Enum ou enum struct são descritas como enumerações escopinhas. Seus enumeradores são definidos como enumeradores de escopo.

Enumeração escopo

A declaração a seguir está OK:

classe enum nam a, b, c = b+2;

Este é um exemplo de enumeração escopo. O nome da classe é Nam. Aqui, o escopo do enumerador começa desde o ponto de declaração até o final da definição de enumeração e não o fim do bloco anexante para a enumeração. O código a seguir não será compilação:

se (1 == 1)

classe enum nam a, b, c = b+2;
cout<

Uso simples de enumeração escopo

O código a seguir mostra uma maneira simples de usar a enumeração escopo:

se (1 == 1)

enum nam a, b, c = b+2;
cout << c << endl; //simple usage

A saída é 3, pois B é 1 ('a' é 0).

Variável global

Uma variável global é uma variável declarada no escopo global. Quando um programador começa a digitar um arquivo, esse é o escopo global. Considere o seguinte programa:

#incluir
usando namespace std;
char va = 'a';
int main ()

cout <cout <<::va<<'\n';
retornar 0;

A saída é:

A
A

Neste programa, a parte ou o escopo do VA começa no ponto de declaração do VA e continua para baixo até o final da unidade de tradução (arquivo).

O corpo da função principal () é um escopo diferente por si só; O escopo global ninhos no escopo da função principal ().

A variável VA é uma variável de escopo global ou simplesmente variável global, porque pode ser vista em todo o arquivo, começando de onde foi declarada. Pode ser visto no escopo da função principal ().

Para acessar uma variável global (variável do escopo global) de um escopo diferente, o nome da variável é usado diretamente ou precedido pelo operador de resolução de escopo, :: Como mostrado no programa acima.

A declaração se, enquanto, para, para, ou switch pode definir um bloco. Essa declaração é uma declaração composta. O nome de uma variável declarada em um bloco tem o escopo de um bloco. Seu escopo começa em seu ponto de declaração e termina no final de seu bloco. O programa curto a seguir ilustra isso para a variável, identificador:

#incluir
usando namespace std;
int main ()

se (1 == 1)

/*Algumas declarações*/
int identd = 5;
cout</*Algumas declarações*/

retornar 0;

Uma variável, como o identificador, declarado no escopo do bloco é uma variável local.

Uma variável declarada fora do escopo do bloco e acima pode ser vista no cabeçalho do bloco (e.g., condição para se bloqueio) e dentro do bloco. O programa curto a seguir ilustra isso para a variável, Identif:

#incluir
usando namespace std;
int main ()

int identif = 8;
if (identif == 8)

cout<
retornar 0;

A saída é,

8

Existem dois escopos de bloco aqui: o bloco para a função principal () e a declaração aninhada if composta. O bloco aninhado é o escopo potencial do bloco de função principal ().

Uma declaração introduzida em um escopo de bloco não pode ser vista fora do bloco. O programa curto a seguir, que não compila, ilustra isso com a variável, variab:

#incluir
usando namespace std;
int main ()

se (1 == 1)

int variab = 15;

cout<retornar 0;

O compilador produz uma mensagem de erro para variab.

Uma entidade introduzida, declarada no cabeçalho de uma função composta, não pode ser vista fora (abaixo) a declaração composta. O seguinte código de loop não compilará, resultando em uma mensagem de erro:

#incluir
usando namespace std;
int main ()

para (int i = 0; i<4; ++i)

cout<
cout<retornar 0;

A variável de iteração, i, é vista dentro do bloco de loop, mas não fora do bloco de loop for.

Uma variável declarada no escopo global é uma variável global. Pode ser visto dentro de um escopo de bloco. O programa a seguir ilustra o seguinte:

#incluir
usando namespace std;
int glb = 5;
int main ()

cout << glb << endl;
retornar 0;

A saída é 5.

Reatribuição não permitida no escopo global

No programa anterior, a declaração:

int glb = 5;

É uma declaração com inicialização (primeira atribuição de valor) simultaneamente. No programa a seguir, a declaração "int glb"; zero atribuído a ele por padrão. A linha após (Glb = 5;) tenta a reatribuição do valor, 5, no escopo global. Isso cria um erro, e o programa não compila. O programa é:

#incluir
usando namespace std;
int glb;
glb = 5;
int main ()

cout << glb << endl;
retornar 0;

No entanto, a reatribuição ocorrerá em um escopo local (bloco), conforme mostrado no seguinte programa:

#incluir
usando namespace std;
int glb;
int main ()

if (1 == 1)
glb = 5;
cout << glb << endl;

retornar 0;

A saída é 5.

Ponteiro global

Quando um ponteiro é declarado no escopo global, ele pode ser visto em um escopo aninhado. Um ponteiro declarado em um escopo aninhado não pode ser visto fora do escopo aninhado. Existem duas maneiras de declarar um ponteiro. Um ponteiro pode ser declarado com uma tarefa prática (de um endereço). Um ponteiro pode ser declarado sem uma tarefa prática. Se o ponteiro for declarado sem atribuição prática no escopo global, não poderá ser transferido no escopo global. No entanto, neste caso, pode ser transferido em um escopo aninhado.

Array global

Quando uma matriz é declarada no escopo global, ela pode ser vista em um escopo aninhado. Uma matriz declarada em um escopo aninhado, não pode ser visto fora do escopo aninhado. Existem duas maneiras de declarar uma matriz. Uma matriz pode ser declarada com uma tarefa prática (de um endereço). Uma matriz pode ser declarada sem atribuição prática. Se a matriz for declarada sem atribuição prática no escopo global, ela não poderá ser transferida no escopo global. No entanto, pode ser transferido em um escopo aninhado (elemento por elemento).

Escopo de parâmetro de modelo

O escopo normal de um nome de parâmetro de modelo começa desde o ponto de declaração até o final de seu bloco, como no exemplo a seguir:

modelo Estrutura idades

T John = 11;
U Peter = 12.3;
T Mary = 13;
U alegria = 14.6;
;

U e t são vistos dentro do bloco.

Para um protótipo de função de modelo, o escopo começa desde o ponto de declaração até o final da lista de parâmetros da função, como na seguinte declaração:

modelo Func void (t Não, U Cha, const char *str);

No entanto, quando se trata da descrição da classe (definição), o escopo também pode ter partes diferentes, como no programa de exemplo a seguir:

#incluir
usando namespace std;
modelo CLASSE THECLA

público:
T num;
estático u ch;
Void Func (U Cha, Const Char *str)

cout << "There are " << num << " books worth " << cha << str << " in the store." << '\n';

Função de vazio estático (U CH)

if (ch == 'a')
cout << "Official static member function" << '\n';

;
int main ()

THECLA obj;
obj.num = 12;
obj.func ('$', "500");
retornar 0;

Nome escondido

Um exemplo de esconder. O programa a seguir ilustra o seguinte:

#incluir
usando namespace std;
void fn ()

int var = 3;
se (1 == 1)

int var = 4;
cout<
cout<
int main ()

fn ();
retornar 0;

A saída é:

4
3

É porque o VAR no bloco aninhado hid var no bloco externo.

Possibilidade de repetir a declaração no mesmo escopo

O ponto da declaração é onde o nome é introduzido (pela primeira vez) em seu escopo.

Protótipo da função

Entidades diferentes, mesmo de tipos diferentes, normalmente não podem ser declaradas no mesmo escopo. No entanto, um protótipo de função pode ser declarado mais de uma vez no mesmo escopo. O programa a seguir com dois protótipos de função e a definição de função correspondente ilustra isso:

#incluir
usando namespace std;
void fn (int num);
void fn (int num);
void fn (int num)

cout<
int main ()

fn (5);
retornar 0;

O programa funciona.

Funções sobrecarregadas

Funções sobrecarregadas são funções com o mesmo nome, mas com diferentes assinaturas de função. Como outra exceção, funções sobrecarregadas com o mesmo nome podem ser definidas no mesmo escopo. O programa a seguir ilustra o seguinte:

#incluir
usando namespace std;
void fn (int num)

cout<
void fn (flutuação não)

cout<
int main ()

fn (5);
flutuar FLT = 8.7;
fn (FLT);
retornar 0;

A saída é:

5
8.7

As funções sobrecarregadas foram definidas no escopo global.

Escopo de namespace

Como duas variáveis ​​diferentes podem ter o mesmo nome e diferenciá -las, as variáveis ​​precisam ser declaradas em dois namespaces diferentes. Um espaço para nome é um bloco com um nome, tendo suas próprias entidades nomeadas. O nome de um namespace é o nome do bloco. Dois namespaces diferentes podem ter entidades com os mesmos nomes. O programa a seguir ilustra o seguinte:

#incluir
usando namespace std;
namespace na

CHAR CH1;
char ch2 = 'q';

namespace nb

CHAR CH1;
char ch2 = 'y';

int main ()

Na :: ch1 = 'p';
cout << NA::ch1 << endl;
Nb :: ch1 = 'x';
cout << NB::ch1 << endl;
retornar 0;

A saída é:

P
X

Existem dois espaços de nome: NA e NB. O espaço predefinido para NA é o seu bloco. O espaço predefinido para NB também é seu bloco. Observe que as entidades nos dois blocos diferentes têm os mesmos nomes. Para declarar um espaço para nome, comece com a palavra reservada, namespace; Um espaço segue, depois o bloco com suas entidades.

Para acessar uma entidade fora do bloqueio de namespace, comece com o nome do espaço para nome. Isto é seguido pelo operador de resolução de escopo e depois pelo nome da entidade.

O escopo da variável, na :: ch1, começa a partir do ponto de declaração de CH1 no bloco Na. Termina no final do bloco NA e depois aparece em qualquer linha fora (e abaixo) do bloco, onde "na ::" é usado. O escopo da variável, NB :: CH1, começa a partir do ponto de declaração de CH1 no bloco NB. Termina no final do bloco NB e aparece em qualquer linha externa (e abaixo) do bloco, onde "NB ::" é usado.

Um escopo de namespace refere -se a uma entidade declarada no bloqueio de namespace. O escopo da entidade do espaço para nome é o bloco de namespace e qualquer linha fora do bloco que usa o nome do namespace.

Escopo em diferentes porções

A classe anterior e os escopos de namespace ilustraram como um escopo pode ser em diferentes partes do texto do programa. Outro bom exemplo é o especificador de amigo.

Especificador de amigo

Se a classe C for declarada como um amigo da Classe A, na definição da classe A, todas as funções públicas de Membro da Classe C poderão acessar os membros de dados privados (e funções de membro privado) da classe A. O programa a seguir ilustra o seguinte:

#incluir
usando namespace std;
classe A
Privado: int d = 5;
Amigo Classe C;
;
classe B
/*
public: int fb ()
A a;
retornar a.d;

*/
;
classe C
public: int fc ()
A a;
retornar a.d;

;
int main ()

A a;
B b;
C c;
// int ret1 = b.fb ();
int ret2 = c.fc ();
cout << ret2 << endl;
retornar 0;

A saída é 5. Na definição de classe A, a classe C é declarada como um amigo da classe A. Portanto, Fc () da definição de classe C pode ver D da definição de classe A. O programa compila. Se os símbolos de comentários forem removidos, o programa não será compilado porque a classe B não foi declarada um amigo para a classe A.

O escopo da variável privada B começa a partir de seu ponto de declaração e termina no final do bloco Classe A. Ele também aparece na função fc () na classe C, que é um amigo da classe A. As duas porções para o escopo são o bloco Classe A e o Bloco de Função Fc ().

Conclusão

Um escopo é uma região declarativa. Uma região declarativa é a maior parte de um texto do programa no qual o nome de uma entidade é válido. Pode ser dividido em mais de uma parte com certos esquemas de programação, como blocos aninhados. As partes que não têm o ponto de declaração formam o escopo potencial. O escopo potencial pode ou não ter a declaração.