You are on page 1of 139

c 


 
V
V
P  V
V M VVV
 V
V ’  V V  VV V
V Ã   V
V   V
V P VVVV
V
M
  V
V M  VVÃ  V
V  VV
V  VV
V
    
 V
V   V
V ½  VV V
V    V
V  V  V
V M  VV V
V  V  VV V
V
 

   


 V
V Ã  VV
V Ã  VV
V £ VV V
V    !  V
V

   

 V
V   V
V è  V
V M" V
V a  V  
V
V    V  V
V
P  

 V
V MVV½#V V V
V
V
V
V
V
V
V
V
V
V
V
V
V
V
V
V
V
V
c 

 


 
  

Este tutorial é para aquelas pessoas que querem aprender a programação em C + + e não necessariamente
têm qualquer conhecimento prévio de outras linguagens de programação. É claro que nenhum conhecimento de
outras linguagens de programação ou qualquer habilidade geral do computador pode ser útil para compreender
melhor este tutorial, embora não seja essencial.

Ele também é indicado para aqueles que precisam de uma pequena atualização sobre as novas funcionalidades
da linguagem adquiriu a partir da última normas.

Se você estiver familiarizado com a linguagem C, você pode tirar as três primeiras partes deste tutorial como
uma revisão de conceitos, uma vez que explicar, principalmente a parte C do C + +. Existem pequenas
diferenças na sintaxe C + + para algumas funções C, assim que eu ainda recomendo que você lê-los.

A parte 4 descreve programação orientada a objetos.

A parte quinto maior parte descreve as novas funcionalidades introduzidas pelo ANSI-C + + padrão. V

M
 
V
× tutorial está dividido em seis partes principais, e cada parte é dividida em várias secções que cobrem cada
um tópico específico.Você pode acessar diretamente qualquer seção do índice de seção disponíveis na barra do
lado esquerdo, ou começar o tutorial a partir de qualquer ponto e seguir os links na parte inferior de cada
seção.

Muitas seções incluem exemplos que descrevem a utilização do conhecimento adquirido no capítulo. É
recomendado que você leia esses exemplos e ser capaz de compreender cada uma das linhas de código que a
constituem, antes de passar para o próximo capítulo.

Uma boa maneira de adquirir experiência com uma linguagem de programação, modificando e acrescentando
novas funcionalidades no seu próprio país para os programas de exemplo que você entendeu. Não tenha medo
de modificar os exemplos fornecidos com este tutorial, que é a maneira de aprender!V

à 

 
V
× ANSI-C + + padrão de aceitação como padrão internacional é relativamente recente. Foi publicado pela
primeira vez em Novembro de 1997, e revisto em 2003. No entanto, a linguagem C + + existe desde muito
tempo antes (1980). Portanto, há muitos compiladores que não suportam todos os novos recursos incluídos em
ANSI-C + +, especialmente aqueles que são liberados antes da publicação da norma.

Este tutorial é pensado para ser seguido com compiladores modernos que suportam, pelo menos em algum
grau-ANSI-C + + especificações. Encorajo-vos a conseguir um se o seu não está adaptado. Há muitas opções,
tanto comerciais como livres.V

à  
 V
×s exemplos incluídos neste tutorial são todos os  

    . Isso significa que usar o texto para
se comunicar com o usuário e para mostrar seus resultados.

Todos os compiladores C + + apoio à elaboração de programas de console. Consulte o manual do usuário do


seu compilador para obter mais informação sobre como compilá-los. V
V
M
  


Provavelmente a melhor maneira para começar a aprender uma linguagem de programação é escrever um
programa. Portanto, fica aqui o nosso primeiro programa:V

à   
        $% 
&

  
   

    !

" #$% 
&# '

 
 (')
D
*
à(

× primeiro painel (em azul) mostra o código fonte para o nosso primeiro programa. × segundo (em cinza claro)
mostra o resultado do programa quando compilado e executado. À esquerda, os números em cinza
representam os números de linha - estas não fazem parte do programa, e são mostrados aqui apenas para fins
informativos.

A maneira de editar e compilar um programa depende do compilador você está usando. Dependendo se ele tem
uma interface de desenvolvimento ou não e sobre a sua versão. Consulte a secção de compiladores e do
manual ou de ajuda que acompanha o seu compilador, se você tem dúvidas sobre como compilar um C + +
console programa.

× programa anterior é o típico programa que os aprendizes programador escrever pela primeira vez, e seu
resultado é a impressão na tela do "×lá Mundo!" frase. É um dos mais simples programas que podem ser
escritas em C + +, mas já contém os componentes fundamentais que cada programa C + + tem. Vamos olhar
linha por linha o código já escrevemos:

  
       
Esta é uma linha de comentário. Todas as linhas que começam com duas barras (   ) são
consideradas comentários e não têm qualquer efeito sobre o comportamento do programa. ×
programador poderá usá-los para incluir explicações ou observações curtas dentro do próprio código
fonte. Neste caso, a linha é uma breve descrição do que é o nosso programa.

   

Esta linha corresponde ao início da definição da função principal. A função principal é o ponto por onde
todos os programas C + + iniciar a sua execução, independentemente da sua localização dentro do
código fonte. Não importa se existem outras funções com outros nomes definidos antes ou depois dela -
as instruções contidas dentro da função esta definição será sempre os primeiros a ser executado em
qualquer programa C + +. Pelo mesmo motivo, é essencial que todos os programas C + + tem
um m m função.

A palavra   é seguido do código por um par de parênteses (  ). Isso é porque é uma


declaração de função: Em C + +, o que diferencia uma declaração de função de outros tipos de
expressões são esses parênteses que seguem o seu nome. ×pcionalmente, estes parênteses podem
incluir uma lista de parâmetros dentro deles.

Logo após estes parênteses, podemos encontrar o corpo da função principal entre chaves ( !) ). × que
está contido dentro destas chaves é que a função faz quando ele é executado.

" #$% 
&# '

Esta linha é um C + + declaração. A declaração é uma expressão simples ou composto que pode
realmente produzir algum efeito. Na verdade, esta afirmação só executa a ação que gera um efeito
visível no nosso primeiro programa.

+ ,
  -
 . é o nome do fluxo de saída padrão em C + +, eo significado de toda a
declaração é para inserir uma seqüência de caracteres (neste caso, o$% 
seqüência de
caracteres) para o fluxo de saída padrão ( a 
   , que normalmente corresponde à tela).

a 
   é declarada no 
 de arquivo padrão dentro do namespace, é por isso que
nós precisamos incluir esse arquivo específico e declarar que iríamos usar este espaço para nome
específico no início do nosso código.

×bserve que a instrução termina com um caractere ponto e vírgula ( ' ). Este caráter é usado para
marcar o final da instrução e, na verdade ele deve ser incluído ao final de todas as declarações de
expressão em todos os programas C + + (um dos erros de sintaxe mais comum é o fato de esquecer
de incluir alguns vírgula depois de uma instrução).


 ('
A instrução return faz com que a função principal para terminar. retorno pode ser seguido por um
código de retorno (no nosso exemplo é seguido pelo código de retorno com um valor de zero). Um
código de retorno  para a m m função é geralmente interpretado como o programa funcionou
como o esperado, sem quaisquer erros durante sua execução. Esta é a forma mais usual para acabar
com a C + + console programa.

Você deve ter notado que nem todas as linhas deste programa executar ações quando o código é
executado. Havia linhas contendo apenas comentários (aquelas iniciadas por   ). Havia linhas com as
directivas para o compilador do pré-processador (aquelas iniciadas por  ). Então havia as linhas que começou
a declaração de uma função (neste caso, a função principal) e, finalmente, as linhas com as declarações (como
a inserção no  ), que foram incluídas dentro do bloco delimitado por chaves ( !) ) do a função principal.

× programa foi estruturado em duas linhas diferentes, a fim de ser mais legível, mas em C + +, não temos
regras rígidas sobre como separar instruções em linhas diferentes. Por exemplo, em vez deV

à     !

 " #$% 
&# '


 (')


Poderíamos ter escrito:

    !

" #$% 
&# '


 (')

Tudo em apenas uma linha e isso teria exatamente o mesmo significado que o código anterior.

Em C + +, a separação entre as afirmações é especificado com um ponto e vírgula final ( ' ) no final de cada
um, portanto a separação em diferentes linhas de código não importa a todos para essa finalidade. Podemos
escrever muitas declarações por linha ou escrever uma única instrução que leva muitas linhas de código. A
divisão do código em linhas diferentes, só serve para tornar mais legíveis e esquema para os seres humanos
que podem lê-lo.

Vamos adicionar uma instrução adicional para o nosso primeiro programa:

à   
 
       $% 
& /

     

  
  

    !

" #$% 
&# '
 " #/

     # '
 
 ('
D )
*
à(
àà
à

Neste caso, foi realizada em duas inserções de corte em duas declarações diferentes. Mais uma vez, a
separação em diferentes linhas de código foi feito apenas para dar maior legibilidade ao programa,
desde m m poderia ter sido perfeitamente válido definido desta maneira:
    !
" #$% 
&# '
" #/

     # '

 ('
)

Fomos também a liberdade de dividir o código em linhas mais se considerou mais conveniente:

à     !

 "#$% 
&# '
 " #/

     # '
 
 ('
 )

D

E o resultado teria sido de novo exatamente como nos exemplos anteriores.

directivas Preprocessor (aquelas que começam por  ) estão fora dessa regra geral, uma vez que não são
declarações. São linhas lido e processado pelo pré-processador e não produzem qualquer código por si
só. directivas Preprocessor devem ser especificados em sua própria linha e não tem que terminar com um
ponto e vírgula ( ' ).

à   V

×s comentários são partes do código-fonte desconsiderados pelo compilador. Eles simplesmente não fazer
nada. × seu objectivo é apenas permitir que o programador para inserir notas ou descrições dentro do código
fonte.

C + + suporta duas maneiras para inserir comentários: V

à   0    % 


  1  %   , 

× primeiro deles, conhecido como linha de comentário, as devoluções de tudo, desde onde o par de barras ( 
 ) encontra-se até ao final da mesma linha. × segundo, conhecido como bloco de comentário, descarta tudo
entre os  1 personagens ea primeira aparição do 1  personagens, com a possibilidade de incluir mais de uma
linha.
Estamos indo para adicionar comentários ao nosso segundo programa:

à  1 
 
           %  1  $% 
& /

     

  
  

    !

" #$% 
&# '    2  $% 
& 
 " #3


      # '     /

  
  
 
 ('
)
à
àà
à

Se você incluir comentários dentro do código fonte dos seus programas sem usar o comentário combinações de
caracteres   ,  1 e 1  , o compilador irá tomá-los como se fossem C + + expressões, mais provável a
causar uma ou várias mensagens de erro quando você compilar .
P 
Ã
P 
à 

A biblioteca C + + inclui as mesmas definições como a biblioteca em linguagem C organizados na mesma


estrutura de arquivos de cabeçalho, com as seguintes diferenças:V

>V Cada arquivo de cabeçalho tem o mesmo nome que a versão da linguagem C, mas com um "  "prefixo
e sem extensão. Por exemplo, o C + + equivalente para a linguagem de cabeçalho do arquivo
C  , é  , .V
>V Cada elemento da biblioteca é definido dentro do  namespace.

No entanto, para compatibilidade com C, o tradicional cabeçalho nomes   (como  , ) também está
disponível com as mesmas definições dentro do namespace global. Nos exemplos apresentados nesta
referência, esta versão é usada para que os exemplos são totalmente compatíveis com C, embora seu uso seja
substituído em C + +.

Existem também algumas alterações pontuais no C + + aplicação:V

>V l 4 é um tipo fundamental em C + + e, portanto, não aparece como um tipo definido nos arquivos
de cabeçalho correspondentes onde ele aparece em C. × mesmo se aplica a várias macros introduzida
pela alteração de 1 a IS× C no cabeçalho do arquivo   , que são palavras-chave em C + +.V
>V As funções seguintes alterações nas suas declarações relacionadas ao constness de seus
parâmetros: strchr , strpbrk ,strrchr , strstr , memchr .
>V As funções atexit , saída e abortar , definido no < cstdlib > Tem adições ao seu comportamento em C +
+.
>V versões sobrecarregadas de algumas funções são fornecidas com outros tipos de parâmetros ea mesma
semântica, como" e  
, versões das funções no CMATH arquivo de cabeçalho, ou 
 versões para abs e div .

 
 
V
C + + inclui a biblioteca C, como descrito pela norma IS× 1990 e sua emenda n º 1 (IS× / IEC 9899:1990 e
IS× / IEC 9899:1990 / DAM 1). Algumas introduções feitas na norma IS× 1999 não são compatíveis com o
padrão C + +. V

Ã

 V


 Biblioteca C Diagnostics (cabeçalho)

   Personagem funções de manipulação (cabeçalho)

   C erros (cabeçalho)

!
!
 Características dos tipos de ponto flutuante (cabeçalho)

 "#" "#" IS× 646 grafias alternativas operador (cabeçalho)

 Tamanhos dos tipos integrais (cabeçalho)

 
 
 C biblioteca de localização (cabeçalho)

à 
 Biblioteca C numéricos (cabeçalho)

$ $  local não pula (cabeçalho)



 biblioteca C para lidar com sinais (cabeçalho)


 tratamento de argumentos variável (cabeçalho)

!! Standard definições C (cabeçalho)

   biblioteca C para executar / ×utput operações de entrada (cabeçalho)

 Standard C Library General Utilitários (cabeçalho)

   C Strings (cabeçalho)

 C Time Library (cabeçalho)

Alteração 1 para IS×-C 90 adicionada dois conectores adicionais: l e l5 .

 !
função

 

"    1 " 6  '

c 
 ! 

 

 

Escreve para a saída padrão (stdout) uma seqüência de dados formatados como o Ñ   argumento
especifica. Após o Ñ  
parâmetro, a função espera que pelo menos tantos argumentos adicionais,
conforme especificado no Ñ   . V


% V
formato

String que contém o texto a ser escrito para 


 .
Ele pode, opcionalmente conter incorporado marcas de formatação que são substituídos pelos valores
especificados no argumento subseqüente (s) e formatado conforme solicitado.
× número de argumentos a seguir o Ñ  
parâmetros deve ser pelo menos tanto quanto o
número de marcas de formatação.
As marcas de formatação de seguir este protótipo:

È 789 7l 9 7 :  ;9 7


.;9   " 
×nde
m
Ñ  é o mais importante e define o tipo ea interpretação do valor do argumento
corespondente:

? ? &

 M  

 Caracteres


 ou Inteiro decimal *

*
A notação científica (mantise / expoente) usando caráter


*3
3 A notação científica (mantise / expoente) usando 3 personagem


" Decimais de ponto flutuante *

 Use o menor de È ou È " *

< Use o menor de 3È ou È " *


 Unsigned octal à(

 Cadeia de caracteres  

Inteiro sem sinal decimal 

= Inteiro sem sinal hexadecimal "

> Inteiro sem sinal hexadecimal (maiúsculas) "

?D((@
endereço do ponteiro
((((

Nada impresso. × argumento deve ser um ponteiro para um assinado  ,



onde o número de caracteres escritos até então é armazenada.

È Uma È6 seguido por outro È personagem vai escrever È para 


 . È

A marca também podem conter  


,    , m
  e  Ñ 

sub-
especificadores, que são opcionais e seguir as seguintes especificações:

u ?  ' 

Deixou de justificar dentro da largura do campo determinado; direito justificação é o padrão


M
(ver    sub-especificador).

Forças de preceder o resultado com um ou menos sinal de adição (  ou M ), mesmo para


 números positivos. Por padrão, somente os números negativos são precedidos por um M
sinal.

3 m Se nenhum sinal de que vai ser escrito, um espaço em branco é inserida antes do valor.

Usado com  , = ou > especificadores o valor é precedido de ( , (= ou (> , respectivamente,


para valores diferentes de zero.
Usado com , 3 e " , que força a saída escrita para conter um ponto decimal, mesmo se
 nenhum dígito se seguiria. Por padrão, se nenhum dígito seguir, sem ponto decimal é
escrita.
Usado com  ou < , o resultado é o mesmo que com ou 3 , mas os zeros à direita não são
removidos.

Left-pad o número com zeros ( ( ) em vez de espaços, onde o preenchimento é especificado


(
(ver    sub-especificador).


 ' 

Número mínimo de caracteres a serem impressos. Se o valor a ser impresso for menor que
3
 este número, o resultado será preenchido com espaços em branco. × valor não é truncado,
mesmo se o resultado for maior.

A    não é especificado no Ñ  
string, mas como um valor inteiro argumento
1
adicional que precede o argumento de que tem que ser formatada.

À
' 
? 

Para especificadores inteiro (  , ,  ,


, = , > ): m
  especifica o número mínimo de
 

dígitos para ser escrito. Se o valor a ser escrito é inferior a este número, o resultado será
preenchido com zeros à esquerda. × valor não é truncado, mesmo se o resultado for
maior. A m
  de ( significa que nenhum personagem foi escrito para o valor ( .
Por , 3 e " especificadores: este é o número de dígitos a ser impresso
( o ponto
decimal.
Para  e < especificadores: Este é o número máximo de dígitos significativos a serem
impressas.
Para  : este é o número máximo de caracteres a ser impresso. Por padrão, todos os
caracteres são impressos até o caractere nulo final é encontrado.
Para  tipo: ele não tem efeito.
Quando nenhuma m
  for especificada, o padrão é à . Se o prazo for especificado sem
um valor explícito para m
  , ( é assumido.

A m
  não é especificada no Ñ  
string, mas como um valor inteiro argumento
1
adicional que precede o argumento de que tem que ser formatada.

  ?  ' 

× argumento é interpretado como um    ou   


   (só se aplica

aos especificadores inteiro: ,  ,  ,
, = e > ).

× argumento é interpretado como um   ou  


   para
 especificadores de inteiros ( ,  ,  ,
, = e > ), e como um caractere de largura ou
seqüência de caracteres de largura para especificadores  e  .

× argumento é interpretado como uma 


 
    (só se aplica aos
0
especificadores de ponto flutuante: 3 , 3 , " ,  e < ).

argumentos adicionais

Dependendo do Ñ   string, a função pode esperar uma seqüência de argumentos adicionais, cada
uma contendo um valor a ser inserido em vez de cada È de tag-especificado no Ñ  
parâmetro,
se houver. Deve haver o mesmo número de esses argumentos como o número de È -tags que esperam
um valor.

’
   V
Em caso de sucesso, o número total de caracteres escritos é retornado.
Em caso de falha, um número negativo é retornado.V

M  V
à  1 3=   1  "
  


     !
"  #:  @È È  A # 6 BB 6  ' "  #   @È È  A # 6 à*6

((((0 '
 "  #  6   .  , @È à( A # 6 à* ' "  #  6 
 C @ (à(DÈ A # 6 à* '
D "  #E
  =   "  @È È =È È   È = A  $ # 6 à((6 à((6 à((6 à((6
* à(( '
à( "  #"

@  (6(È " A 3È È# 6 6àà6 6àà6 6àà '
àà "  # 0 
 
F
@ 1È  A  # 6 6 à( ' "  #È A  # 6 #G  FHI  
  # '
à
à 
 (')
à
à

V

!
função

 

 "   1 " 6  '


 
 ! 

 
 


'

Lê dados de   e armazena-os de acordo com o parâmetro de Ñ   para os locais apontados pelos
argumentos adicionais. ×s argumentos adicionais devem apontar para objetos alocados já do tipo especificado
pela tag de formato correspondente no Ñ  
string.V


% V
formato

C string que contém um ou mais dos seguintes itens:

>V 


 
 ) a função vai ler e ignorar todos os caracteres em branco (o que
inclui espaços em branco e da nova linha e caracteres de tabulação), que são encontrados
antes do não-branco próximo caractere. Isto inclui qualquer quantidade de caracteres em
branco, ou nenhuma.
>V Ã

 ' *
 + 
  
,) Qualquer personagem que
não é um caractere em branco (newline, espaço em branco ou tabulação) ou parte de um
especificador de formato (que começam com um È do personagem) faz a função de ler o
próximo caractere a partir de   , compará-lo com este espaço em branco sem carácter e se
coincidir, ele é descartado ea função continua com o próximo caracter do Ñ   . Se o
personagem não corresponder, a função falhar, retornando e deixando os caracteres
subseqüentes de   não lidas.
>V × !
 ! 
 ) uma seqüência formada por um sinal de porcentagem inicial
( È ) indica um especificador de formato, que é usado para especificar o tipo e formato dos
dados a serem recuperados a partir de   e armazenados nos locais apontados pelos
argumentos adicionais. Um especificador de formato segue este protótipo:

largura %[*][] [modificadores tipo]

onde:

Uma partida asterisco opcional indica que os dados estão a ser recuperados a
ù partir de   , mas ignorado, ou seja, não é armazenada no argumento
correspondente.

   Especifica o número máximo de caracteres a ser lido na operação de leitura atual

Especifica um tamanho diferente de  (no caso de  , e  ),


  
 (no caso de  ,
e = ) ou " (no caso de , " e  ) para os dados
apontados pela argumento adicional correspondente:
 Ñ 
)   (para  , e  ), ou   
   (para  ,
e = )
)  (para  , e  ), ou
     (para  ,
e = ),
ou 
 (para , " e  )
) 
, (por , " e  )

Um personagem especificando o tipo de dados a serem lidos e como é esperado


m
para ser lido. Veja a tabela seguinte.

>V
  !
 
!)

 
  -
!
' M 



  

.  ) Lê o próximo caractere. Se uma    diferente
de 1 for especificado, a função lê    caracteres e armazena-os
  1
nos locais sucessivos do array passado como argumento. Nenhum
caractere nulo é acrescentado no final.

x
  ) Número opcionalmente precedido de um  ou M
  1
sinal.

 !
) número decimal contendo um ponto decimal,
opcionalmente precedido de um  ou M assinar e, opcionalmente,
,3,",,< " 1
pela folowed ou 3 caractere e um número decimal. Dois
exemplos de entradas válidas são -732,103 e 7.12e4

 ×
  .  1

& /0 


 . Isto irá ler os caracteres
subseqüentes até um espaço em branco é encontrado (caracteres
  1
em branco são considerados de nova linha, em branco e
tabulação).


  

Inteiro sem sinal decimal.
 1

=,> Hexadecimal inteiro.  1

argumentos adicionais

A função espera uma seqüência de referências como argumentos adicionais, cada um apontando para
um objeto do tipo especificado por suas respectivas È de tag-no Ñ  
cadeia, na mesma ordem.
Para cada especificador de formato no Ñ  
string que recupera dados, um argumento adicional
deve ser especificado.
Estes argumentos são esperados ser referências (ponteiros): se você deseja armazenar o resultado de
um "" operação em uma variável regular você deve preceder o seu identificador com o m
  


Ñ
 , ou seja, um sinal de E comercial ( € ), como em:

 '
" #È #6 €  '

’
   V
Em caso de sucesso, a função retorna o número de itens lidos com êxito. Esta contagem pode igualar o número
esperado de leituras ou menos, até zero, se uma falha de correspondência acontece.
No caso de uma falha de entrada antes de qualquer dado pode ser lido com sucesso, E×F é retornado.V

M  V
à  1 3=   " 
  


     !
  7D(9'

 '
 "  #D   
  "J @# '
 "  #È # 6  '
D
* "  #D   
  @# '
à( "  #È # 6 € '
àà
"  #È  / 6È    A# 6  6 ' "  #D  
 K   =  @# '
à
"  #È =# 6 € ' "  #LI   
=È  È   A# 6 6 '
à
à 
 (')
à
à
à
àD
à*

V
V
’
 x
 
A utilidade do A  A programas mostrados na seção anterior é bastante questionável. Tínhamos que
escrever várias linhas de código, compilá-los, e depois executar o programa resultante apenas para obter uma
simples frase escrita na tela como resultado. Certamente teria sido muito mais rápido digitar a frase de saída
por nós mesmos. No entanto, a programação não se limita apenas à impressão simples textos na tela. Para ir
um pouco mais adiante e tornar-se capaz de escrever programas que executam tarefas úteis que realmente
nos salvar de trabalho é necessário introduzir o conceito de  
 .

Vamos pensar que eu peço que você mantenha o número 5 em sua memória mental, e então eu pedir para
você memorizar também o número dois ao mesmo tempo. Você tem apenas dois valores diferentes
armazenados em sua memória. Agora, se eu pedir para você adicionar 1 para o primeiro número que eu disse,
você deve manter os 6 números (que é 5 +1) e 2 em sua memória. Valores que nós poderíamos agora, por
exemplo, subtrair e obter 4 como resultado.

× processo todo que você tem feito apenas com sua memória mental é um símile do que um computador pode
fazer com duas variáveis. × mesmo processo pode ser expresso em C + + com a seguinte instrução:V

à  M 6 , M '  M   à' 
 M  M ,'




×bviamente, este é um exemplo muito simples, já que usamos somente dois valores inteiros pequenos, mas
considere que o computador pode armazenar milhões de números como estes, ao mesmo tempo sofisticado e
realizar operações matemáticas com elas.

Portanto, podemos definir uma  


 como uma parte da memória para armazenar um valor determinado.

Cada variável precisa de um identificador que o distingue dos demais. Por exemplo, no código anterior
a 
 Ñ 

 
 foram
 , , e 
 , mas poderíamos ter chamado todos os nomes das
variáveis que queríamos inventar, enquanto eles estavam identificadores válidos.

c !
 V
Um 
 Ñ    é uma seqüência de uma ou mais letras, dígitos ou caracteres de sublinhado ( 4 ). Nem
espaços nem sinais de pontuação ou símbolos podem ser parte de um identificador. Somente letras, números e
caracteres de sublinhado simples são válidas. Além disso, os identificadores de variável sempre tem que
começar com uma letra. Eles também podem começar com um caractere sublinhado ( 4 ), mas em alguns
casos, estes podem ser reservados para determinadas palavras-chave compilador ou identificadores externos,
bem como identificadores, contendo dois sucessivos caracteres de sublinhado em qualquer lugar. Em nenhum
caso, pode começar com um dígito.

×utra regra que você tem que considerar ao inventar a sua própria identificadores é que eles não podem
corresponder a qualquer palavra-chave da linguagem C + + é específico, nem os seus compilador, que
são m  


  . As palavras-chave reservadas padrão são:

6 
6 ,6

6 6   
6  6  6 6 46  
6  ;6
=
6 "C 
6 5 46 
   6 
6 = J 6  =  .;6 = 6 "6
"6  6  6 6  6   6 6 6 
%N 6  .6 N   N6
    46   M 6 K, 6   6  
6  6  C "6
 46 % 6 
 l 6  6 6 O 6 5  " N  6   6 5 6
5  6
 ;6 ;  6
6 N 
6 
 l 46 N% 6 F


Além disso, representações alternativas para alguns operadores não podem ser usadas como identificadores,
uma vez que são palavras reservadas em algumas circunstâncias:
6 4 F6 ? E6 ? $ 6  6 ;6 = 4 F 
6  4 F6 = 4 F

Seu compilador pode também incluir algumas palavras-chave específicas adicionais reservados.

  
) A linguagem C + + é um A

  
A idioma. Isso significa que um identificador escrito
em letras maiúsculas não é equivalente a outro com o mesmo nome mas escrito em letras pequenas. Assim,
por exemplo, o ®3/G0+ED$ variável não é o mesmo que o 
 da variável ou o 
 da
variável. Estes são três identificadores de variáveis diferentes.V

 
 
 
 V
Durante a programação, nós armazenamos as variáveis na memória do nosso computador, mas o computador
tem que saber que tipo de dados que deseja armazenar nelas, pois não vai ocupar a mesma quantidade de
memória para armazenar um número simples de armazenar uma única letra ou um número grande, e eles não
vão ser interpretadas da mesma maneira.

A memória em nossos computadores são organizados em bytes. Um byte é a quantidade mínima de memória
que pode gerenciar em C + +. Um byte pode armazenar uma quantidade relativamente pequena de dados: um
único caractere ou um inteiro pequeno (geralmente um número inteiro entre 0 e 255). Além disso, o
computador pode manipular tipos de dados mais complexos que vêm do agrupamento de vários bytes, como
números de longo ou de números não-inteiros.

Em seguida você tem um resumo dos tipos de dados básicos fundamentais em C + +, bem como o intervalo de
valores que podem ser representados com cada um:V

1
  x'  2

1


 

assinado: -128 a 127


 Caráter ou pequeno inteiro. 1byte
assinado: 0 a 255

 assinado: -32.768-32.767
Curto inteiro. 2 bytes
  ( 
 ) assinado: 0-65.535

assinado: -2147483648 a
 Integer. 4bytes 2147483647
sem sinal: 0-4294967295

assinado: -2147483648 a

Long inteiro. 4bytes 2147483647
 (    )
sem sinal: 0-4294967295

Boolean valor. Pode levar um dos dois valores:


, 1byte N   ou "
verdadeiro ou falso.

"

 Número de ponto flutuante. 4bytes + / - 3,4 E + / - 38 (~ 7 dígitos)

+ / - 1.7e + / - 308 (~ 15

 Duplo precisão de ponto flutuante. 8bytes
dígitos)

+ / - 1.7e + / - 308 (~ 15
 
, Long precisão dupla de ponto flutuante. 8bytes
dígitos)

2  4
l 4 Wide personagem. Um caractere de largura
bytes

* ×s valores das colunas de  e


 dependem do sistema o programa é compilado. ×s valores
apresentados acima são os encontrados na maioria dos sistemas de 32 bits. Mas para outros sistemas, a
especificação geral é que  tem o tamanho natural sugerido pela arquitetura do sistema (uma Am A ) e
os quatro tipos inteiros  ,   ,  e  cada um deve ser pelo menos tão grande quanto o anterior
que, com  sendo sempre um byte de tamanho. × mesmo se aplica aos tipos de ponto
flutuante " , ,  e  
, , onde cada um deve fornecer pelo menos tanta precisão como o
anterior.

x

' 
V
A fim de usar uma variável em C + +, devemos primeiro declará-la especificando que tipo de dados que nós
queremos que ela seja. A sintaxe para declarar uma nova variável é escrever o especificador do tipo de dados
desejado (como bool, int, float ...) seguido por um identificador de variável válido. Por exemplo:V

à  '
 " N L C '

Estas são duas declarações válidas de variáveis. × primeiro declara uma variável do tipo  com o identificador
de  . × segundo declara uma variável do tipo Ñ com o identificador  

. Uma vez declarado, as
variáveis de  e  

pode ser usado no resto do seu âmbito de aplicação do programa.

Se você estiver indo para declarar mais de uma variável do mesmo tipo, você pode declarar todos eles em uma
única instrução, separando seus identificadores com vírgulas. Por exemplo:

 6 ,6 '

Este declara três variáveis (  ,  e  ), todas elas do tipo  , e tem exatamente o mesmo significado como:

à 
'
  ,6
  '

×s tipos de dados inteiros  ,   ,  e  pode ser assinado ou não assinado, dependendo da faixa de
números necessários para ser representado. Assinado tipos podem representar tanto valores positivos e
negativos, enquanto que os tipos sem sinal só pode representar valores positivos (e zero). Isso pode ser
especificado usando o especificador    ou o especificador    antes do nome do tipo. Por
exemplo:

à
      P
, $"/  '
    5E
? '

Por padrão, se não especificar    ou    compilador irá assumir a maioria das configurações do
tipo a ser assinado, por isso, em vez de a segunda declaração acima, poderíamos ter escrito:

 5E
? '

com exatamente o mesmo significado (com ou sem a palavra-chave   )

Uma exceção a essa regra geral é o  tipo, que existe por si só e é considerado um outro tipo de dados
fundamental da 
 e  
 , o pensamento para armazenar caracteres. Você deve usar
uma  
 ou    
 , se você pretende armazenar valores numéricos em  de tamanho
variável.


 e  pode ser usado sozinho como especificadores de tipo. Neste caso, eles se referem a seus direitos
fundamentais inteiro respectivos tipos:  
 é equivalente a  
 e  é equivalente a 
 . ×s dois seguintes declarações de variáveis são equivalentes:
à 
 E'
 
  '

Finalmente,   e    


 também pode ser usado como especificadores de tipo autônomo, o
que significa o mesmo que    e
    respectivamente. ×s dois seguintes declarações são
equivalentes:

à
   P =Q  '

    P =Q  '

Para ver o que as declarações de variáveis parecer em ação dentro de um programa, vamos ver o C + + código
do exemplo, sobre sua memória mental proposto no início desta seção:

à  3=  .;   N %N  

  
  


    !
     .;  N %N @
  6 ,'
D  
'
*
à(    @
àà  M 6 , M '  M   à' 
 M  M ,'
à
  3= ,  
@
à : "  
 '
à
à      @
à 
 ('
à )
àD
à*
(




Não se preocupe se algo mais do que as declarações de variáveis se parece um pouco estranho para você. Você
vai ver o resto em detalhes nas próximas seções.

! 

V
Todas as variáveis que pretendemos usar em um programa deve ter sido declarada com o especificador de tipo
em um ponto anterior no código, como fizemos no código anterior ao início do corpo da função principal,
quando declarou que  ,  , eo
   foram do tipo  .

Uma variável pode ser tanto de âmbito global ou local. Uma variável global é uma variável declarada no corpo
principal do código-fonte, fora de todas as funções, enquanto uma variável local é declarada dentro do corpo de
uma função ou um bloco.
As variáveis globais podem ser consultados de qualquer lugar do código, mesmo dentro de funções, sempre
que após a sua declaração.

× escopo das variáveis locais é limitado ao bloco entre chaves ( !) ), onde eles são declarados. Por exemplo, se
eles são declarados no início do corpo de uma função (como na função m m ), seu alcance é entre a sua
declaração e ponto final dessa função. No exemplo acima, isto significa que, se existia uma outra função além
da m m , as variáveis locais declaradas no m m não poderia ser acessado a partir da função de outro e
vice-versa.V

c 
3
' 
V
Ao declarar uma variável local normal, seu valor é, por padrão indeterminado. Mas você pode querer uma
variável para armazenar um valor concreto no mesmo momento em que é declarada. Para fazer isso, você
pode inicializar a variável. Há duas maneiras de fazer isso em C + +:

× primeiro, conhecido como  , é feito acrescentando um sinal de igual seguido do valor para
o qual a variável será inicializada:

  "     M   4N


'
Por exemplo, se quisermos declarar uma  variável chamada  inicializado com um valor de 0 no momento
em que for declarado, podemos escrever:V

  M ('

A outra maneira de inicializar variáveis, conhecido como    


 , é feito colocando o valor
inicial entre parênteses (  ):

     "     4N


'
Por exemplo:


 ( '

Ambas as maneiras de inicializar as variáveis são válidas e equivalentes em C + +.

à   R   C.;  N %N  

  
  

    !

  M '      N M 
  ,  '      N M 
  
'      N    
D
*  M   ' 
 M  M ,' 
  
'
à(

 ('
àà )
à
à
à
à
à
à

c  ' 4

 V
Variáveis que podem armazenar valores numéricos que não são mais do que um único personagem são
conhecidos como cordas.

A biblioteca C + + idioma oferece suporte para cordas através do padrão   classe. Este não é um tipo
fundamental, mas ele se comporta de forma semelhante como tipos fundamentais fizesse no seu uso mais
básico.

Uma primeira diferença com tipos de dados fundamental é que, a fim de declarar e utilizar objetos (variáveis)
desse tipo é preciso incluir um arquivo de cabeçalho adicionais em nosso código fonte:   e ter acesso
ao  namespace (que já tínhamos em todos os nossos programas anteriores graças à
 
   declaração).V

à   :     
3 S
    

  
  

    !
 5    M #3 S
  # '
 " 5  '

D 
 ('
* )
à(
àà

Como você pode ver no exemplo anterior, cordas pode ser inicializado com qualquer cadeia de caracteres válida
literal como variáveis do tipo numérica pode ser inicializado com qualquer literal numérico válido. Ambos os
formatos são válidos de inicialização com cordas:

à 5    M #3 S
  # ' 5     #3 S
  # '


Strings também podem executar todas as outras operações básicas que tipos de dados fundamentais pode,
gosta de ser declarada sem um valor inicial e que está sendo atribuído valores durante a execução:

à   :     

    



  
  

     !
   5 ' 5  M #3 S   K      # '
 " 5  '
D
* 5  M #3 S
  FHI    K  "   # '
à( " 5  '
àà
à 
 ('
à )
à
à




à 

à 
são expressões com um valor fixo.V


V
Ë
 são os tipos mais óbvios de constantes. Eles são usados para expressar valores específicos dentro do
código fonte do programa. Nós já usamos esses anteriormente para dar valores concretos para as variáveis ou
para expressar as mensagens que queríamos nossos programas para imprimir, por exemplo, quando escreveu:V

 M '

a  , neste pedaço de código era uma  



 .

Constantes literais podem ser divididos em 



   ,
m Ñ 


 ,  

,
 e 

 .

c 
 V
V

à à ( M





Eles são constantes numéricas que identificam decimal valores inteiros. Repare que para expressar uma
constante numérica não temos que escrever aspas ( # ) nem qualquer caractere especial:. Não há dúvida de
que é uma constante sempre que escreverà em um programa, estaremos nos referindo ao valor de 1776.

Além de números decimais (aqueles que todos nós estamos acostumados a usar todos os dias), C + + permite
o uso de números octais ( 
 ) e números hexadecimal ( 
!" ), como constantes literais. Se queremos
expressar um número octal temos de precedê-lo com um ( (um 
 caracteres). E a fim de expressar um
número hexadecimal que temos de precedê-lo com os caracteres (= ( 
 , # ). Por exemplo, o literal
seguintes constantes são todas equivalentes entre si:

à      
 (àà   
 (=,   =   

Todos estes representam o mesmo número: 75 (setenta e cinco), expressa como um número de base 10,
numeral numeral octal e hexadecimal, respectivamente.

constantes literais, como as variáveis, são considerados como um tipo de dados específico. Por padrão, literais
inteiros são do tipo . No entanto, pode forçar o sistema a ser assinado, anexando o  personagem para ela,
ou a longo prazo, acrescentando  :

à    
 

   
 0  

 
   


Em ambos os casos, o sufixo pode ser especificado usando letras maiúsculas ou minúsculas.

.   !


V
Eles expressam números com decimais e / ou expoentes. Eles podem incluir um ponto decimal a,
um personagem (que expressa "por dez na altura Xth", onde X é um valor inteiro que segue
o personagem), ou ambos um ponto decimal e um caráter:V

à 6àà*  6àà*
 (   6( = à( T 
 à Mà*  à6 = à( T Mà*
 6(  6(

São quatro números válidos com decimais, expresso em C + +. × primeiro número é PI, o segundo é o número
de Avogadro, a terceira é a carga elétrica de um elétron (um número extremamente pequeno), todos eles de
aproximação eo último é o número três, expressa em ponto flutuante literal numérico.

× tipo padrão para literais de ponto flutuante é m . Se você quer expressar explicitamente um Ñ ou 

numérico literal, você pode usar o " e  sufixos, respectivamente:

à àà*0   
,
 ( "   "

Qualquer das letras que podem ser parte de um ponto flutuante numérico constante ( , " ,  ) pode ser
escrita utilizando letras maiúsculas ou inferior, quer sem qualquer diferença em seus significados.

Ã

 
V
Existem também as constantes não-numéricos, como: V

à BUB
 B
 #$% 
#
# N NIV#


As duas primeiras expressões representam constantes único personagem, e os dois seguintes representam os
literais cadeia composta por vários personagens. ×bserve que para representar um único personagem que
colocá-lo entre aspas simples ( B ) e expressar uma seqüência de caracteres (que geralmente é composto por
mais de um personagem) que incluí-la entre aspas ( # ).

Ao escrever literais tanto caracter e string, é necessário colocar as aspas em torno deles para distingui-los dos
identificadores de variáveis possíveis, ou palavras-chave reservadas. ×bserve a diferença entre essas duas
expressões:

à =
 B=B

= só por si, se referem a uma variável cujo identificador é = , enquanto que B=B (entre aspas simples) remete
para o carácter constante i#i .

Caracteres e strings literais tem certas peculiaridades, como os códigos de escape. Estes são caracteres
especiais que são difíceis ou impossíveis de expressar de outra forma no código-fonte de um programa, como
nova linha ( A  ) ou guia ( A  ). Todos eles são precedidos por uma barra invertida ( A ). Aqui você tem uma
lista de alguns dos códigos de escape como:

A P newline

A ® retorno de carro

A + guia

A L guia vertical

A ? retrocesso

A 8 alimentação de formulário (alimentação de página)

A E alerta (bip)

A B aspas simples (W)

A # aspas duplas (#)

AV ponto de interrogação (V)

A A barra invertida (A)

Por exemplo:

à BA PB
 A  B#
 #A  D  3F
#
 #
 A A D
  #

Além disso, você pode expressar qualquer personagem com o seu código ASCII numérico escrito por uma barra
invertida ( A ) seguido do código ASCII expresso como um octal ( 
 ) ou hexadecimal ( 
!" ) de
número. No primeiro caso (octal) os dígitos deve seguir imediatamente a barra invertida (por exemplo A
 ou A ( ), no segundo caso (hexadecimal), um =personagem deve ser escrito antes dos dígitos si (por
exemplo A =( ou A =E ).

Strings podem estender para mais de uma única linha de código, colocando um sinal de barra invertida ( A ) no
final de cada linha inacabado.

à #/  =   A 
  #


Você pode também concatenar as constantes da cadeia várias separando-os por um ou vários espaços em
branco, tabulações, quebra de linha ou qualquer outro caractere válido em branco:

#3 " #


 #  # # # #   #

Finalmente, se quisermos que a string literal a ser feita explicitamente de caracteres de largura ( l $ tipo),
em vez de caracteres estreitos (  tipo), que pode preceder a constante com o 0 prefixo:
0 #3 S
  FHI        
#

caracteres de largura são usados principalmente para representar conjuntos de caracteres não-Inglês ou
exóticos.


 
V
Há apenas dois válido valores booleanos: 
e Ñ
. Estes podem ser expressos em C + + como valores do
tipo  , utilizando os literais booleanos N   e " . V

à 
! 
5! V
Você pode definir seus próprios nomes para constantes que você usa muito frequentemente sem ter que
recorrer a variáveis de consumo de memória, simplesmente usando o   "  diretiva de pré-
processamento. Seu formato é:

 D "    "  N


Por exemplo: V

à  D "  :R 6àà*
   "  BN   AB 

Isso define duas constantes novo:  e  Ë . Uma vez que eles são definidos, você pode usá-los no resto
do código como se fossem qualquer outro regular constante, por exemplo:

à      "  @ 


   
" I  àà*

  
   

  "  :R 6àà*

  "  BN   AB 

     !
D 
 M 6('    
* 
 J 
6 J 
 M  1 :R 1 '
à( J 
 O
  ' " P3X0RP3 '
àà
à 
 ('
)
à
à
à
à
à
àD
à*

Na verdade a única coisa que o pré-processador do compilador faz quando encontra   "  diretrizes é
literalmente substituir qualquer ocorrência de seu identificador (no exemplo anterior, estes
eram  e  Ë ) pelo código para o qual foram definidos (6àà* e B A  B , respectivamente).

×   "  directiva não é um C + + afirmação, mas uma diretiva para o pré-processamento, pelo que
assume toda a linha como a directiva e não necessita de um ponto e vírgula ( ' ) na sua extremidade. Se você
acrescentar um caractere de ponto e vírgula ( ' ) no final, ele também será anexado em todas as ocorrências
do identificador no corpo do programa que o pré-processador substitui.

x


 
 V
Com a  prefixo que você pode declarar constantes com um tipo específico da mesma forma como você
faria com uma variável:V
à   l  M à(('
   ,
.; M BA B '

Aqui, l  e ,


.; são duas constantes digitado. Eles são tratados como variáveis regulares, exceto
que seus valores não podem ser modificadas após a sua definição.

× 
 
Uma vez que sabemos da existência de variáveis e constantes, podemos começar a operar com eles. Para esse
efeito, C + + integra operadores. Diferente de outras linguagens cujos operadores são palavras-chave,
principalmente, os operadores em C + + são feitos principalmente de sinais que não são parte do alfabeto, mas
estão disponíveis em todos os teclados. Isso faz com C + + código mais curto e mais internacional, uma vez
que se baseia menos em palavras em Inglês, mas requer um pouco de esforço de aprendizagem no início.

Você não tem de memorizar todo o conteúdo desta página. A maioria dos detalhes são fornecidos apenas para
servir como uma referência futura no caso de você precisar dele.V

' 6V
× operador de atribuição atribui um valor a uma variável.V

 M '

Esta afirmação atribui o valor inteiro 5 à variável


 . A parte do lado esquerdo do operador de atribuição ( M )
é conhecido como o
(valor à esquerda) eo da direita como 
(valor correto). × lvalue tem que ser
uma variável enquanto o rvalue pode ser uma constante, uma variável, o resultado de uma operação ou
qualquer combinação destes.
A regra mais importante quando a atribuição é da 
 m 

 regra: A operação de atribuição
ocorre sempre da direita para a esquerda, e nunca outra maneira:

 M ,'

Esta afirmação atribui à variável


 (a lvalue) o valor contido na variável , (o rvalue). × valor que foi
armazenado até o momento em
 não é considerado em todo este funcionamento, e no fato de que o valor é
perdido.

Considere também que estamos apenas atribuindo o valor de , para


 momento da operação de
cessão. Portanto, uma mudança depois de , não afetará o novo valor de
 .

Por exemplo, vamos ter um olhar para o código a seguir - Eu incluí a evolução do conteúdo armazenado em
variáveis como os comentários:

à   $    ,
.;
@  ,@ 

  
  

    !

 6 ,'   @V6 ,V
  M à('   @6 ,@V à(
 , M '   @ à(6 ,@ 
D  M ,'   @ 6 ,@ 
* , M '   @ 6 ,@ 
à(
àà " #@# '
"  '
à
" #,# '
à " , '
à
à 
 (')
à
à
àD
à*
(

Esse código nos dará como resultado que o valor contido no


 é F
  e que se inclui na , é  . ×bserve
como
 não foi afetada pela modificação final de , , apesar de declarada  M , anterior (que é por causa
do m 


 
 
  ).

Uma propriedade que C + + tem sobre outras linguagens de programação é que a operação de atribuição pode
ser utilizado como rvalue (ou parte de um rvalue) por outra operação de cessão. Por exemplo:

 M   , M  '

é equivalente a:

à , M '  M   ,'


que significa: primeiro atribuir  para a variável , e, em seguida, atribuir


 valor  mais o resultado da tarefa
anterior de , (ou seja, 5), deixando
 com um valor final de  .

A expressão a seguir também é válido em C + +:

 M , M  M '

Ele atribui   ao todo três variáveis:


 , , e  .

× 
 
 7+*+1+8+,V
As cinco operações aritméticas suportadas pela linguagem C + + são: V

+ Além

- subtração

* multiplicação

/ divisão

% modulo

As operações de adição, subtração, multiplicação e divisão correspondem literalmente com seus respectivos
operadores matemáticos. × único que talvez não seja tão acostumados a ver é   , cujo operador é o sinal
de porcentagem ( È ). Módulo é a operação que dá o resto de uma divisão de dois valores. Por exemplo, se
escrevermos:

 M ààÈ '

a variável de
 conterá o valor  , pois  é o resto da divisão àà entre os  I .
à   
' 76+*6+1686,+6+96+::6+;<6+6+=6V

Quando queremos modificar o valor de uma variável realizando uma operação no valor atualmente armazenado
nessa variável, podemos usar os operadores de atribuição composta:V

 '   


 


N  M 
 ' N M N  
 '

MM  '  M  M '

  M ,'  M   ,'

1M .
    à' 1 . M . 
    à '

eo mesmo para todos os outros operadores. Por exemplo:

à   $     ,
.;   

  
  

    !

 6 , M '  M ,6   M '   F
N   M
  
 "  '
D 
 ( '
* )
à(
àà
à
à

 
 77+*V
Encurtando ainda mais algumas expressões, o operador de incremento (   ) eo operador de diminuição ( M ),
aumentar ou reduzir a um valor armazenado em uma variável. São equivalentes a  M à ea MM à ,
respectivamente. Assim:V

à   6   M à'  M  à'



são todos equivalentes na sua funcionalidade: três deles aumentará de um valor de c.

No início de compiladores C, as três expressões anteriores, provavelmente produzida código executável


diferente dependendo de qual delas foi usada. Atualmente, este tipo de otimização de código é geralmente feito
automaticamente pelo compilador, portanto, as três expressões deve produzir exatamente o mesmo código
executável.

Uma característica desse operador é que pode ser usado tanto como um prefixo e um sufixo como. Isso
significa que podem ser escritos antes da variável (identificador    ) ou depois (    ). Embora em
expressões simples, como    ou    ambos têm exatamente o mesmo significado, em outras expressões
em que o resultado da ou diminuir operação de aumento é avaliada como um valor em uma expressão exterior
podem ter uma diferença importante no seu significado: o caso que o operador aumento é utilizado como um
prefixo (+ + a) o valor é aumentado
 o resultado da expressão é avaliada e, portanto, aumentou o valor
é considerado na expressão exterior, no caso em que é usado como um sufixo (    ), o valor é armazenado
em um aumento depois de ser avaliado e, portanto, o valor armazenado antes da operação de aumento é
avaliada a expressão externa. ×bserve a diferença:
M  > M  ?

? M ' ? M '
E M   ?' E M ?  '
  E S 6 ? S    E S 6 ? S 

No Exemplo 1, ? é aumentada antes que seu valor é copiado para


 . Enquanto no Exemplo 2, o valor de ? é
copiado para
 e ? é aumentada.

®

 
 

66+@6+9+:+96+:6V

Para avaliar uma comparação entre duas expressões, podemos usar os operadores relacionais e de
igualdade. × resultado de uma operação relacional é um valor booleano que só pode ser verdadeiro ou falso, de
acordo com seu resultado booleano.

Nós podemos querer comparar duas expressões, por exemplo, para saber se eles são iguais ou se um é maior
do que o outro é.Aqui está uma lista dos operadores relacionais e de igualdade que pode ser usado em C + +:V

== Igual a

! = Não é igual a

> Superior

< Menos

> = Maior ou igual a

<= Inferior ou igual a

Aqui há alguns exemplos:

à  MM    N   "


     N   N  
 & M    N   N  
  M    N   N  
     N   "


Claro que, em vez de usar somente constantes numéricas, podemos usar qualquer expressão válida, incluindo
variáveis. Suponha que  M  , , M  e  M  ,

à E MM    N   "


 N C F
; S 
  
  1 , M    N   N  
 N C  1  M  S N  
 ,   1    N   "     1   S "
 , M  MM    N   N  

Cuidado! × operador M (um sinal de igualdade) não é o mesmo que o operador MM (dois sinais de igual), o
primeiro é um operador de atribuição (atribui o valor de seu direito à variável à sua esquerda) eo outro ( M M )
é o operador de igualdade que compara se as duas expressões nos dois lados são iguais uns aos outros. Assim,
na última expressão , M  MM  , primeiro atribuído o valor  para , e então comparou a
 , que
também armazena o valor  , então o resultado da operação é verdade.

× 
 ( <<+=@=V

× ×perador & é o operador C + + para realizar a operação booleana não, ele tem apenas um operando,
localizado a sua direita, ea única coisa que ele faz é valorizar o inverso dela, produzindo false se seu operando
é verdade e verdade se seu operando é falso. Basicamente, ele retorna o Boolean valor oposto de avaliar seu
operando. Por exemplo:V

à &  MM    N   "  F


 = ; Y 
    MM  S N  
 &  M    N   N    F
 M    "
 & N    
  "
 & "   N   N  

×s operadores lógicos € € e são usados na avaliação de duas expressões para obter um único resultado
relacional. × operador € € corresponde à operação lógica booleana AND. Esta operação resulta verdadeiro se
ambos os seus dois operandos são verdadeiros e falso caso contrário. × quadro a seguir mostra o resultado do
operador € € avaliação da expressão  € € , :

× 
 << x
 
<<

verdade verdade verdade

verdade falsa falsa

falsa verdade falsa

falsa falsa falsa

× operador corresponde com a lógica de operação lógica ×R. Esta operação resulta verdadeiro se qualquer
um de seus dois operandos é verdadeiro, sendo falsa somente quando ambos os operandos são falsos si. Aqui
estão os resultados possíveis de  ,:

==× M®x×® ×®

 
==

verdade verdade verdade

verdade falsa verdade

falsa verdade verdade

falsa falsa falsa

Por exemplo:

à  MM  € €     N   " 


€ € " 
  MM      N   N   
" 

Ao utilizar os operadores lógicos, C + + só avalia o que é necessário, da esquerda para a direita para avançar
com o relacional resultado combinado, ignorando o resto. Portanto, neste último exemplo (  MM  
 ), C + + que avaliar primeiro se  MM  é verdadeira, e se assim for, ele nunca iria verificar se   é
verdadeira ou não . Isso é conhecido como a avaliação de curto-circuito, e funciona assim para estes
operadores:


   * 

se a expressão do lado esquerdo for falso, o resultado combinado é falsa (lado direito de expressão
€ €
secundários não avaliados).
se a expressão do lado esquerdo é verdade, o resultado combinado é verdadeiro (lado direito de
expressão secundários não avaliados).

Isto é mais importante quando a expressão do lado direito tem efeitos colaterais, como alteração valores:

"  à( €€   ! 11 )

Isto combinado condicional aumenta a expressão por um, mas somente se a condição na esquerda da € € é
verdade, pois caso contrário, o lado direito de expressão (    ) nunca é avaliado.


  
V

× operador condicional avalia uma expressão retornando um valor se essa expressão é verdadeira e um
diferente se a expressão é avaliada como falsa. Seu formato é:

 .;V 
à@ 


Se a  .; for verdadeira a expressão retornará 


à , se não for ele retornará 
 . V

à  MM V @      6    ; S 
  
  MM  V @      6 O% F
 S 
   
  V @ ,      N 
6    S   F

  ,V @ ,      F
"   6  
,

à   $     



  
  

     !
 6 ,6 6  M 6 , M   M  , V @ ,'

"  '

D 
 ('
* )
à(
àà
à
à
à
à
à
à

Neste exemplo,
 era  e , foi  , então a expressão a ser avaliada (  , ) não era verdadeira, assim,
inicialmente, o valor especificado após o ponto de interrogação foi descartado em favor do segundo valor (o
que depois dos dois pontos), que Foi , , com um valor de  .

× 
 
+V
× operador vírgula ( 6 ) é usada para separar dois ou mais expressões que são incluídos em uma única
expressão é o esperado.Quando o conjunto de expressões tem que ser avaliado por um valor, apenas a
expressão mais à direita é considerada.

Por exemplo, o seguinte código:V

 M , M 6 ,  '
Em primeiro lugar, atribuir o valor  para , , e depois atribuir ,  a variável
 . Assim, no final, a
variável
 deve conter o valor  , enquanto variável , seria conter o valor  .

× 
 
<+=+;+A+::+99V

×peradores bit a bit modificar as variáveis, considerando os padrões de bits que representam os valores que
eles armazenam.V


  
 
 ' 

€ E AND bit a bit

×U Inclusive ×R bit a bit

T X×R Bit a bit ×U Exclusivo

Z NÃ× Unários complementar (inversão de bits)

 SHL Shift Esquerda

 SHR Shift direito

× 
  '  
 V
Tipo de fundição operadores permitem converter um dado de um determinado tipo para outro. Existem várias
maneiras de fazer isso em C + +. × mais simples, que foi herdada da linguagem C, deve preceder a expressão
a ser convertido por um novo tipo colocada entre parênteses (  ): V

à  '
 " " M 6à' M   "'


× código anterior converte o número float 6à para um valor inteiro (  ), o restante é perdido. Aqui, o
operador foi typecasting  . ×utra maneira de fazer a mesma coisa em C + + está usando a notação
funcional: precedendo a expressão a ser convertido pelo tipo e colocando a expressão entre parênteses:

M  " '

Ambas as formas de conversão de tipo são válidas em C + +.

3 !V
Esse operador aceita um parâmetro, que pode ser tanto um tipo ou variável em si e retorna o tamanho em
bytes desse tipo ou objeto:V

 M  C "   '

Isso vai atribuir o valor de


 para um, porque  é um tipo de bytes de tamanho um.
× valor retornado por  C " é uma constante, por isso é sempre determinado antes da execução do
programa.
×  
 V
Mais tarde, estes tutoriais, vamos ver mais alguns operadores, como os referentes a ponteiros ou os específicos
para programação orientada a objetos. Cada um é tratado em sua respectiva seção.V

0 
  
 V
Ao escrever expressões complexas com vários operandos, podemos ter algumas dúvidas sobre qual operando é
avaliado primeiro e que mais tarde. Por exemplo, nesta expressão:V

 M   È 

podemos duvidar se ele realmente significa:

à  M   È   
 
  6 

  M    È    
 
  (

A resposta correta é a primeira das duas expressões, com um resultado de  . Há uma ordem estabelecida com
a prioridade de cada operador, e não apenas os aritméticos (aqueles cuja preferência vêm da matemática),
mas para todos os operadores que podem aparecer em C + +. Do maior para a menor prioridade, a ordem de
prioridade é a seguinte:

 × 
  x'  
  

Da esquerda para a
1 @@ escopo
direita

 79 M   M D5 4 4 Da esquerda para a


2 postfix
 4  4 5  direita

  M Z&  C " N   unário (prefixo)

indiretamente, e de Da direita para a


3 1 €
referência (ponteiros) esquerda

 M operador de sinal unário

Da direita para a
4 +  tipo de vazamento
esquerda

Da esquerda para a
5 1 M 1 ponteiro-para-membro
direita

Da esquerda para a
6 1È  multiplicativo
direita

Da esquerda para a
7  M aditivo
direita

Da esquerda para a
8  mudança
direita

Da esquerda para a
9  M M relacional
direita

Da esquerda para a
10 MM& M igualdade
direita
Da esquerda para a
11 € AND bit a bit
direita

Da esquerda para a
12 T X×R bit a bit
direita

Da esquerda para a
13 ×R bit a bit
direita

Da esquerda para a
14 € € E lógico
direita

Da esquerda para a
15 ×R lógico
direita

Da direita para a
16 V@ condicional
esquerda

Da direita para a
17 M 1M  MÈ M  M MM M M € M T M M atribuição
esquerda

Da esquerda para a
18 6 vírgula
direita

Agrupamento define a ordem de precedência, em que os operadores são avaliados no caso de existirem vários
operadores do mesmo nível em uma expressão.

Todos esses níveis de precedência dos operadores pode ser manipulado ou se tornar mais legível removendo
possíveis ambiguidades usando sinais entre parênteses  e , como neste exemplo:

 M   È '

pode ser escrito como:

 M   È  '

ou
 M    È'

dependendo da operação que deseja executar.

Então, se você quiser escrever expressões complicadas e você não está completamente certo dos níveis de
prioridade, sempre inclua parênteses. Ele também fará seu código mais fácil de ler.


P c 8× 
Até agora, os programas de exemplo das seções anteriores, desde muito pouca interação com o usuário, se
houver algum. Usando o padrão de entrada e saída de biblioteca, seremos capazes de interagir com o usuário
através da impressão de mensagens na tela e começar a entrada do usuário a partir do teclado.

C + + usa uma abstração conveniente chamados Ñ# para realizar operações de entrada e de saída em meio
seqüencial, como a tela ou o teclado. Um stream é um objeto onde um programa pode inserir ou extrair
caracteres para / a partir dele. Nós realmente não precisa se preocupar com muitas especificações sobre os
meios físicos associados com o fluxo - só precisamos de saber que vai aceitar ou fornecer caracteres em
seqüência.

× padrão C + + biblioteca inclui o arquivo de cabeçalho   , onde o padrão de entrada e saída de objetos
de fluxo são declaradas.V

&


' 
V
Por padrão, a saída padrão do programa é a tela, eo C + + objeto de fluxo definido para acessá-lo é  ,
 .
V

à : " #  .  /J# '        "  J


 : " à( '      K  à(   
 : " = '       K  =   

× " operador insere os dados que segue para a corrente que o precede. Nos exemplos acima é inserido a
constante string "   J , a constante numérica à( e variável = dentro do padrão de saída de fluxo
de   . ×bserve que a sentença em primeira instrução é colocada entre aspas ( # ) porque é uma constante
cadeia de caracteres. Sempre que quisermos usar seqüências de caracteres constantes, devemos colocá-los
entre aspas ( # ) para que eles possam ser claramente distinguidos dos nomes de variáveis. Por exemplo, essas
duas frases têm resultados muito diferentes:

à " #$%# '     $%


 " $% '       K  N %N  $%

× operador de inserção ( 6 ) pode ser utilizado mais de uma vez em uma única instrução:

: " #$%# 6 #3

# 6 #  
   .;# '

Esta última afirmação deve imprimir a mensagem $%6




      .; na tela. × utilitário de
repetir o operador de inserção ( 6 ) é demonstrada quando queremos imprimir uma combinação de variáveis e
constantes ou mais de uma variável:

" #$%6

#6  6#   
 S#6 3: '

Se assumirmos que a  variável para conter o valor  eo  variável para conter *(( a saída da
declaração anterior seria:

$%6     


 S *((

É importante notar que o  ,


 não adiciona uma quebra de linha após a sua saída, a menos que
explicitamente indicam que, portanto, as seguintes afirmações:

à " #3 S
   .# '
 " #3 S
 
    .# '

será mostrado na tela uma após a outra, sem qualquer quebra de linha entre eles:

3 S
    +  S 
  "  
mesmo que tinha escrito em dois diferentes inserções em  ,
 . Para realizar uma quebra de linha na
saída, devemos explicitamente inserir um caractere de nova linha em F
  . Em C + + um caractere de nova
linha pode ser especificado como A  (n barra invertida):

à " #:   "   A# '


 " #/ 
 "  "   +  A# '

Isso produz o seguinte resultado:

:   "  
/ 
 "  
E    "  

Além disso, para adicionar uma nova linha, você também pode usar o  manipulador. Por exemplo:

à " #   "  A# '


 " # 
 "  A# '

deveria imprimir:

:   "  
/ 
 "  

×  manipulador produz um caractere de nova linha, exatamente como a inserção de BA B faz, mas
também tem um comportamento adicional quando ele é usado com buffered streams: o buffer é
liberado. Enfim,  ,
 será um fluxo unbuffered na maioria dos casos, assim que você geralmente pode
usar tanto o A  caractere de escape ea  manipulador, a fim de especificar uma nova linha, sem qualquer
diferença em seu comportamento.

M 


' cÃV
× dispositivo de entrada padrão é geralmente o teclado. Manipulação da entrada padrão em C + + é feito
através da aplicação do operador sobrecarregado de extração ( €) no scanf fluxo. × operador deve ser seguido
pela variável que irá armazenar os dados que vai ser extraído do córrego. Por exemplo:V

à   '
 " #È#6€  '

A primeira instrução declara uma variável do tipo  chamado de  , eo segundo aguarda a entrada
de   (teclado), a fim de guardá-la nesta variável inteira.

scanf só pode processar a entrada do teclado uma vez que o ®3+G®P tecla foi pressionada. Portanto, mesmo se
você solicitar um único personagem, a extração de scanf não irá processar a entrada até que o usuário
pressiona ®3+G®P após o personagem ter sido introduzida.

Você deve sempre considerar o tipo da variável que você está usando como um recipiente
com   extrações. Se você pedir um inteiro que você irá obter um número inteiro, se você pedir um
personagem que você vai ter um personagem e se você pedir uma cadeia de caracteres que você terá uma
seqüência de caracteres.

à  R   =   : "

  
  

    !

 '

 " #D  
 N  @# '
D " #È#6€ '
* " #$ N F
NI 
S#6 '
à( " # 

 S#6 1  6# A# '
àà

 (')
à
à
à

Você também pode usar scanf para solicitar mais de um dado de entrada do usuário:

/" #ÈÈ#6€6€, '

é equivalente a:

à /" #È#6€ ' "#È#6€, '




Em ambos os casos o usuário deve dar dois dados, um para a variável de


 e outro para a variável , que
podem ser separados por qualquer separadoras em branco válidos: um espaço, um caractere de tabulação ou
uma nova linha.

M
à 
Um programa é geralmente não se limita a uma seqüência linear de instruções. Durante o seu processo, podem
se bifurcar, repetir o código, ou tomar decisões. Para esse efeito, C + + oferece estruturas de controle que
servem para especificar o que deve ser feito pelo nosso programa, quando e sob quais circunstâncias.

Com a introdução de estruturas de controle nós vamos ter que introduzir um novo conceito: o m 

  ou  . Um bloco é um grupo de instruções que são separados por ponto e vírgula (;) como todas
as instruções C + +, mas agrupados em um bloco entre chaves: !) :

!à'   ' 


.;')

A maioria das estruturas de controle que veremos nesta seção requerem um enunciado genérico, como parte
de sua sintaxe. A declaração pode ser simples declaração (uma simples instrução termina com um ponto e
vírgula) ou um comando composto (várias instruções agrupadas em um bloco), como a descrita acima. No caso
em que queremos que a instrução seja uma instrução simples, não precisa incluí-la entre chaves ( !) ). Mas no
caso que nós queremos que a instrução seja uma instrução composta, deve ser colocada entre chaves ( !) ),
formando um bloco.V


 
)!V
×  palavra-chave é usada para executar uma instrução ou bloco somente se uma condição é satisfeita. Sua
forma é:

"  .;   .;

×nde  .; é a expressão que está sendo avaliado. Se esta condição for verdadeira, 
.; é
executada. Se for falsa,   .; é ignorado (não executado) eo programa continua logo após esta estrutura
condicional.
Por exemplo, o seguinte fragmento de código imprime = S  à(( somente se o valor armazenado
em = variável é realmente à(( : V

à " = MM à(( " #= S à((# '



Se nós queremos mais do que uma simples instrução a ser executada no caso de que a condição é verdadeira,
podemos especificar um bloco usando chaves !) :

à " = MM à(( !
 " #= S# '
 " = '
 )


Podemos adicionalmente especificar o que quer que aconteça, se a condição não for cumprida, usando a
palavra-chave   . Sua forma usada em conjunto com  é:

"  .;    à   

Por exemplo:

à " = MM à((
 " #= S à((# '

 
" #= ; S à((# '

imprime na tela S à(( = se de fato = tem um valor de à(( , mas se não tiver e só se não for, ele imprime =
; S à(( .

×     estruturas podem ser concatenado com o intuito de verificar um intervalo de valores. ×
exemplo a seguir mostra a sua utilização dizer se o valor atualmente armazenado em = é positivo, negativo ou
nenhum deles (ou seja, zero):

à " = (
 " #= S   N# '

 
" = (

" #= S   N# '


" #= S (# '

Lembre-se que no caso em que queremos mais do que uma simples instrução a ser executada, devemos
agrupá-los em um bloco, colocando-os entre chaves !) .



'  V

Loops tem como finalidade a repetir uma afirmação de um certo número de vezes ou enquanto uma condição
for cumprida.V

×
 B V
Seu formato é:

l   = ; 
.;

e sua funcionalidade é simplesmente repetir while a condição estabelecida na expressão é verdadeira.


Por exemplo, vamos fazer um programa para diminuir a contagem usando um ciclo while: V

à       N  C


 F
 D  
  
  

     !
 '

" #D    K       # '
 " #È#6 '

D l   ( !
* " 6#6#6M '
à( )
àà " #8R®3 A & # '
à

 ('
à )
à
à
à
à
àD
à*

Ao iniciar o programa o usuário é solicitado a inserir um número inicial para a contagem regressiva. Então,
o    de loop começa, se o valor digitado pelo usuário preenche a condição  ( (que  é maior do que zero)
o bloco que segue a condição será executado e repetido enquanto a condição (  ( ), continua sendo verdade.

× processo inteiro do programa anterior pode ser interpretado de acordo com o seguinte roteiro (a partir de
principal):

àV Usuário atribui um valor para V


2.V A condição enquanto estiver marcada (  ( ). Neste ponto existem duas possibilidades:
* condição for verdadeira: instrução é executada (para o passo 3)
* condição é falsa: ignorar instrução e continuar depois (para a etapa 5)
3.V instrução de execução:
" 6#6# '
M P'
(Imprime o valor de  na tela e diminui  de à )
4.V Fim do bloco. Voltar automaticamente para a etapa 2
5.V Continuar o programa certo depois que o bloco: F×G× imprimir! e um programa final.

Ao criar um laço while, devemos sempre considerar que ele tem que terminar em algum momento, portanto,
temos de fornecer, dentro do bloco de algum método para forçar a condição se tornar falsa em algum
momento, caso contrário, o loop continuará looping para sempre. Neste caso, nós incluímos M ' que diminui o
valor da variável que está sendo avaliado na condição (  ) por um - isso acabará por tornar a condição (  ( )
para tornar-se falso depois de um certo número de loop iterações: para ser mais específico, quando  se
torna ( , que é onde o nosso tempo de ciclo e nosso fim de contagem regressiva.

Claro que isto é uma ação tão simples para o nosso computador que a contagem é feita toda de imediato, sem
qualquer atraso prática entre os números.V

×
  *B V

Seu formato é:

 l   .; '

Sua funcionalidade é exatamente o mesmo que o loop while, exceto que a  .; do loop do-while é
avaliada após a execução da declaração, em vez de antes, a concessão, pelo menos, uma execução
de   .; , mesmo  .; nunca é cumprida. Por exemplo, o programa ecos exemplo a seguir qualquer
número que você entra até que você digite ( . V

à   3 K  D    K  (      @ à


 LI   
@ à D    K  (      @
  
   à(
 LI   
@ à(
     ! D    K  (      @ ( LI   
@ (

      '

 !
 "#D    K  (      @# '
D "#È#6€ '
*
à( " #LI   
@ #6 6#A # '
àà )l  &  M ( '
à

 (')
à
à
à

× do-while normalmente é utilizado quando a condição que tem de determinar o fim do ciclo é
determinada   da instrução loop em si, como no caso anterior, onde a entrada do usuário dentro do bloco
é o que é usado para determinar se o loop tem que acabar. De fato, se você não inserir o valor ( no exemplo
anterior, você pode ser solicitado para mais números sempre.

×
 ! V

Seu formato é:

"     C.;'  .;' 


    .;'

e sua principal função é repetir a " .; , enquanto  .; for verdade, como o loop while. Mas, além
disso, a  loop fornece localizações específicas para conter a    C.;  declaração e um 
 
 declaração. Portanto, este ciclo é especialmente concebido para realizar uma ação repetitiva com um
contador que é inicializado e aumentou em cada iteração.

Ele funciona da seguinte maneira:V

àV    C.; é executada. Geralmente é um valor inicial de configuração para uma variável de
contador. Esta é executado apenas uma vez.V
2.V  .; é verificada. Se é verdade o ciclo continua, caso contrário, o laço termina e 
.; é
ignorada (não executado).
3.V 
.; é executada. Como de costume, ele pode ser uma única instrução ou um bloco entre
chaves !) .
4.V enfim, tudo o que é especificado no 
  campo é executado eo ciclo se volta para a etapa 2.

Aqui está um exemplo de contagem regressiva usando um loop for:V

à      N 

  à(6 *6
  
  

     !
"    M à('  (6  M !
 "  ,
 #6# '
 )

D " #8R®3 & A# '
*
à( 
 (')
àà

A    C.; e 
  os campos são opcionais. Eles podem ficar vazios, mas em todos os casos, os
sinais de ponto e vírgula entre eles deve ser escrita. Por exemplo, poderíamos escrever: " '  à(' se
quiséssemos especificar nenhuma inicialização e não aumentar, ou   '   '  à( , se quiséssemos
incluir um campo de aumento, mas não de inicialização (talvez porque a variável já foi inicializada antes).
×pcionalmente, usando o operador vírgula ( 6 ), podemos especificar mais de uma expressão em qualquer um
dos campos incluídos em um  laço, como na    C.; , por exemplo. × operador vírgula ( 6 ) é um
separador de expressão, que serve para separar mais de uma expressão em que apenas um é normalmente
esperado.Por exemplo, suponha que queremos iniciar mais de uma variável no nosso loop:

à "  M (6 M à((' & M 6   6 M !


   F
F
  F

 )


Este loop será executado por 50 vezes, se não  ou são modificadas dentro do loop:

 começa com um valor de ( , e


com à(( , a condição é & M (que  não é igual a ). Porque  é
aumentada de um e
diminuído por um, a condição do loop se tornará falso depois do ciclo 50, quando
ambos  e será igual a ( .

c

 V
V

 ' 


CV

Usando F
,  podemos deixar um loop mesmo que a condição para o seu fim não é cumprido. Ele pode ser
usado para terminar um loop infinito, ou forçá-lo a terminar antes de seu fim natural. Por exemplo, vamos
parar a contagem regressiva antes de seu fim natural (talvez por causa de uma falha de verificação do
motor?):V

à   3=     , [ à(6 *6

  
  

    !

 '
 "  M à('  (6  M !
 " 6#6# '
D
* "  MM  !
à( " #    N , &# '
àà , [ ')
)
à

 ('
à )
à
à
à
à
àD
à*

 '   V

A  
  instrução faz com que o programa para passar o resto do laço na iteração atual, como se o fim
do bloco de declaração tinha sido alcançado, fazendo com que ele salte para o início da iteração seguinte. Por
exemplo, vamos pular o número 5 em nossa contagem regressiva:V

à    
=    à(6 *6
  
  

     !
"    M à('  (6  M

!
 "  MM   
'
 " 6## '
D )
* " #8R®3 & A# '
à(
àà 
 ('
)
à
à

 '   V
 permite fazer um salto absoluto para outro ponto do programa. Você deve usar esse recurso com cautela,
pois sua execução faz com que um salto incondicional ignorando qualquer tipo de limitações de aninhamento.
× ponto de destino é identificado por uma etiqueta, que depois é usado como um argumento para a instrução
goto. Um rótulo é feito de um identificador válido seguido por dois pontos ( @ ).

De um modo geral, esta instrução não tem nenhum uso concreto estruturado ou programação orientada a
objeto com exceção daqueles que os fãs de programação de baixo nível pode encontrar para ele. Por exemplo,
aqui é o nosso laço de contagem regressiva usando  : V

à   3=      à(6 *



  
  

    !

  M à('  @
 " 6#6#6 M '

D "  (
*   ' "  ,
6#8R®3 & A# '
à(
àà 
 (')
à
à
à
à

! ' 



V

J é uma função definida na  , biblioteca.

× objectivo da J é terminar o programa actual, com um código de saída específico. Seu protótipo é:V

N  =    =  '

× =  é utilizado por alguns sistemas operacionais e pode ser utilizado por chamada de programas. Por
convenção, um código de saída de ( significa que o programa terminou normalmente, e qualquer outro valor
significa que alguns resultados inesperados ou erro aconteceu.



)BV
A sintaxe da instrução switch é um pouco peculiar. Seu objetivo é verificar possíveis diversos valores
constantes de uma expressão. Algo semelhante ao que fizemos no início desta seção, com a concatenação de
vários  e  " instruções. Sua forma é o seguinte:V
l   = ; ! à@ 
  
.2 
 , ['  @ 
 

.2   , ['    "
@  "
 
  
.2 )

Ele funciona da seguinte maneira: switch avalia = ; e verifica se ele é equivalente a à , se for,
ele executa
 
   até encontrar o , [ comunicado. Quando encontra
esse F
,  declaração o programa salta para o final do l  estrutura seletiva.

Se a expressão não era igual a à será verificado contra  . Se for igual a este, ele irá
executar 
    até uma palavra-chave break for encontrada, e em seguida, irá saltar para o
final do l  estrutura seletiva.

Finalmente, se o valor da = ; não corresponde a nenhuma das constantes especificadas anteriormente
(você pode incluir quantos  rótulos como os valores que pretende verificar), o programa irá executar as
declarações depois que o  ;@ label, se existir (desde é opcional).

Ambos os fragmentos de código a seguir têm o mesmo comportamento:

B    
 !*

" = MM à !
" #= S à# ')
l  = !

 à@ " #= S
# ' , ['
" = MM  !
 @ " #= S # ' , ['
" #= S #')
 "
@ " #N  =    # '
 !
)
: " #N  =    # '
)

× 
  declaração é um pouco peculiar dentro da linguagem C + +, pois ele usa etiquetas em vez
de blocos. Isto nos obriga a colocar F
,   declarações depois que o grupo de instruções que queremos ser
executado para uma condição específica. Caso contrário, as declarações restante, incluindo os correspondentes
a outros rótulos também será executado até o final do l  bloco seletiva ou um F
,  afirmação é
atingido.

Por exemplo, se não incluir uma F


,   declaração após o primeiro grupo de um caso, o programa não irá
saltar automaticamente para o final do l  bloco seletivo e que iria continuar a executar o restante das
declarações até que ele atinja tanto uma F
,   instrução ou o fim do l  bloco seletivo. Isso torna
desnecessário incluir chaves !) em torno das declarações de cada um dos casos, e pode também ser útil para
executar o mesmo bloco de instruções para diferentes valores possíveis para a expressão ser avaliada. Por
exemplo:

à l  = !
  à@
  @
  @ " #= S à6  
# '
, [ '
  "
 @ " #= ; S à6  
# '
 )

D
*

×bserve que a chave só pode ser usado para comparar uma manifestação contra constantes. Portanto, não
podemos colocar variáveis como etiquetas (por exemplo,  @ onde  é uma variável) ou intervalos ( 
à   @ ) porque eles não são válidos C + + constantes.

Se você precisar verificar a extensão ou os valores que não são constantes, use uma concatenação
de  e ;  declarações.

 c
Usando funções podemos estruturar nossos programas de forma mais modular, o acesso a todo o potencial que
a programação estruturada pode oferecer a nós em C + +.
Uma função é um grupo de instruções que é executada quando é chamada a partir de algum ponto do
programa. × seguinte é o seu formato:

        à6    6  ! 


.2 )

onde:V

>V   é o especificador de tipo de dados dos dados retornados pela função.V


>V  é o identificador pelo qual será possível chamar a função.
>V  \   (como quantas forem necessárias): Cada parâmetro consiste em um tipo de dados seguido
por um identificador, como qualquer declaração de variáveis regulares (por exemplo:  = ) e que
atua dentro da função como uma variável local normal. Eles permitem passar argumentos para a
função quando é chamada. ×s diferentes parâmetros são separados por vírgulas.
>V   .2  é a função do corpo. É um bloco de instruções entre chaves !) .

Aqui você tem a função de primeiro exemplo: V

à   3=    "
.; $ 

  
  

     6  , !
 6 M   ,'
 
  '
 )

D     !
*  C' S C M  6 '
à( " #$ 
 S#6C '

 ('
àà
)
à
à
à
à
à
à
àD

A fim de examinar este código, antes de tudo lembrar algo dito no início deste tutorial: um programa C + +
sempre começa a sua execução pelo   função. Então, vamos começar por aí.

Nós podemos ver como a   função começa por declarar a variável C do tipo  . Logo depois, vemos
uma chamada a uma função chamada   . Prestando atenção, vamos ser capazes de ver a semelhança
entre a estrutura da chamada para a função ea declaração da função em si algumas linhas de código acima:

×s parâmetros e argumentos têm uma correspondência clara. Entre a   função que chamamos
de S de passar dois valores:  e  , que correspondem ao   e  , parâmetros declarados para além
da função.

No momento em que a função é chamada de dentro    , o controle é perdido pelo   e


passados para a função   . × valor de ambos os argumentos passados na chamada (  e  ) são copiados
para as variáveis locais   e  , dentro da função.

Função   declara outra variável local (  ), e por meio da expressão M   , , que atribui aos o
resultado de
 plus , . Como os parâmetros reais passados para
 e , são  e  , respectivamente, o
resultado é D .

A seguinte linha de código:

   '

Finaliza função   , e retorna o controle para a função que a chamou, em primeiro lugar (neste caso,
a   ). Nesse momento, o programa segue o seu curso regular a partir do mesmo ponto em que foi
interrompido pelo convite para S . Mas, além disso, porque o   declaração em
função   especificado um valor: o conteúdo da variável ( 
  ' ), que naquele momento tinha um
valor de D . Este valor torna-se o valor de avaliação da chamada de função.

Assim sendo o valor retornado por uma função do valor dado à função de chamar a si mesmo quando é
avaliado, a variável C será definido como o valor retornado pela  .; 6  , que é D . Para explicar de
outra forma, você pode imaginar que a chamada para uma função (   .; 6 ) é literalmente
substituído pelo valor que ela retorna ( D ).

A seguinte linha de código na seção principal é:

: " #$ 
 S#6C '

Que, como você já pode esperar, produz a impressão do resultado na tela.

! 



× escopo das variáveis declaradas dentro de uma função interna ou qualquer outro bloco é apenas a sua
própria função ou o seu próprio bloco e não pode ser utilizado fora deles. Por exemplo, no exemplo anterior,
teria sido impossível o uso de variáveis
 , , ou diretamente na função   , uma vez que foram as
variáveis locais a função   . Além disso, teria sido impossível usar a variável C diretamente em
função  , uma vez que esta era uma variável local à função   .

Portanto, o escopo de variáveis locais é limitado ao nível mesmo bloco em que elas são declaradas. No entanto,
também temos a possibilidade de declarar variáveis globais, que são visíveis de qualquer ponto do código,
dentro e fora de todas as funções. Para declarar variáveis globais, você simplesmente tem que declarar a
variável fora de qualquer função ou bloco, ou seja, diretamente no corpo do programa.

E aqui está outro exemplo sobre funções:

à   3=    "
.;
  
  

 
, .;   6  , !

 ' M , '
 
  '
 )

D     !
*  = M 6 5 M ' C6 C M 
, .; 6 '
à(
" #$   
 SA#6C6 '
àà
" #$  
 
 S#6
, .;66 6#A # '
à " #$    
 S #6
, .;6=6 5 6#A #6 C M   
, .; =6 5 '
à " #$ F
  
 S#6C6#A # '
à
à 
 ('
à )
à
àD
à*
(



Neste caso, criamos uma função chamada  


, .; . A única coisa que esta função faz é subtrair os
parâmetros passados e retorna o resultado.

No entanto, se examinarmos a função   , veremos que temos feito várias chamadas para a função 

, .; . Nós usamos alguns chamar métodos diferentes para que você veja outras formas ou momentos
em que uma função pode ser chamado.

A fim de compreender estes exemplos, deve-se considerar mais uma vez que uma chamada para uma função
poderia ser substituído pelo valor que a função de chamar a si mesma que vai voltar. Por exemplo, o primeiro
caso (que você já deve saber, porque é o mesmo padrão que temos usado nos exemplos anteriores):

à C M 
, .;M ' " #$   
 S#6C '


Se substituirmos a chamada de função com o valor que retorna (ou seja,  ), teríamos:

à C M ' " #$   


 S#6C '


Bem como

" #$  
 
 S #6 
, .;MM '

tem o mesmo resultado que a chamada anterior, mas neste caso nós fizemos a chamada para 

, .; diretamente como um parâmetro de inserção para  ,
 . Basta considerar que o resultado é o
mesmo como se tivéssemos escrito:
" #$  
 
 S # '

uma vez que  é o valor retornado por 


, .; 6 .

No caso de:

" #$    
 S #6
, .;6=6 5 '

A única coisa nova que foi introduzida é que os parâmetros de 


, .; são variáveis ao invés de
constantes. Isso é perfeitamente válido. Neste caso, os valores passados para a função  
, .; são os
valores de = e 5 , que são  e  , respectivamente, dando  como resultado.

× quarto caso é mais do mesmo. Basta notar que em vez de:

C M   
, .; =6 5 '

poderíamos ter escrito:

C 
, .; M =6 5  '

com exatamente o mesmo resultado. Eu tenho mudado lugares assim que você pode ver que o sinal de ponto e
vírgula ( ' ) vai no final de toda a declaração. Não necessariamente tem que ir logo após a chamada da
função. A explicação pode ser uma vez mais que você imaginar que uma função pode ser substituído pelo seu
valor devolvido:

à C M   6 C M   '


 
  
  ×  V

Se você lembra da sintaxe de uma declaração de função:

     
 à6  
     .;

você vai ver que a declaração começa com um   , que é o tipo de função em si (ou seja, o tipo de dado que
será retornado pela função com a instrução de retorno). Mas o que se queremos retornar nenhum valor?

Imagine que nós queremos fazer uma função só para mostrar uma mensagem na tela. Nós não precisamos que
ele retorne algum valor. Neste caso, deveríamos usar o NC  especificador de tipo para a função. Este é um
especificador especial que indica ausência de tipo.V

à   3=    "
.; N  3

  
  

 N     !
 " #3


 "
.;&# '
 )

D     !
*
à(    '
àà

 ('
à )
à
à

NC  também pode ser usado em função do parâmetro na lista para especificar explicitamente que queremos
que a função não dar parâmetros reais quando é chamado. Por exemplo, a função   poderia ter
sido declarada como:

à N     N  !

 " #3


 "
.;&# '
 )

Embora seja opcional para especificar N  na lista de parâmetros. Em C + +, uma lista de parâmetros pode
simplesmente ser deixado em branco, se queremos uma função sem parâmetros.

× que você deve sempre lembrar é que o formato para chamar uma função inclui especificando seu nome e
encerrando os respectivos parâmetros entre parênteses. A inexistência de parâmetros não nos exime da
obrigação de escrever os parênteses. Por esse motivo, a chamada para   é:

   '

×s parênteses indicam claramente que esta é uma chamada para uma função e não o nome de uma variável ou
algum outro C + + declaração. A chamada a seguir teria sido incorreto:

  '

V
 cc
  

  
  !0 


Até agora, em todas as funções já vimos, os argumentos passados para as funções foram passados m 
 . Isto significa que ao chamar uma função com parâmetros, o que temos passado para a função eram
cópias de seus valores, mas nunca as próprias variáveis. Por exemplo, suponha que nós chamamos a nossa
primeira função  usando o seguinte código:V

à  = M 6 5 M 6 C6 C M  =6 5 '




× que fizemos nesse caso foi a chamada para a função addition passando os valores de = e 5 , ou
seja,  e  respectivamente, mas não as variáveis = e 5 si.

Dessa forma, quando a adição da função é chamado, o valor de suas variáveis locais
 e , -
se  e  respectivamente, mas qualquer modificação a qualquer
 , ou , dentro da função disso não terá
nenhum efeito nos valores de = e 5 fora , porque as variáveis = e 5 não foram eles mesmos passados para a
função, mas apenas cópias de seus valores no momento em que a função foi chamada.

Mas pode haver alguns casos em que você precisa para manipular de dentro de uma função o valor de uma
variável externa. Para esse efeito, podemos usar argumentos passados por referência, como na função de
duplicar o seguinte exemplo:

à   :    \    " I  = M 


  
  

 N  
    € 6  € ,6  €  !
 1M ' , 1M '  1M '
 )

     !
D  = M à6 5 M 6 C M ' 
  =6 56 C '
* " #= M#6=6#6 5 M#656#6 C M #6C '
à(

 ('
àà
)
à
à
à
à
à
à
àD

A primeira coisa que deve chamar a atenção é que na declaração de 


  o tipo de cada parâmetro foi
seguido por um sinal de E comercial ( € ). Esse comercial é o que especifica que os seus argumentos
correspondentes devem ser passados m 
Ñ
 em vez de m  .

Quando uma variável é passada por referência que não estamos passando uma cópia do seu valor, mas nós
somos de alguma forma passar a variável-se para a função e qualquer modificação que podemos fazer para as
variáveis locais terão um efeito em variáveis sua contraparte passados como argumentos no a chamada para a
função.

Para explicá-lo de outra forma, podemos associar


 , , e  com os argumentos passados na chamada da
função ( = , 5 e C ) e qualquer mudança que fazemos em
 dentro da função afetam o valor de = fora
dela. Qualquer mudança que fizermos em , afetará 5 , e mesmo com  e C .

É por isso que o nosso programa de saída, que mostra os valores armazenados em = , 5 e C após a chamada
para 
  , mostra os valores de todas as três variáveis    duplicou.

Se, ao declarar a função a seguir:

N  
    € 6  € ,6  € 

que havia declarado desta forma:

N  
    6  ,6  

ou seja, sem os sinais e comercial ( € ), não teríamos passado por referência as variáveis, mas uma cópia de
seus valores em vez e, portanto, a saída na tela do nosso programa teria sido os valores de = , 5 e C , sem ter
sido modificado.

Passagem por referência é também uma forma eficaz de permitir que uma função para retornar mais de um
valor. Por exemplo, aqui está uma função que retorna o número anterior e próximo do primeiro parâmetro
passado.

à     
 N    E
  
  

 N  N =   =6  € N6  €  
 !
N M =Mà6  M = à'
 )

     !
D  = M à((6 56 C'
*
à( N = =6 56 C '
" #E  M#656#6 ]=  M#6C '
àà
à 
 ('
à )
à
à
à
à

×
 
'  
% V
Quando declarar uma função que pode especificar um valor padrão para cada um dos últimos parâmetros. Esse
valor será usado se o argumento correspondente é deixado em branco quando chamado para a função. Para
fazer isso, nós simplesmente temos que usar o operador de atribuição e um valor para os argumentos na
declaração da função. Se um valor para esse parâmetro não é passado, quando a função é chamada, o valor
padrão é usado, mas se um valor é especificado o valor padrão é ignorado eo valor passado é usado. Por
exemplo:V

à  D "
  N   "
.2   
  
  

  N    6  , M  !

 6 M   ,'
 
  '
 )

D     !
*  ,
   N ; à ' " #A# '
à( "  N ; '

 ('
àà
)
à
à
à
à
à
à
àD

Como podemos ver no corpo do programa há duas chamadas para a função  N  . No primeiro:

 N ; à

temos apenas especificado um argumento, mas a função de  N  permite até duas. Assim, a função
de  N  assumiu que o segundo parâmetro é  que é o que temos especificado acontecer se este parâmetro
não foi passado (note a declaração de função, que termina com  , M  , e não apenas  , ). Portanto, o
resultado dessa chamada de função é  ( (à ).
Na segunda chamada:

 N ; (6

Existem dois parâmetros, de modo padrão o valor para , (  , M  ) é ignorado e , assume o valor passado
como argumento, que é  , tornando o resultado retornado igual a   ( (   ).

  


V
Em C + + duas funções diferentes podem ter o mesmo nome se seus tipos de parâmetro ou o número é
diferente. Isso significa que você pode dar o mesmo nome para mais de uma função, caso tenha um número
diferente de parâmetros ou tipos diferentes de seus parâmetros. Por exemplo:V

à   8
.; ,   à( 
  
  

     6  , !


  1 , '
 )

 "    " 6 " , !
D 
   , '
* )
à(
    !
àà
 = M 6 5 M '
à "  M (6  M 6('
à
à   =6 5 '
à "  #A # '
à   6 6  '
à
" #A # '
àD
à* 
 ('
( )





Neste caso, nós definimos duas funções com o mesmo nome,   , mas um deles aceita dois parâmetros do
tipo  eo outro aceita-los do tipo " . × compilador sabe qual é a chamada em cada caso, examinando os
tipos passados como argumentos quando a função é chamada. Se for chamada com dois inteiros como
argumentos a que chama a função que tem dois  parâmetros em seu protótipo e, se for chamado com dois
carros alegóricos será chamada para aquele que tem dois " parâmetros em seu protótipo.

Na primeira chamada para   os dois argumentos passados são do tipo  , portanto, a função com o
primeiro protótipo é chamado; Essa função retorna o resultado da multiplicação de ambos os
parâmetros. Enquanto a segunda chamada passa dois argumentos do tipo " , então a função com o
segundo protótipo é chamado. Este tem um comportamento diferente: ele divide um parâmetro pelo
outro. Assim, o comportamento de uma chamada para   depende do tipo dos argumentos passados,
porque a função tem sido 

  .

×bserve que uma função não pode ser sobrecarregado apenas pelo seu tipo de retorno. Pelo menos um dos
seus parâmetros devem ter um tipo diferente.

! 
V
×   especificador indica ao compilador que a substituição inline é o preferido para a função chamada de
mecanismo usual para uma função específica. Isso não muda o comportamento de uma função em si, mas é
usada para sugerir ao compilador que o código gerado pelo corpo da função é inserido em cada ponto da função
é chamado, em vez de ser inserido apenas uma vez e executar uma chamada normal para ele , que geralmente
envolve uma sobrecarga adicional em tempo de funcionamento.

× formato de sua declaração é a seguinte:

    ,
   
   ! 
.2   )

ea chamada é como a chamada para qualquer outra função. Você não tem que incluir a   de palavras-
chave ao chamar a função, somente na sua declaração.

A maioria dos compiladores já otimizar o código para gerar funções inline quando for mais conveniente. Este
especificador indica apenas o compilador que a linha é o preferido para essa função.V

®
V
Recursividade é a propriedade que têm funções a ser chamado por eles mesmos. É útil para muitas tarefas,
como a classificação ou calcular o fatorial de números. Por exemplo, para obter o fatorial de um número (n!) a
fórmula matemática seriam:V

& 1 M P 1 Mà M 1 M  1 à

mais concretamente, 5! (Fatorial de 5) seria:

& M  1  1  1  1 à M à(

e uma função recursiva para calcular isso em C + + pode ser:

à  
  "  : "
  
  

  "     !
"  à
 
  1 "  Mà '
 
 
 à'
D )
*
à(     !
 
 '
àà
" #D  
 K @# '
à " #È#6€
  '
à
à " K 6#& M#6 "  
  '
à 
 ('
à )
à
àD
à*
(

×bserve como na função "  incluímos uma chamada para si, mas apenas se o argumento passado foi
maior que 1, pois caso contrário a função irá executar uma recursiva loop infinito em que uma vez chegou
a ( que vai continuar se multiplicando por todos os números negativos ( provavelmente provocando um erro de
estouro de pilha em tempo de execução).

Esta função tem uma limitação, devido ao tipo de dados que usamos em seu desenho (  ) para mais
simplicidade. ×s resultados obtidos não serão válidos para valores muito maiores do que 10! ou 15!,
dependendo do sistema de compilá-lo.

x

 ! V
Até agora, nós temos definidas todas as funções antes da primeira aparição de chamadas a elas no código-
fonte. Essas chamadas são geralmente em função   que temos sempre à esquerda no final do código-
fonte. Se você tentar repetir alguns dos exemplos das funções descritas até agora, mas colocando a
função   , antes de qualquer uma das outras funções que foram chamadas a partir de dentro dela,
você provavelmente irá obter erros de compilação. A razão é que para ser capaz de chamar uma função que
deve ter sido declarada em algum ponto antes do código, como temos feito em todos os nossos exemplos.

Mas há uma maneira alternativa para evitar escrever todo o código de uma função antes de poder ser utilizado
em principal ou em alguma outra função. Isto pode ser conseguido, declarando apenas um protótipo da função
antes de ser usado, em vez de toda a definição. Esta declaração é menor do que toda a definição, mas
suficientemente significativo para o compilador para determinar o seu tipo de retorno e os tipos de seus
parâmetros.

Sua forma é:

     
 45 à6  
 45 6  '

É idêntica a uma definição de função, exceto que ele não inclui o corpo da função em si (ou seja, as declarações
de função que nas definições normais são delimitados por chaves !) ) e ao invés de que a declaração final de
protótipo com um ponto e vírgula obrigatória ( ' ).

A enumeração parâmetro não precisa incluir os identificadores, mas apenas os especificadores de tipo. A
inclusão de um nome para cada parâmetro, na definição da função é opcional na declaração do protótipo. Por
exemplo, podemos declarar uma função chamada "
  com dois  parâmetros com qualquer uma
das seguintes declarações:V

à  "
    6     
 '
  "
    6  '

De qualquer forma, incluindo um nome para cada variável faz com que o protótipo mais legível.

à   D   "


.2  ]  D  
 K  (    @ * PK 
  
     @ à(( PK  S   D  
 K

    '

NC       '
 N       '

     !
D  '
*  !
  #D  
 K  (    @ # '   '
à( J    ') 6 F
 
& M ( '
  (')
àà
à N  J     !
à  È & M (  
  #PK  S    A  # '
à 
       ')
à
à N       !
à  È  MM ( 
  #$ K  S  # A  '
     ')
àD
à*
(







D
*

Este exemplo não é de fato um exemplo de eficiência. Estou certo de que, neste ponto você já pode fazer um
programa com o mesmo resultado, mas utilizando apenas metade das linhas de código que foram usados neste
exemplo. De qualquer forma este exemplo ilustra como funciona a prototipagem. Além disso, neste exemplo
concreto a prototipagem de pelo menos uma das duas funções é necessário para compilar o código sem erros.

As primeiras coisas que nós vemos é a declaração de funções   e S   :

à N  J     '
 N       '

Isso permite que essas funções devem ser utilizadas antes de serem definidas, por exemplo, no   ,
que agora está localizado onde algumas pessoas acham que ele seja um lugar mais lógico para o início de um
programa: o início do código-fonte.

Enfim, a razão pela qual este programa precisa de pelo menos uma das funções deve ser declarada antes de
ser definido é porque   existe uma chamada para   e   há uma chamada para   . Se
nenhuma das duas funções, tinha sido declarado anteriormente, um erro de compilação que aconteceria, já que
tanto   não seria visível do   (porque ainda não tenha sido declarada), ou S   não seria
visível do   (pelo mesmo motivo) .

Tendo o protótipo de todas as funções em conjunto no mesmo local no código-fonte é encontrada prática por
alguns programadores, e isso pode ser facilmente alcançado por todos os protótipos, que declara as funções no
início de um programa.


3
Uma matriz é uma série de elementos do mesmo tipo, colocados em locais contíguos de memória que podem
ser individualmente referenciados pela adição de um índice para um identificador exclusivo.

Isso significa que, por exemplo, podemos guardar cinco valores do tipo  em um array sem ter que declarar
5 variáveis diferentes, cada uma com um identificador diferente. Em vez disso, usando uma matriz que pode
armazenar 5 valores diferentes do mesmo tipo,  por exemplo, com um identificador exclusivo.

Por exemplo, uma matriz contém 5 valores inteiros do tipo  chamado , 5 poderia ser representado
assim:

onde cada painel em branco representa um elemento da matriz, que neste caso são valores inteiros do
tipo  . Estes elementos são numerados de ( a  vez em matrizes o primeiro índice é sempre ( ,
independentemente do seu comprimento.

Como uma variável normal, um array deve ser declarado antes de ser usado. Uma declaração típica para um
array em C + + é a seguinte:

    7   9'

onde   é um tipo válido (como  , " ...),  é um identificador válido e os    de campo
(que é sempre entre colchetes 79 ), especifica quantos desses elementos a matriz contém.

Portanto, a fim de declarar um array chamado ? 5 como o mostrado na figura acima, é tão simples como:V

 , 5 79'

× : ×s    de campo entre colchetes 79 que representa o número de elementos do array vai
realizar, deve ser uma  
 de valor, já que matrizes são blocos de memória não-dinâmico cujo tamanho
deve ser determinado antes da execução. A fim de criar matrizes com comprimento variável de memória
dinâmica é necessária, o que é explicado mais tarde nesses tutoriais.
c 
3
 

V
Ao declarar uma matriz regular de âmbito local (dentro de uma função, por exemplo), se não especifique o
contrário, os seus elementos não será inicializada com qualquer valor, por padrão, assim que seu conteúdo será
indeterminado até que nós guardamos algum valor em si. ×s elementos das matrizes globais e estáticos, por
outro lado, são automaticamente inicializados com seus valores padrão, que para todos os tipos fundamentais,
isto significa que são preenchidos com zeros.

Em ambos os casos, o local eo global, quando se declarar uma matriz, temos a possibilidade de atribuir valores
iniciais para cada um dos seus elementos, colocando os valores em chaves !) . Por exemplo:V

 , 5 79 M !à6 6 6 (6 à(à)'

Esta declaração teria criado uma matriz assim:

A quantidade de valores entre chaves !) não deve ser maior que o número de elementos que declarar para a
matriz entre colchetes 79 . Por exemplo, no exemplo da matriz , 5 temos declarou que tem 5 elementos e
na lista de valores iniciais dentro de chaves !) temos especificadas 5 valores, um para cada elemento.

Quando um arquivo de inicialização de valores está prevista uma matriz, C + + permite a possibilidade de
deixar os colchetes vazios 79 . Neste caso, o compilador irá assumir uma dimensão para a matriz que
corresponde ao número de valores compreendidos entre chaves !) :

 ? 5 79 M !à6 6 6 (6 à(à)'

Após esta declaração, a matriz , 5 seria 5 ints tempo, já temos os 5 valores de inicialização.


  
 

3V

Em qualquer ponto de um programa em que uma matriz é visível, podemos acessar o valor de qualquer dos
seus elementos individualmente como se fosse uma variável normal, sendo capaz de ler e modificar seu
valor. × formato é tão simples como:

 7J  9

Seguindo os exemplos anteriores em que , 5 tinha 5 elementos e cada um desses elementos foi do
tipo  , o nome que podemos usar para se referir a cada elemento é o seguinte:

Por exemplo, para armazenar o valor  no terceiro elemento de , 5 , nós poderíamos escrever a seguinte
instrução:V

, 5 79 M '

e, por exemplo, para passar o valor do terceiro elemento de , 5 para uma variável chamada
 , poderíamos
escrever:

 M , 5 79'
Portanto, a expressão , 5 79 é para todos os efeitos, como uma variável do tipo  .

×bserve que o terceiro elemento de , 5 é especificado , 5 79 , uma vez que o primeiro é , 5 7(9 , o
segundo é , 5 7à9 e, portanto, o terceiro é , 5 79 . Por esta mesma razão, o seu último elemento
é , 5 79 . Portanto, se escrevermos billy [5], estaríamos acessando o sexto elemento de , 5 e, portanto,
superior ao tamanho da matriz.

Em C + + é sintaticamente corretas para exceder o intervalo válido de índices para uma matriz. Isso pode criar
problemas, uma vez que o acesso fora do alcance elementos não causar erros de compilação, mas pode causar
erros de execução. A razão para isso é permitido será vista mais adiante quando começarmos a usar ponteiros.

Neste ponto é importante ser capaz de distinguir claramente entre os dois usos que colchetes 9 7 têm
relacionado a matrizes. Eles executam duas tarefas diferentes: uma é para especificar o tamanho das matrizes
que tenham sido declarados; ea segunda é especificar os índices para os elementos de matriz de concreto. Não
confundir estes dois usos possíveis dos suportes 79 com matrizes.

à  , 5 79'     .; 


 N  C
 , 5 79 M '     
      C

Se você ler cuidadosamente, você verá que um especificador de tipo sempre precede uma declaração de
variável ou matriz, embora nunca precede um acesso.

Algumas outras operações válidas com matrizes:

à , 5 7(9 M ' , 5 79 M ' , 5 , M 7  9' , 5 7, 5 799 M , 5 79  '




à   3=    5 à(
  
   

    '

 ? 5 79 M !à6 6 6 (6 à(à)'
  6  
  M ('

     !
D    M (6   6    ! 
  M , 5 79') 
  
'
*   (')
à(
àà
à
à
à
à
à


 
V

Matrizes multidimensionais podem ser descritas como "matrizes de matrizes". Por exemplo, uma matriz
bidimensional pode ser imaginada como uma tabela bidimensional feita de elementos, todos eles de um mesmo
tipo de dados uniforme.
O 5 representa uma matriz bidimensional de 3 por 5 elementos do tipo  . A forma de declarar essa matriz
em C + + seria:V

 O 5 79 79'

e, por exemplo, a forma para fazer referência ao segundo elemento verticalmente eo quarto horizontalmente
em uma expressão seria:

O 5 7à9 79

(Lembre-se que os índices de matriz sempre começar por zero).

Matrizes multidimensionais não são limitadas a dois índices (ou seja, duas dimensões). Eles podem conter
índices que forem necessárias. Mas cuidado! A quantidade de memória necessária para uma matriz aumenta
rapidamente com cada dimensão. Por exemplo:

 S
 7à((9 79 79 7(9 7(9'

declara uma matriz com um  elemento para cada segundo de um século, ou seja, mais de 3 mil
caracteres. Então, essa declaração iria consumir mais de 3 gigabytes de memória!

Arrays multidimensionais são apenas uma abstração para os programadores, uma vez que podemos obter os
mesmos resultados com uma matriz simples simplesmente colocando um fator entre os índices:

à  O 5 79 796   S F


N  
  O 5 7à9'    1  M à

Com a única diferença de que, com matrizes multidimensionais o compilador lembra a profundidade de cada
dimensão imaginária para nós. Tomemos como exemplo estes dois pedaços de código, com ambos
exactamente o mesmo resultado. Um usa uma matriz bidimensional e outra usa uma matriz simples:


3 
 
3  * 


 D "   
    "  
  O 5   D "   
    "  
   O 5
7
9 70E®<G®E96  6 '     !" 7 
 1 
9' 6  6     !"
 M (' 
 6       M ('  
  M (' 
 6       M ('  

6    !O 5 79 79 M  à 1  à ') 6    !O 5 7 
 1   9 M  à 1

 (')  à ') 
 (')

Nenhum dos dois códigos-fonte acima produz nenhuma saída na tela, mas ambos atribuir valores para o bloco
de memória chamado Jimmy, da seguinte forma:
Temos usado "constantes definidas" (   "  ) para simplificar a possíveis modificações futuras do
programa. Por exemplo, no caso em que decidimos ampliar a matriz para uma altura de 4 em vez dos 3 que
poderia ser feito simplesmente mudando a linha:

 D "  
 

para:
 D "  
 

sem a necessidade de fazer outras modificações para o programa.


3  
% V
Em algum momento podemos precisar de passar um array para uma função como um parâmetro. Em C + +
não é possível passar um bloco inteiro de memória em termos de valor como um parâmetro para uma função,
mas estamos autorizados a passar o seu endereço. Na prática, isso tem quase o mesmo efeito e é uma
operação muito mais rápida e mais eficiente.

Para aceitar matrizes como parâmetros a única coisa que temos que fazer quando se declara a função é
especificar em seus parâmetros o tipo de elemento da matriz, um identificador e um par de suportes
vazio 79 . Por exemplo, após a função:V

N          79

aceita um parâmetro do tipo "array de  "chamado   . Para passar para esta função uma matriz declarada
como:

 5 5 7(9'

seria suficiente para escrever um convite como este:

    5 5 '

Aqui você tem um exemplo completo:

à   E 5   \    à(
  
   

    '

N  : E 5     796   !
      M ('    6    
   79  ## ' 
  #A # ')

     !
D  " E 5 79 M !6 à(6 à)'
*   E 5 79 M !6 6 6 D6 à()' : E 5 " E 56  ' : E 5  E 56  '
à(   (')
àà
à
à
à
à
à
à
àD

Como você pode ver, o primeiro parâmetro (    79 ) aceita qualquer matriz cujos elementos são do
tipo  , independentemente do seu comprimento. Por essa razão, nós incluímos um segundo parâmetro que
diz a função do comprimento de cada array que passamos a ele como seu primeiro parâmetro. Isso permite
que o   loop que imprime a matriz para saber o intervalo de iterar na matriz passou sem sair do intervalo.

Em uma declaração de função também é possível incluir matrizes multidimensionais. × formato de um


parâmetro de matriz tridimensional é:

, 45 79 7 "


  9 7 "
  9

por exemplo, uma função com uma matriz multidimensional como argumento poderia ser:

N        5 5 79 79 79

×bserve que os colchetes primeiro 9 7 são deixadas em branco, enquanto os seguintes não são. Isto é assim
porque o compilador deve ser capaz de determinar dentro da função que é a profundidade de cada dimensão
adicional.

Matrizes, simples ou multidimensionais, passadas como parâmetros da função são uma fonte muito comum de
erros para programadores iniciantes. Eu recomendo a leitura do capítulo sobre ponteiros para uma melhor
compreensão sobre como os arrays operar.

& /0 



Como você já sabe, o padrão C + + Biblioteca implementa uma poderosa cadeia de classe, que é muito útil
para segurar e manipular cadeias de caracteres.No entanto, porque as cordas estão em seqüências de
caracteres de fato, podemos representá-los também como matrizes simples de  elementos.

Por exemplo, a matriz seguinte:V

 O 5 7(9'

é uma matriz que pode armazenar até 20 elementos do tipo  . Ele pode ser representado como:

Portanto, nessa matriz, em teoria, podemos armazenar as seqüências de caracteres até 20 caracteres. Mas
também podemos armazenar seqüências mais curtas. Por exemplo, O 5 poderia armazenar em algum ponto
em um programa a seqüência de #$%# ou a seqüência de #8  C P# , já que ambos são menores do que
20 caracteres.

Portanto, uma vez que a matriz de caracteres pode armazenar seqüências mais curtas do que o seu
comprimento total, um caractere especial é usado para sinalizar o fim da seqüência válida: o  

 ,
cuja constante literal pode ser escrito como BA (B (barra invertida, zero) .
Nossa matriz de 20 elementos do tipo  , chamada - 5 , pode ser representado armazenar as seqüências
de caracteres #$%# e #8  C P# como:

Note como depois do conteúdo válido um caractere nulo ( BA (B ) foi incluída a fim de indicar o fim da
seqüência. ×s painéis em cor cinza representam  elementos com valores indeterminados.

c 
3
'  /0 




   V
Como arrays de caracteres são vetores comuns que seguem todas as regras mesmo. Por exemplo, se
quisermos inicializar um array de caracteres com alguma seqüência pré-determinada de caracteres que podem
fazê-lo, tal como qualquer outra matriz:V

 5l  79 M ! B^B 6 B B 6 BB 6 BB 6 BB 6 BA (B )'

Neste caso, teria declarado um array de 6 elementos do tipo  inicializado com os personagens que formam
a palavra #$%# mais um personagem nulo BA (B no final.
Mas arrays de  elementos têm um método adicional para inicializar seus valores: usando literais string.

Nas expressões que usamos em alguns exemplos nos capítulos anteriores, constantes que representam
seqüências inteiras de personagens já apareceram várias vezes. Estes são especificados envolvendo o texto
para tornar-se uma seqüência literal entre aspas (") por exemplo.:

#$ 
 S@#

é uma constante string literal que temos, provavelmente, já utilizado.

citado cordas duplas ( # ) são constantes literais cujo tipo é na verdade um nulo encerrado matriz de
caracteres. Então strings literais entre aspas duplas sempre tem um caractere nulo ( BA (B ) automaticamente
anexado ao final.

Portanto, podemos inicializar a matriz de  elementos chamados 5l  terminou com um nulo seqüência
de caracteres de um destes dois métodos:

à  5l  79 M ! B^B 6 B B 6 BB 6 BB 6 BB 6 BA (B )'


  5l  79 M #$%# '

Em ambos os casos, a matriz de caracteres 5l  é declarada com um tamanho de 6 elementos do tipo  :
os 5 caracteres que compõem a palavra #$%#mais um caractere nulo final ( BA (B ), que especifica o fim da
seqüência e que , no segundo caso, quando se utilizam aspas ( # ) é anexado automaticamente.

Por favor note que estamos falando de inicializar um array de caracteres no momento em que está sendo
declarado, e não sobre a atribuição de valores a eles uma vez que já tinha sido declarado. De facto, porque
este tipo de nulo matrizes de caracteres terminadas são matrizes regulares que têm as mesmas restrições que
nós temos com qualquer outra matriz, de modo que não são capazes de copiar blocos de dados com uma
operação de atribuição.

Assumindo 5 = é um 79  variáveis, expressões dentro de um código como:

à 5 = M #$%# ' 5 = 79 M #$%# '




que ' seja válido, nem como seria:

5 = M ! B^B 6 B B 6 BB 6 BB 6 BB 6 BA (B )'

A razão para isso pode se tornar mais compreensível uma vez que você sabe um pouco mais sobre ponteiros,
desde então ele vai ficar claro que uma matriz é na verdade um ponteiro constante que aponta para um bloco
de memória.

Ú
  

 /0 


V

NULL-Terminated seqüência de caracteres são a maneira natural de tratar strings em C + +, para que possam
ser usadas enquanto tal em muitos procedimentos. Na verdade, literais string regulares deste tipo (  79 )
e também pode ser usado na maioria dos casos.

Por exemplo,   e   apoio nulo seqüências denunciado como recipientes válida para seqüências de
caracteres, para que eles possam ser usados diretamente para extrair seqüências de caracteres de   ou para
inseri-los em  ,
 . Por exemplo:V

à   PG00M+     FHI      : "N 6    


  
    -;&

    '

    !
  
 79 M #: "N 6    
   @# '
  
.; 79 M #$%# '
  7
 D(9' 
 F
;'   
 ' 
 
.; 
 
D #&# '
*   (')
à(
àà
à
à
à

Como você pode ver, temos declarou três arrays de  elementos. ×s dois primeiros foram inicializados com
constantes seqüência literal, enquanto a terceira foi deixado não inicializado. Em qualquer caso, temos que
speficify o tamanho da matriz: nos dois primeiros ( 
 e 
.; ), o tamanho foi definido
implicitamente pelo comprimento da constante literal foram inicializados com. Enquanto que
para 
 temos explicitamente especificado que tem um tamanho de 80 caracteres.

Finalmente, as seqüências de caracteres armazenados em  arrays podem ser facilmente convertidos
em   de objetos usando apenas o operador de atribuição:

à 5   '
  5 79 M #
  =# ' 5  M 5'


V
 
Já vimos como as variáveis são vistos como células de memória que pode ser acessada usando seus
identificadores. Desta forma, não precisa se preocupar com a localização física dos nossos dados dentro da
memória, nós simplesmente usamos a sua identificação sempre que queria referir-se à nossa variável.
A memória do seu computador pode ser imaginado como uma sucessão de células de memória, cada um do
tamanho mínimo que computadores administrem (um byte). Estas células de memória de um byte são
numeradas de forma consecutiva, de modo a, dentro de qualquer bloco de memória, cada célula tem o mesmo
número que a anterior mais um.

Desta forma, cada célula pode ser facilmente localizado na memória, porque ele tem um endereço único e
todas as células de memória segue um padrão sucessivas. Por exemplo, se nós estamos olhando para celular
1776, sabemos que vai ser mesmo entre células de 1775 e 1777, exatamente mil células após 776 e
exatamente mil células antes de pilha 2776.V

®!0 
  
 <V
Assim que nós declaramos uma variável, a quantidade de memória necessária é atribuído por ele em uma
posição específica na memória (o endereço de memória). Nós geralmente não ativamente decidir o local exato
da variável dentro do painel de células que nós imaginamos que a memória seja - Felizmente, essa é uma
tarefa executada automaticamente pelo sistema operacional durante a execução. No entanto, em alguns casos,
podemos estar interessados em conhecer o endereço onde a variável está sendo armazenado durante a
execução, a fim de operar com posições relativas a ele.

× endereço que localiza uma variável na memória é o que chamamos de


Ñ
 para essa variável. Esta
referência a uma variável podem ser obtidas pelo anterior o identificador de uma variável com um sinal de E
comercial ( € ), conhecido como operador de referência, e que pode ser traduzido literalmente como
"endereço". Por exemplo:V

  M €5'

Isso seria atribuir a   o endereço da variável 5 , desde quando precede o nome da variável 5 com o
operador de referência ( € ) não estamos mais falando sobre o conteúdo da variável em si, mas sobre a sua
referência (ou seja, o seu endereço na memória).

De agora em diante vamos supor que E5 é colocado durante a execução no endereço de memória à . Esse
número ( à ) é apenas uma suposição arbitrária estamos inventando agora, a fim de ajudar a esclarecer
alguns conceitos neste tutorial, mas na realidade, não podemos saber antes de tempo de execução real do
valor do endereço de uma variável terá na memória.

Considere o seguinte fragmento de código:

à 5 M ' "  M 5'   M €5'





×s valores contidos em cada variável após a execução do presente, são mostrados no diagrama abaixo:

Primeiro, temos atribuído o valor de 25 a 5 (uma variável cujo endereço na memória que temos assumido
como sendo 1776).

A segunda declaração copiado para "  o conteúdo da variável 5 (que é 25). Esta é uma operação de
atribuição padrão, como temos feito muitas vezes por isso antes.

Finalmente, as cópias de declaração de terceiros para +  não o valor contido na 5 , mas uma referência a
ele (isto é, seu endereço, que assumiram a à ). × motivo é que nesta terceira operação de atribuição temos
precedidas do identificador 5 com o operador de referência ( € ), de modo que já não estavam se referindo
ao valor de Andy, mas a sua referência (o seu endereço na memória).

A variável que armazena a referência a outra variável (como +  , no exemplo anterior) é o que chamamos
de m
  . ×s ponteiros são um poderoso recurso muito da linguagem C + + que tem muitos usos na
programação avançada. Mais à frente, vamos ver como esse tipo de variável é utilizada e declarada.

× 
 !0 
1V

Acabamos de ver que uma variável que armazena uma referência a outra variável é chamado de
ponteiro. Ponteiros são disse para "apontar para" a variável cuja referência que eles armazenam.

Usando um ponteiro, podemos acessar diretamente o valor armazenado na variável que ele aponta. Para fazer
isso, nós simplesmente temos que precedem o ponteiro identificador com um asterisco (*), que atua como
operador dereference e que pode ser traduzido literalmente como "valor apontado por".

Assim, seguindo com os valores do exemplo anterior, se escrevermos: V

1 ?  M  '

(Que poderíamos ler como: " ?  igual ao valor apontado por   ") ,  levaria o valor  , já
que +  é à , eo valor apontado pelo 1776 é 25.

Você deve diferenciar claramente que a expressão  +  se refere ao valor à6 , enquanto 1 +  (com um
asterisco 1 antes do identificador) refere-se ao valor armazenado no endereço à , que neste caso
é  . ×bserve a diferença de seleção incluindo ou não o operador dereference (Eu incluí um comentário
explicativo de como cada uma dessas duas expressões pode ser lido):

à ,  M  '  ,  
    à
 ,  M 1  '  ,  
  N      

×bserve a diferença entre os operadores de referência e dereference:

>V E é o operador de referência e pode ser lido como "endereço de"V


>V * É o operador de dereferência e pode ser lido como "valor apontado por"

Assim, eles têm complementar (ou oposta) significados. Uma variável referenciada com pode ser
dereferenced com 1 .

Anteriores foram realizados os seguintes operações de atribuição:V

à 5 M '   M €5'



Logo após essas duas afirmações, todas das seguintes expressões daria certo como resultado:

à 5 MM  € 5 MM à à MM 1     MM 






A primeira expressão é bastante clara, considerando que a operação de cessão realizados em 5 foi 5 M
 . × segundo usa o operador de referência ( € ), que retorna o endereço da variável 5 , que assumiu que
para ter um valor de à . × terceiro é um tanto óbvio, já que a segunda expressão era verdade e da
operação de cessão realizados em +  foi   M € E5 . A quarta expressão usa o operador de dereferência
( 1 ) que, como acabamos de ver, pode ser lido como "valor apontado por" e, o valor apontado por   é
realmente  .

Então, depois de tudo isso, você também pode-se inferir que, enquanto o endereço apontado
por   permanece inalterada a seguinte expressão também será verdadeiro:

1 +  MM 5

x

 
   V
Devido à capacidade de um ponteiro para se referem diretamente para o valor que ele aponta, torna-se
necessário especificar em sua declaração de que tipo de dados de um ponteiro que vai apontar. Não é a mesma
coisa para apontar para um  como para apontar para um  ou " .

A declaração de ponteiros segue este formato:

    1'

onde   é o tipo de dados do valor que o ponteiro se destina a apontar. Este tipo não é o tipo do ponteiro em
si! mas o tipo de dados que o ponteiro aponta. Por exemplo:V

à  1 K '
    1'
 "  
, 1'

Estes são três declarações de ponteiros. Cada um deles destina-se a apontar para um tipo de dados diferentes,
mas na verdade todos eles são ponteiros e todos eles vão ocupar o mesmo espaço na memória (o tamanho da
memória de um ponteiro depende da plataforma onde o código está acontecendo para executar). No entanto,
os dados a que ponto a não ocupar o mesmo espaço nem são do mesmo tipo: o primeiro aponta para um  ,
o segundo para um  eo último a uma ,]  . Portanto, embora estas três variáveis exemplo são todos os
ponteiros que ocupam o mesmo tamanho em memória, é dito que eles têm diferentes tipos:  1 ,  1 e 1
" , respectivamente, dependendo do tipo eles apontam.

Quero enfatizar que o sinal asterisco ( 1 ) que usamos quando declarar um ponteiro significa apenas que ele é
um ponteiro (que faz parte do seu especificador composto tipo), e não deve ser confundido com o operador
dereference que temos visto uma pouco mais cedo, mas que também é escrito com um asterisco ( 1 ). Eles
simplesmente são duas coisas diferentes representados com o mesmo sinal.

Agora dê uma olhada neste código:

à   
   
  
   

    '

     !
  " N
6  L
'
 5   1' 5   M 5   €" N
' 1 M à(' 5   M €  L
' 5   1 M (

# L
S#  L
 '
   (')
D
*
à(
àà
à
à
à
à
à
à

×bserve que, embora nunca diretamente definir um valor para qualquer " N
ou  L
, tanto
acabar com um valor definido indiretamente através do uso de 5   . Este é o procedimento:

Primeiro, temos atribuído como valor da 5   uma referência para " N
usando o operador de
referência ( € ).

A fim de demonstrar que um ponteiro pode tomar vários valores diferentes no mesmo programa que eu tenho
repetido o processo com  L
e que mesmo ponteiro, 5   .

Aqui está um exemplo um pouco mais elaborada:

à       " N


  
   

    '

    !
  " N
M 6  L
M à'
  1 à6 1 6 à M €" N
'   à M  .  " N

  M €  L
'    M  .   L

D 1 à M à('   N    à M à(
* 1 1  M à'   N     M N    à
à( à M '   à M  N    S  
1 à M ('   N    à M (
àà
à 
  #" N
S# " N
 ' 
  # L
S#  L
 '
à   (')
à
à
à
à
àD
à*
(

Tenho incluído como um comentário em cada linha como o código pode ser lido: "comercial ( € ) como
"endereço de" e um asterisco ( 1 ) como "valor apontado por".

×bserve que há expressões com ponteiros à e  , ambos com e sem operador dereference ( 1 ). × significado
de uma expressão usando o operador de dereferência ( 1 ) é muito diferente de um que não: Quando este
operador precede o nome do ponteiro, a expressão se refere ao valor que está sendo apontado, ao mesmo
tempo quando um nome de ponteiro aparece sem este operador, refere-se para o valor do ponteiro em si (ou
seja, o endereço do que o ponteiro está apontando).

×utra coisa que pode chamar sua atenção é a linha:


 1 à6 1 '

Este declara dois ponteiros usado no exemplo anterior. Mas repare que há um asterisco (*) para cada ponteiro,
de modo que ambos têm o tipo  1 (ponteiro para  ).

Caso contrário, o tipo para a segunda variável declarada em que a linha teria sido  (e não  1 ), devido
às relações de precedência. Se tivéssemos escrito:

 1 à6 '

à teria certamente  1 tipo, mas  teria tipo  (espaços não importa a todos para essa finalidade). Isto é
devido às regras de precedência do operador. Mas de qualquer maneira, basta lembrar que você tem que
colocar um asterisco por ponteiro é suficiente para a maioria dos usuários do ponteiro.

 
3V
× conceito de matriz é muito ligado ao do ponteiro. Na verdade, o identificador de uma matriz é equivalente
para o endereço do seu primeiro elemento, como um ponteiro é equivalente para o endereço do primeiro
elemento que chama a atenção para, então na verdade eles são o mesmo conceito. Por exemplo, supondo que
estas duas declarações:V

à  K  7(96
  1 '

A operação de atribuição a seguir seria válido:

M K '

Depois disso, e K  seriam equivalentes e teria as mesmas propriedades. A única diferença é que nós
podemos mudar o valor do ponteiro por outro, ao passo que  K  vão sempre apontar para o primeiro
dos 20 elementos do tipo  com o qual ele foi definido. Portanto, ao contrário , que é um ponteiro
comum, K  é uma matriz e uma matriz pode ser considerado um m
  
. Portanto, a
atribuição a seguir não seriam válidas:

K  M '

Porque  K  é um array, por isso funciona como um ponteiro constante, e não podemos atribuir valores
para constantes.

Devido às características de variáveis, todas as expressões que incluem ponteiros no exemplo a seguir são
perfeitamente válidas:

à   :   
  
   

    '

    !
  K  796
  1 6 M K ' 1 M à(' M ('  ' 1 M € K  79 ' 1 M (6 M K   ' 1 M (
 K ' 1   M ('
D      M (6  '    
 K  79  #6# '
*   (')
à(
àà
à
à
à
à
à
à

No capítulo sobre matrizes usamos colchetes ( 79 ) várias vezes a fim de especificar o índice de um elemento
da matriz a que queria referir. Bem, estes assinam operadores colchete 79 também são
uma !  operador conhecido como m
  
ÑÑ
.Eles dereference a variável seguem apenas
como 1 faz, mas também adicionar o número entre parênteses para o endereço a ser dereferenced. Por
exemplo:

à
 79 M ('    7    9 M (
 1   M ('        M (

Estas duas expressões são equivalentes e válidas tanto se


 é um ponteiro, ou se
 é uma matriz.

 
3
'    V
Ao declarar ponteiros, a gente pode querer especificar explicitamente qual a variável que queremos que eles
apontam para:V

à  K '
  5 1 M €
, '

× comportamento deste código é equivalente a:

à  K '
  1 56 5 M €
, '


Quando a inicialização do ponteiro tem lugar sempre estamos atribuindo o valor de referência para onde o
ponteiro aponta ( +5 ), nunca o valor que está sendo apontado ( 1 5 ). Você deve considerar que, no
momento de declarar um ponteiro, o asterisco (1 ) indica apenas que é um ponteiro, ele não é o operador de
dereferência (embora ambos usam o mesmo sinal: *). Lembre-se, são duas funções diferentes de um
sinal. Assim, devemos tomar cuidado para não confundir com o código anterior:

à  K '
  1 56 5 1 M €
, '


que está incorreto, e mesmo assim não teria muito sentido neste caso, se você pensar sobre isso.

Como no caso de matrizes, o compilador permite que o caso especial que queremos para inicializar o conteúdo
ao qual o ponteiro aponta com constantes no mesmo instante, o ponteiro é declarado:

 1  5 M #$%# '


Neste caso, o espaço de memória é reservada para conter #$%# e, em seguida, um ponteiro para o primeiro
caractere do bloco de memória é atribuído a + 5 . Se imaginarmos que #$%# é armazenado na memória
locais que começam em endereços 1702, podemos representar a declaração anterior como:

É importante indicar que  5 contém o valor de 1702, e não ## , nem #$%# , embora na verdade 1702 é o
endereço de ambos.

× ponteiro  5 aponta para uma seqüência de caracteres e pode ser lido como se fosse uma matriz (lembre-
se que uma matriz é igual a um ponteiro constante). Por exemplo, podemos acessar o quinto elemento do
array com qualquer uma dessas duas expressões:

à 1 + 5  5  79


Ambas as expressões têm um valor de BB (o quinto elemento da matriz).


  V

Para realizar operações aritméticas em ponteiros é um pouco diferente do que para conduzi-los em tipos de
dados inteiros regular. Para começar, a única adição e subtração são operações de poder ser realizado com
eles, os outros não fazem sentido no mundo dos ponteiros. Mas a adição e subtração têm um comportamento
diferente com os ponteiros de acordo com o tamanho do tipo de dados para que eles apontam.

Quando vimos os diferentes tipos de dados fundamentais, vimos que alguns ocupam menos espaço, ou mais do
que outros na memória. Por exemplo, vamos supor que em um dado compilador para uma máquina
específica,  tem 1 byte,   ocupa 2 bytes e   leva 4.

Suponha que nós definimos três ponteiros neste compilador: V

à  5 1'


 
 5  1'
  5 1'

e que nós sabemos que eles apontam para posições de memória à((( , ((( e ((( , respectivamente.

Então, se escrever:

à 5  ' 5   ' 5  '





5 , como você pode esperar, deve conter o valor de à((à . Mas não tão obviamente, 5  conteria o
valor (( , e 5 conteria (( , apesar de terem sido aumentado cada uma só vez. A razão é que, ao
adicionar um a um ponteiro que estamos fazendo com que ela aponte para o elemento seguinte do mesmo tipo
com o qual ele foi definido e, portanto, o tamanho em bytes do tipo apontado é adicionado ao ponteiro.
Isto é aplicável tanto ao somar e subtrair qualquer número para um ponteiro. Ele iria acontecer exactamente o
mesmo se escrever:

à 5 5 M  à' 5  5  M  à' 5 5 M  à'





Ambos aumentam o (   ) e diminuir ( M ) ×s operadores têm precedência de operador maior do que o


operador de dereferência ( 1 ), mas ambos têm um comportamento especial quando usada como sufixo (a
expressão é avaliada com o valor que tinha antes de ser aumentada) . Portanto, a seguinte expressão pode
levar à confusão:

1 :  

Porque   tem maior precedência que 1 , esta expressão é equivalente a 1    . Portanto, o que faz é
aumentar o valor de p (de modo que agora aponta para o elemento seguinte), mas porque + + é usado como
postfix toda a expressão é avaliada como o valor apontado pela referência original (o endereço do ponteiro
apontado para antes de ser aumentada).

×bserve a diferença com:

1 :  
Aqui, a expressão teria sido avaliado como o valor apontado por aumentado em um. × valor de (o próprio
ponteiro) não seria alterada (o que está sendo modificada é o que está sendo apontada por este ponteiro).

Se escrevermos:

1 : M F     1'

Porque   tem uma precedência maior do que 1 , ambos e F são aumentados, mas porque os operadores
aumento (   ) são utilizados como postfix e não o prefixo, o valor atribuído à 1 é 1 F

 ambos e F são aumentadas . E então ambos serão aumentados. Seria equivalente a:

à 1 : M F 1'   6 F  '


Como sempre, eu recomendo que você use parênteses  , a fim de evitar resultados inesperados e para dar
maior legibilidade ao código.

 

  V
C + + permite o uso de ponteiros que apontam para ponteiros, que estes, por sua vez, apontam para dados
(ou até mesmo para outros ponteiros). A fim de fazer isso, só precisamos adicionar um asterisco ( 1 ) para
cada nível de referência nas suas declarações:V

à  @

  1 ,'
  11 6  M BCB 6 , €'  M €,'




Isto, supondo que a memória de locais escolhidos aleatoriamente para cada variável de ( , D(* e à(( ,
pode ser representado como:

× valor de cada variável é escrito dentro de cada célula, as células estão sob seus respectivos endereços na
memória.

A novidade neste exemplo é variável  , que pode ser utilizado em três diferentes níveis de indireção, cada uma
delas corresponderia a um valor diferente:

>V  tem o tipo  11 e um valor de D(*V


>V  1 tem um tipo  1 e um valor de (
>V 11  tem o tipo  e um valor de BCB

  V


× NC  tipo de ponteiro é um tipo especial de ponteiro. Em C + +, 
 representa a ausência do tipo, nula
ponteiros para os ponteiros que apontam para um valor que não tem nenhum tipo (e, portanto, também uma
duração indeterminada e propriedades dereference indeterminado).

Isso permite que os ponteiros void para apontar para qualquer tipo de dados, a partir de um valor inteiro ou
um float para uma seqüência de caracteres. Mas em troca, eles têm uma grande limitação: os dados apontados
por eles não podem ser directamente dereferenced (que é lógico, pois não temos nenhum tipo de dereference
a), e por isso sempre teremos de lançar o endereço do ponteiro nulo para algum tipo outro ponteiro que aponta
para um tipo de dados concretos antes de dereferencing-lo.

Um de seus usos podem ser para passar parâmetros genéricos para uma função: V

à   R  56 à
  
   

    '

N  
   N  1 6   C !
    C MM  C "   !  1  '  M   1 D'   1 : ')
      C MM  C "   !   1'  M   1 D'   1    '))

D     !
*   M B=B '
à(  , M à(' 
  € 6  C "  ' 
  € ,6  C " , ' 
   #6# ,  '
  (')
àà
à
à
à
à
à
à
àD
à*
(

 C " é um operador integrado na linguagem C + + que retorna o tamanho em bytes do seu parâmetro. Para
tipos de dados dinâmicos não esse valor é uma constante. Assim, por exemplo,  C "  é
 ,
porque  é um tipo byte.

   V
Um ponteiro nulo é um ponteiro regular de qualquer tipo de ponteiro que tem um valor especial que indica que
ele não está apontando para qualquer referência válida ou endereço de memória. Este valor é o resultado de
tipo-casting o valor inteiro zero para qualquer tipo de ponteiro.V

à  1 6 M ('   
 N    



Não confundir com ponteiros nulos ponteiros void. Um ponteiro nulo é um valor que pode assumir qualquer
ponteiro para representar que ele está apontando para "lugar nenhum", enquanto um ponteiro void é um tipo
especial de ponteiro que pode apontar para algum lugar sem um tipo específico. Uma se refere ao valor
armazenado no ponteiro propriamente dito e outro para o tipo de dados que ele aponta.

 

! V
C + + permite operações com ponteiros para funções. × uso típico deste é para passar uma função como um
argumento para outra função, desde que estes não podem ser passados dereferenced. Para declarar um
ponteiro para uma função que temos que declará-la como o protótipo da função, exceto que o nome da função
é incluída entre parênteses  e um asterisco ( 1 ) é inserido antes do nome:V

à   :    "
.2  D
  
   

    '

    6  , !     , ')

  
, .;   6  , !   , ')

D   .;   =6  56  1 "
   6  !
*  6  M 1 "
 =6 5 '
à(    ')
àà
 !  
à  6 '
à  1     6  M 
, .;'   .; M 6 6   .; '  M  .; (6 6 
à   ' 
 '
à   (')
à
à
àD
à*
(








No exemplo, a   é um ponteiro para uma função que tem dois parâmetros do tipo  . Ele é
imediatamente atribuído a apontar para a função de 
, .; , tudo em uma única linha:

 1     6  M 
, .;'

V
(
 %

Até agora, em todos os nossos programas, só temos tido tanta memória disponível como nós declaradas para
nossas variáveis, tendo o tamanho de todos eles a ser determinado no código-fonte, antes da execução do
programa. Mas, e se precisamos de uma quantidade variável de memória que só pode ser determinada durante
a execução? Por exemplo, no caso em que precisamos de alguma entrada do usuário para determinar a
quantidade necessária de espaço de memória.

A resposta é 
%  & , para a qual C + + integra os operadores N e =
. V

× 
 D  EV
Para solicitar a memória dinâmica, usamos o operador de N . N é seguido por um tipo de dados e, se
uma seqüência de mais de um elemento é necessário, o número destes entre colchetes 79 . Ela retorna um
ponteiro para o início do novo bloco de memória alocada. Sua forma é:

  M N  
  M 7
, 4"4   9 N  

A primeira expressão é usada para alocar memória para conter um único elemento do tipo    . × segundo
é usado para atribuir um bloco (uma matriz) de elementos de tipo   , onde 
, 4"4    é um valor
inteiro que representa a quantidade destes. Por exemplo:V

à  1 ,,,56 ?,,5 M N  79'




Neste caso, o sistema atribui dinamicamente espaço para cinco elementos do tipo  e retorna um ponteiro
para o primeiro elemento da sequência, que é atribuído a ?,,5 . Portanto, agora, ,,,5 aponta para um bloco
válido de memória com espaço para cinco elementos do tipo  .

× primeiro elemento apontado por Bobby pode ser acessado tanto com a expressão ?,,5 7(9 ou a
expressão 1 ?,,5 . Ambos são equivalentes, como foi explicado na seção sobre ponteiros. × segundo
elemento pode ser acessado tanto com ?,,5 7à9 ou 1 ,,,5 à e assim por diante ...

Você pode estar se perguntando a diferença entre declarar uma matriz normal e atribuição dinâmica de
memória para um ponteiro, como acabamos de fazer. A diferença mais importante é que o tamanho de uma
matriz tem que ser um valor constante, o que limita seu tamanho para o que nós decidimos no momento da
concepção do programa, antes de sua execução, enquanto que a alocação de memória dinâmica permite
atribuir memória durante o execução do programa (runtime) usando qualquer variável ou um valor constante
de seu tamanho.

A dinâmica de memória solicitada pelo nosso programa é atribuído pelo sistema a partir da pilha de
memória. No entanto, a memória do computador é um recurso limitado, e pode ser esgotado. Portanto, é
importante ter algum mecanismo para verificar se o nosso pedido para alocar a memória foi bem sucedida ou
não.

C + + fornece dois métodos padrão para verificar se a alocação foi bem sucedida:

Uma delas é o tratamento de exceções. Usando este método uma exceção do tipo ,4 é acionada
quando a alocação falhar. As exceções são a C + + poderoso recurso explicado mais tarde nesses
tutoriais. Mas, por agora você deve saber que, se essa exceção é lançada e não é tratado por um manipulador
específico, a execução do programa é encerrado.

Este método de exceção é o método padrão usado pelo novo, e é o utilizado em uma declaração como:

,,,5 M N  79'    ;


 = .; S .

× outro método é conhecido como  l , eo que acontece quando ele é usado é que, quando uma alocação
de memória falha, ao invés de lançar um ,4 exceção ou encerrar o programa, o ponteiro retornado
por N é um ponteiro nulo, eo programa continua sua execução .

Este método pode ser especificado usando um objeto especial chamado  l , declarado no
cabeçalho  l , como argumento para N :

,,,5 M N  l  79'

Neste caso, se a atribuição deste bloco de memória falha, a falha pode ser detectada verificando se ,,,5 teve
um valor de ponteiro nulo:

à  1 ,,,56 ?,,5 M N  l  79'


  ,,,5 MM ( !
   ,
.;     ]   +   
 )'


Este  l método requer mais trabalho do que o método de exceção, uma vez que o valor retornado deve
ser verificada após cada alocação de memória, mas vou usá-lo nos nossos exemplos, devido à sua
simplicidade. De qualquer forma esse método pode se tornar tedioso para projetos maiores, onde o método de
exceção é geralmente preferido. × método de exceção será explicado em detalhe mais tarde neste tutorial.

× 
 


DEV
Desde a necessidade de memória dinâmica é geralmente limitada a momentos específicos dentro de um
programa, uma vez que não é mais necessária que deve ser liberada para que a memória se torna disponível
novamente para outras solicitações de memória dinâmica. Este é o objetivo do operador    , cujo formato
é:V

à =
 '
 =
 9 7'

A primeira expressão deve ser usada para apagar a memória alocada para um único elemento, eo segundo
para a memória alocada para arrays de elementos.

× valor passado como argumento para excluir deve ser um ponteiro para um bloco de memória previamente
alocado com N , ou um ponteiro nulo (no caso de um ponteiro nulo, =
não produz nenhum efeito).
à   ®  ,MM  _
 K  F
NI  
     
 K @ D D    K @  L
  
  l

    '

     !
   6
  1 ' 
  #_
 K  F
NI     N V# '
D   6 M N  l  7 9'
*   MM ( 
  #3 @ E  ]  ;    ,
J# '
à( 
 
!
àà
   M (6   6    !
  #D    K @# '  
à 79') 
  #LI   
@# 6
à    M (6   6    
  79  ## '
à =
79 ')
à   (')
à
à
àD
à*
(







D

×bserve como o valor entre parêntesis na N declaração é um valor variável digitada pelo usuário ( ), e não
um valor constante:

M N  l  7 9'

Mas o usuário poderia ter entrado um valor para i tão grande que nosso sistema não pode lidar com isso. Por
exemplo, quando eu tentei dar um valor de 1000 milhões para o "Quantos números" pergunta, meu sistema
não pôde alocar a memória tanto para o programa e recebi a mensagem de texto que preparou para este caso
( @  ]  ; `   ,
J ). Lembre-se que no caso em que tentou alocar a memória, sem
especificar o parâmetro nothrow na nova expressão, uma exceção seria lançada, que se não for tratado termina
o programa.

É uma boa prática de sempre verificar se um bloco de memória dinâmica com êxito foi atribuído. Portanto, se
você usar o  l método, você deve sempre verificar o valor do ponteiro retornado. Caso contrário, use o
método de exceção, mesmo se você não tratar a exceção. Desta forma, o programa será encerrado neste
ponto, sem causar resultados inesperados de continuar a execução de um código que pressupõe um bloco de
memória de ter sido atribuída, quando na verdade ele não tem.

x %
(
&c*ÃV

×peradores de N e   são exclusivos do C + +. Eles não estão disponíveis na linguagem C. Mas usando
a linguagem C pura e sua biblioteca, a memória dinâmica também pode ser usado com as
funções malloc , calloc , realloc e livre , que também estão disponíveis em C + +, incluindo
o  , arquivo de cabeçalho (vejacstdlib para mais informações).

×s blocos de memória alocada por essas funções não são necessariamente compatíveis com os retornados pelo
novo, por isso cada um deve ser manipulada com seu próprio conjunto de funções ou operadores.
M
x
 
Nós já aprendemos como os grupos de dados seqüenciais podem ser usados em C + +. Mas isso é um pouco
restritivo, pois em muitas ocasiões que queremos loja não são seqüências simples de todos os elementos do
mesmo tipo de dados, mas conjuntos de elementos diferentes, com diferentes tipos de dados.V



 V
Uma estrutura de dados é um grupo de elementos de dados agrupados sob um nome. Estes elementos,
conhecidos como 
  , podem ter diferentes tipos e tamanhos diferentes. As estruturas de dados são
declarados em C + + usando a seguinte sintaxe:

struct {structure_name
member_type1 member_name1;
member_type2 member_name2;
member_type3 member_name3;
.
.
×bject_names};

onde 

4 é um nome para o tipo de estrutura, ,O 4 pode ser um conjunto de
identificadores válidos para objetos que tenham o tipo desta estrutura. Dentro de chaves !) existe uma lista
com os membros de dados, cada um é especificado com um tipo e um identificador válido como o seu nome.

A primeira coisa que temos que saber é que uma estrutura de dados cria um novo tipo: Quando uma estrutura
de dados é declarado, um novo tipo de identificador especificado como 

4 é criado e pode ser
usado no resto do programa como se fosse qualquer outro tipo. Por exemplo:V

à 
 
 !
  '
 " .')' .; 
' 
 ,6  ;'





Temos primeiro declarado um tipo de estrutura chamado 


 com dois membros:   eo . , cada
um de um tipo diferente fundamental. Temos, em seguida, usou este nome do tipo de estrutura ( 
 )
para declarar três objetos desse tipo: .; , , e  ; como teria feito com qualquer tipo de dados
fundamental.

Uma vez declarada, 


 tornou-se um tipo novo nome válido como os fundamentais  ,  ou   e
desse ponto em que somos capazes de declarar objetos (variáveis) desse novo tipo de composto, tal como
temos feito com .; , , e  ; .

Logo no final da 
 declaração, e antes do ponto e vírgula final, podemos usar o campo
opcional ,O 4 diretamente declarar objetos do tipo de estrutura. Por exemplo, podemos também
declarar a estrutura de objetos  .; , , e  ; no momento em que definir o tipo de estrutura de
dados desta forma:

à 
 
 !
  '
 " .') .;6 ,6  ;'


É importante diferenciar claramente entre o que é o nome do tipo de estrutura, eo que é um objeto (variável)
que tem esse tipo de estrutura. Podemos instanciar muitos objetos (variáveis, ou seja,
como .; , , e  ; ) de um tipo de estrutura simples ( 
 ).
Uma vez que tenhamos declarado nossos três objetos de um tipo de estrutura determinada
( .; , , e  ; ), podemos atuar diretamente com os seus membros. Para isso, usamos um ponto
(  ) inserido entre o nome do objeto eo nome do membro. Por exemplo, poderíamos operar com qualquer um
desses elementos como se fossem variáveis padrão de seus respectivos tipos:

à   l          l  ,l  , 








Cada um deles tem o tipo de dados correspondente ao membro que se


referirem:   l  , ,l  e  l  são do tipo  ,
enquanto     , ,  e    são do tipo " .

Vamos ver um exemplo real, onde você pode ver como um tipo de estrutura pode ser usado da mesma forma
como tipos fundamentais:

à   3=   ,  


     

  
  
  
  

    '

 
 ' N 4  FHI  ! 
  ') 
6 
'
D
* N  N 4 "  '  " 
à(
    ! 5  '     M #((à G $ S   3 .# '   5  M à*D' 
  #D  
àà
    6 5
  ' 
  #D    @# '      6 5 ' 5     5

à #
"  "N  S@ A # '' 
   "    #3  
S@ A # '  "  
'
à   (')
à
à N   "  N 4 "  ! ,
 N   ' 
  ## N 5   # A # ')
à
à
àD
à*
(







D
*
(







D

× exemplo mostra como podemos usar os membros de um objeto como variáveis regular. Por exemplo, o
membro 5
5  é uma variável válida do tipo  , e     é uma variável válida do tipo   .

×s objetos    e 
também podem ser tratados como variáveis do tipo válido N 4 , por exemplo,
nós passamos a eles a função  "  como teria feito com variáveis regular. Portanto, uma das
vantagens mais importantes das estruturas de dados é que podemos fazer referência aos seus membros
individualmente ou para toda a estrutura como um bloco com apenas um identificador.

Estruturas de dados são um recurso que pode ser usado para representar bancos de dados, especialmente se
considerarmos a possibilidade de construção de matrizes de um deles:

à    C  

 D  
     
  J
  
   à***
 
  


    '

   "  P4$LR3/ 

D 
 ' N 4  FHI  ! 
*  ') "   7P4$LR3/9'
à(
àà N   "  "  N 4 '
à     5 ! 6
à  '
à
à    M (6  P4$LR3/'    !
  #D    J
@# '    79 J
 ' 
  6
à  "   #3 @ # '  6 5 '    5  7"   9    ') 
  #A
à LI  
   "  @ A # 6
àD    M (' P4$LR3/ '     "  "   79 '
  (')
à*
( N  N 4 "   "  !
 N   ' 
  ## N 5   # A # ')







D
*
(







D
*
(

 


V
Como qualquer outro tipo, as estruturas podem ser apontados pelo seu próprio tipo de ponteiros:V

à 
 ' N 4  FHI  ! 
  ')' EN N 4' N 1 N 4'





Aqui EN é um objeto do tipo de estrutura N 4 e N é um ponteiro para apontar para objetos do
tipo estrutura N 4 . Então, o seguinte código também seria válido:

N M €N '

× valor do ponteiro N seria atribuído a uma referência ao objeto EN (seu endereço de memória).

Agora vamos ir com outro exemplo que inclui ponteiros, que servem para introduzir um novo operador: o
operador seta ( M ):

à   :    


     

  
  
  
  

    '

 
 ' N 4  FHI  ! 
  ')'
D
*     !5  ' EN N 4' N 1 N 4' N M €N ' 
  #D    J

à(     6M   N ' 
  #D    @# '     6 5 '    5  N

  #A P;   
@ A # ' 
 #   N ' 
  ##  N M   # A # '
àà
à   (')
à
à
à
à
à
àD
à*
(







D
*
(

× código anterior inclui uma introdução importante: o operador seta ( M ). Este é um operador dereference
que é usado exclusivamente com ponteiros para objetos com os membros. Este operador serve para acessar
um membro de um objeto para o qual temos uma referência. No exemplo que usamos:

J
 N M

Qual é para todos os efeitos equivalente a:

1 :N  +J


Ambas as expressões M   N e 1 N  J


 são válidos e ambos significam que estamos
avaliando o membro do J
 da estrutura de dados


  um ponteiro chamado N . Deve ser
claramente diferenciado:

1 :N  

que é equivalente a:

1 :N  

E isso poderia acessar o valor apontado pelo ponteiro membro de um hipotético chamado J
 do objeto
estrutura N (que neste caso não seria um ponteiro). × quadro a seguir resume as combinações possíveis
de ponteiros e os membros da estrutura:

M '  × 


  M 
 

ab B Membro do objeto a

a-> b B Membro do objeto apontado por um (* A). B

* Ab Valor apontado por b membro de um objeto * (Ab)

!
' 
V

Estruturas também podem ser aninhados de modo que um elemento válido de uma estrutura também pode
ser, por sua vez uma outra estrutura.V

à 
 ' N 4  FHI  ! 
  ')'

 
 ) " 4   !   ' M  N 4' "N  4N '   6  '
"  1 " 4 M €  '



D
*
à(
àà
à

Após a declaração anterior, podemos usar qualquer uma das seguintes expressões:

à     "N  4N   "N  4N 5  " M


   "N  4N 5 



(×nde, aliás, as duas últimas expressões se referem a um mesmo membro).

×  


 
x!    
  !
C + + permite a definição de nosso próprios tipos baseados em outros tipos de dados existentes. Podemos
fazer isso usando a palavra-chave 5  " , cujo formato é:
5  "  4 =   N4 4 4 '

onde =  45 é um C + + fundamentais ou compostos tipo e  l45 4 é o nome para o novo tipo
que estamos definindo. Por exemplo:V

à 5  "  '


 5  "
    X$®D'
 5  "  1 : '
 5  "    7(9'

Neste caso, temos a definição de quatro tipos de dados:  , X$®D , : e   como  ,
  
 ,  e  7(9 , respectivamente, que poderíamos perfeitamente usar em declarações posteriores
válida como qualquer outro tipo:

à  5 6   6 1 à' 5l  X$®D'    ' 3  :+ : '




5  " não cria tipos diferentes. Ela só cria sinónimos de tipos existentes. Isso significa que o tipo
de 5l  pode ser considerado tanto X$®D ou
    , já que ambos são, de facto, do mesmo tipo.

5  " pode ser útil para definir um apelido para um tipo que é usado freqüentemente dentro de um
programa. Também é útil para definir os tipos, quando é possível que teremos de alterar o tipo em versões
posteriores do nosso programa, ou se um tipo que você quiser usar tem um nome que é muito longo ou
confuso.

& 
 V
Uniões permitem uma mesma porção de memória a ser acessada como diferentes tipos de dados, uma vez que
todos eles são de fato o mesmo local na memória. Sua declaração e utilização é semelhante ao de estruturas,
mas sua funcionalidade é totalmente diferente:V

 4
  ! , 45 à  , 4 à'  , 45   , 4 '  , 45 
 , 4 '  $,O 4 )'

Todos os elementos da
 ; declaração ocupar o mesmo espaço físico na memória. Seu tamanho é o de o
maior elemento da declaração. Por exemplo:

à G ; 55 4 !
  '
  '
" "') 55 '



define três elementos:

à 55  55  55 "





cada um com um tipo de dados diferentes. Uma vez que todos eles estão se referindo ao mesmo local na
memória, a modificação de um dos elementos afetará o valor de todos eles. Não podemos armazenar valores
diferentes nas mesmas independentes umas das outras.
Um dos usos de uma união pode ter é a de unir um tipo elementar com um conjunto de elementos ou
estruturas de menor dimensão. Por exemplo:

à G ;  =4 !
  '
 
 !
    '

 ') '
   79')  
'


D

define três nomes que nos permitem acessar o mesmo grupo de 4 bytes:  = ,  = e  = e que
podemos usar de acordo com a forma como queremos acessar esses bytes, como se fossem um único  -
tipo dados, como se fossem duas 
 elementos ou como uma matriz de  elementos,
respectivamente. Tenho tipos mistos, matrizes e estruturas na união de modo que você pode ver as diferentes
formas que podemos acessar os dados. Para um  

  sistema (PC maioria das plataformas), esta união
pode ser representada como:

× alinhamento exato ea ordem dos membros de um sindicato na memória depende da plataforma. Portanto,
esteja ciente das questões de portabilidade possível com este tipo de uso.

 (   
  V
Em C + +, temos a opção de declarar os sindicatos anônimo. Se declarar uma união sem qualquer nome, o
sindicato será anônimo e seremos capazes de acessar seus membros diretamente por seus nomes de
membros. Por exemplo, olhar para a diferença entre essas duas declarações estrutura:V


   
 
  
  ' 
F 



 ! J
 7(9' 
  7(9'
 ; 
 ! J
 7(9' 
  7(9'
!" ] 6   ') .')  N '
 ; !" ] 6   ')')  N '

A única diferença entre os dois pedaços de código é que no primeiro temos dado um nome para o sindicato
(  . ) e na segunda não temos. A diferença é visto quando o acesso a membros 
]  e   de um objeto desse tipo. Para que um objeto do primeiro tipo, seria:

à ,[    ,[  5 




Considerando que para um objeto do segundo tipo, seria:

à ,[  ,[5 


Mais uma vez devo lembrar que, porque é uma união e não uma estrutura, os membros 
]  e   ocupar o mesmo espaço físico na memória de modo que não pode ser usado para armazenar
dois valores diferentes em simultâneo. Você pode definir um valor para o . em dólares ou ienes, mas não
em ambos.
M 
 V
Enumerações de criar novos tipos de dados para conter algo diferente que não está limitada aos valores
fundamentais tipos de dados podem tomar. Sua forma é o seguinte:V


  4 
 !N à6 N 6 N   $,O 4 )'

Por exemplo, poderíamos criar um novo tipo de variável chamada  4 para armazenar as cores com a
seguinte declaração:


 ! 4 6 C
6 N  6 
F
6 N  6 =6  6 , )'

×bserve que não incluem qualquer tipo de dados fundamental na declaração. Para dizê-lo de alguma forma,
criamos um todo novo tipo de dados a partir do zero, sem baseá-lo em qualquer outro tipo existente. ×s
possíveis valores que as variáveis deste novo tipo  4 pode tomar é a constante de novos valores incluídos
dentro de chaves. Por exemplo, uma vez que o  4enumeração é declarado as seguintes expressões
serão válidos:

à 5  4' 5 M C


'
  MM 5 N  5 M N  '



Enumerações são tipos compatíveis com as variáveis numéricas, para que seus constantes são sempre
atribuído um valor numérico inteiro internamente. Se não for especificado, o equivalente ao valor inteiro
possível, o primeiro valor é equivalente a ( e as seguintes seguem uma progressão 1. Assim, em nosso tipo de
dados  4 que temos acima definidos,  seria equivalente a (, C
 seria equivalente
a
 , N  a  , e assim por diante.

Podemos especificar explicitamente um valor inteiro para qualquer um dos valores constantes que o nosso tipo
enumerado pode assumir. Se o valor constante que se segue não é dado um valor inteiro, ele é
automaticamente assumido o mesmo valor do anterior mais um. Por exemplo:

à 
 4 !O  M à6 " N 6  .6 , 6  6 O
6 O
6 6   , 6
 

, 6 N , 6  C , 6 5[)'


Neste caso, a variável 5[ do tipo enumerado 4 pode conter qualquer um dos 12 possíveis valores que
vão de O  a  C ,  , e que são equivalentes aos valores entre à e à (não entre ( e àà , já
fizemos O  igual a à ) .

Ã
c
Uma 
é um conceito expandido de uma estrutura de dados: em vez de realizar apenas os dados, ele pode
armazenar os dados e funções.

Um '
 é uma instanciação de uma classe. Em termos de variáveis, uma classe seria o tipo, e um objeto
seria a variável.

As aulas são geralmente declaradas usando a palavra-chave  , com o seguinte formato:V

4  ! 4  " 4à@  , à'  4  " 4@  , ' 
$,O 4 )'

×nde 4 é um identificador válido para a classe, ,O 4  é uma lista de nomes para os objetos
desta classe. × corpo da declaração pode conter membros, que podem ser dados ou declarações de função e,
opcionalmente, especificadores de acesso.
Tudo é muito parecido com a declaração sobre as estruturas de dados, exceto que agora podemos incluir
também as funções e os membros, mas também essa coisa nova chamada
m
Ñ  

 . Um
especificador de acesso é uma das três seguintes palavras-chave: N , K,  ou    . Estes
especificadores de modificar os direitos de acesso que os seguintes membros para que adquiram:

>V N membros de uma classe são acessíveis somente através de outros membros da mesma classe
ou de seus  . V
>V    membros são acessíveis a partir de membros da sua mesma classe e de seus amigos, mas
também de membros de suas classes derivadas.
>V Finalmente, K,  integrantes são acessíveis de qualquer lugar onde o objeto é visível.

Por padrão, todos os membros de uma classe declarada com a  de palavras-chave têm acesso privado
para todos os seus membros. Portanto, qualquer membro que seja declarada antes de um especificador de
classe de outros automaticamente tem acesso privado. Por exemplo:V

à  ®  !
  =6 5'
 K,  @
 N   4N
   6  '
 %   N  ') '



Declara uma classe (ou seja, um tipo) chamado ®  e um objeto (ou seja, uma variável) desta classe
chamado  . Essa classe contém quatro membros: dois membros de dados do tipo  (membro = e
membro 5 ), com acesso privado (pois privadas é o nível de acesso padrão) e duas funções de membro de
acesso público:  4N
  e    , das quais para a agora só foram incluídos a sua declaração, e não
sua definição.

×bserve a diferença entre o nome da classe eo nome do objeto: No exemplo anterior, ®  era o nome
da classe (ou seja, o tipo), enquanto rect era um objeto do tipo ®  . É a mesma relação  e
 tem
a seguinte declaração:

 '

onde  é o nome do tipo (a classe) e


 é o nome da variável (o objeto).

Após as declarações anteriores do ®  e  , podemos nos referir dentro do corpo do programa a
qualquer um dos membros públicos do objeto  como se fossem funções normais ou variáveis normal,
apenas colocando objeto o nome seguido por um ponto (  ) e depois o nome do membro. Tudo muito
semelhante ao que fizemos com estruturas de dados comum antes. Por exemplo:

à  4N
 6 ' 5    M  '


×s únicos membros do rect que não podemos acessar a partir do corpo do nosso programa fora da classe
são = e 5 , uma vez que têm acesso privado e só podem ser encaminhados a partir de outros membros da
mesma classe.

Aqui está o exemplo completo da classe CRectangle:

à   3=     % 
  
   

    '

  ®  !
  =6 5'
K,  @

N   4N
   6  '
D     !   = 1 5 '))'
*
à( N  ®  @  4N
   6  , != M 6 5 M ,')
àà
à     !®  '  4N
 6 ' 
  #a @#     '
à   (')
à
à
à
à
àD
à*
(



A coisa mais nova e importante neste código é o operador de escopo ( @@ , dois-pontos), incluído na definição
de  4N
  . Ele é usado para definir um membro de uma classe a partir de fora da definição da própria
classe.

Você pode notar que a definição da função de membro    foi incluída diretamente na definição
do ®  classe dada a sua extrema simplicidade, ao passo que  4N
  tem apenas o seu
protótipo declarado dentro da classe, mas sua definição é fora dela. Nesta declaração fora, devemos usar o
operador de escopo ( @@ ) para especificar que estamos definindo uma função que é membro da
classe ®  e não uma função global regular.

× operador de escopo ( @@ ) especifica a classe a que o membro que está sendo declarado pertence, garantindo
exatamente as mesmas propriedades de escopo como se essa definição de função foi directamente incluído na
definição de classe. Por exemplo, na função de  4N
  do código anterior, temos sido capazes de
utilizar as variáveis = e 5 , que são membros privados da classe ®  , o que significa que eles só são
acessíveis por outros membros da sua classe.

A única diferença entre a definição de um membro da classe funcionar completamente dentro de sua classe ou
para incluir somente o protótipo e, posteriormente, a sua definição, é que no primeiro caso, a função será
automaticamente considerado uma função inline, o compilador, enquanto no segundo ele irá ser um normal
(não-inline) função de membro de classe, que na verdade supõe nenhuma diferença no comportamento.

×s membros = e 5 tem acesso privado (lembre-se que, se nada for dito, todos os membros de uma classe
definida com a classe de palavras-chave têm acesso privado). Ao declarar-los privados negamos acesso a eles
de qualquer lugar fora da classe. Isso faz sentido, uma vez que já definimos uma função membro para definir
valores para os membros dentro do objeto: a função de membro  4N
  . Portanto, o resto do
programa não precisa de ter acesso direto a eles. Talvez em um exemplo simples assim, como isto, é difícil ver
qualquer utilidade na proteção dessas duas variáveis, mas em projetos maiores, pode ser muito importante que
os valores não podem ser modificadas de forma inesperada (inesperada do ponto de vista do objeto ).

Uma das maiores vantagens de uma classe é que, como qualquer outro tipo, podemos declarar vários objetos
do mesmo. Por exemplo, seguindo com o exemplo anterior da classe ®  , poderíamos ter declarado o
objeto , além do objeto  :

à   3=  @
  6   ,O  % 
  
   

    '

 ®  !
  =6 5'
 K,  @
 N   4N
   6  '
D     !   = 1 5 ')) '
*
à( N  ®  @  4N
   6  , != M 6 5 M ,')
àà
    !  ®  6 ,'  4N
 6 ' , 4N
 6 ' 
  #% 
à @#      ' 
  #%  ,@#  ,    '
à   (')
à
à
à
à
àD
à*
(





Neste caso concreto, a classe (tipo de objetos) para o qual estamos falando é ®  , do qual existem
duas instâncias ou objetos:  e , . Cada um deles tem suas próprias variáveis de membro e funções
membro.

×bserve que a chamada para    não dá o mesmo resultado que a chamada para , 
 . Isso ocorre porque cada objeto da classe CRectangle tem suas próprias variáveis = e 5 , uma vez que, de
alguma forma, também têm suas próprias funções membros  4N
 e %   que cada um usa seu
próprio variáveis de seu objeto de operar.

Esse é o conceito básico de m   


  '
 : ×s dados e as funções são ambos membros do
objeto. Nós já não usam conjuntos de variáveis globais que passamos de uma função para outra, como
parâmetros, mas sim como lidamos com objetos que possuem os seus próprios dados e funções incorporados
como membros. Repare que nós não tivemos a dar os parâmetros em qualquer uma das chamadas
para   ou ,  . Essas funções de membro usado diretamente os membros de dados de seus
respectivos objetos  e , .

à   V


×bjetos geralmente precisam para inicializar variáveis ou atribuir memória dinâmica durante o seu processo de
criação para se tornar operativa e para evitar o retorno de valores inesperados durante a sua execução. Por
exemplo, o que aconteceria se no exemplo anterior, chamamos a função de membro    antes de ter
função chamada  4N
  ? Provavelmente, teríamos obtido um resultado indeterminado desde que os
membros = e 5 nunca teria sido atribuído um valor.

A fim de evitar que, uma classe pode incluir uma função especial chamado 
 , que é chamado
automaticamente sempre que um novo objeto desta classe é criado. Esta função construtor deve ter o mesmo
nome da classe, e não pode ter qualquer tipo de retorno, nem mesmo N  .

Vamos implementar ®  incluindo um construtor:V

à   3=  @ 
   % 
  
   

    '

 ®  !
   
6 
'
 K,  @ ®    6  '
     !   
 1  
 '))' ®  @ ®    6  , !l  M '
D   M ,')
*
à(     !  ®  6 ' ®  , 6 ' 
  #%  @#      
 ' 
  #%  ,@#  ,    '
àà
  (')
à
à
à
à
à
à
àD
à*
(




Como você pode ver, o resultado deste exemplo é idêntico ao anterior. Mas agora temos removido a função de
membro  4N
  , e incluíram em vez de um construtor que executa uma ação semelhante: ele
inicializa os valores de  
 e 
 com os parâmetros que são passados para ele.

×bserve como esses argumentos são passados para o construtor no momento em que os objetos dessa classe
são criadas:

à ®   6 ' , ®  6 '




Construtores não podem ser chamados explicitamente como se fossem funções de membro regular. Eles só são
executados quando um novo objeto da classe é criada.

Você também pode ver como nem a declaração do protótipo do construtor (dentro da classe), nem a definição
do construtor últimos incluem um valor de retorno, nem mesmo N  .

×
  cumpre a função oposta. É chamado automaticamente quando um objeto é destruído, ou porque o
seu âmbito de existência, tem acabado (por exemplo, se ele foi definido como um objeto local dentro de uma
função ea função termina), ou porque é um objeto dinamicamente atribuído a ele e é liberado usando o
operador delete.

× destruidor deve ter o mesmo nome da classe, mas precedido de um sinal de til ( Z ) e ele também deve
retornar nenhum valor.

× uso de destrutores é especialmente adequada quando um objeto atribui memória dinâmica durante sua vida
útil e no momento de serem destruídos queremos liberar a memória que o objeto foi alocado.

à   3=    
   
  % 
  
   

    '

 ®  !
  1  
6 
 1'
 K,  @ ®    6  ' Z ®   '
     !   1  
 1 1 
 '))' ®  @ ®    6  , !l 
D M N  '   M N  '  
 1 M ' 1   M ,') ®  @@ Z ®   !
*     
 '
à( =

')
àà
    !  ®  6 6 , 6 ' 
  #%  @#      ' 

à  %  , # @ #  ,    '
à   (')
à
à
à
à
àD
à*
(







D
*
(

& 

à V
Como qualquer outra função, um construtor também pode ser sobrecarregado com mais de uma função que
tem o mesmo nome mas diferentes tipos ou número de parâmetros. Lembre-se que a sobrecarga de funções
que o compilador irá chamar a cujos parâmetros coincidir com os argumentos usados na chamada de
função. No caso dos construtores, que são automaticamente chamados quando um objeto é criado, o
executado é o único que combina os argumentos passados sobre a declaração do objeto:V

à   
    ,   % 
  
   

    '

 ®  !
   
6 
'
 K,  @ ®   ' ®    6  '
  %   N  !   
 1  
 ')) ' ®  @ ®   !l  M '
D   M ') ®  @ ®    6  , !l  M '   M ,')
*
à(     !  ®  6 ' ®  ,' 
  #%  @#      '

  #%  ,@#  ,    '
àà
  (')
à
à
à
à
à
à
àD
à*
(







D
*

Neste caso, , foi declarada sem argumentos, para que ele tenha sido inicializado com o construtor que não
tem parâmetros, que inicializa tanto  
 e 
 , com um valor de 5.

c 
) ×bserve como se declarar um novo objeto e nós queremos usar o construtor padrão (um sem
parâmetros), não incluir parênteses  :

à , ®  '   


 , ®   '   &
  x!
V
Se você não declarar nenhum construtor em uma definição de classe, o compilador assume que a classe tem
um construtor padrão sem argumentos. Portanto, depois de declarar uma classe como esta:V

à  3=  !
 K,  @
  6  ,6 '
 N  
     6   ! M '  M ,6  M  1 ,'))'


× compilador assume que 3=  tem um construtor padrão, então você pode declarar os objetos desta
classe, basta declará-los sem argumentos:

3=  ='

Mas tão logo você declarar seu próprio construtor para uma classe, o compilador não fornece um construtor
padrão implícito. Então você tem que declarar todos os objetos dessa classe de acordo com o construtor de
protótipos que você definiu para a classe:

à  3=  !
 K,  @
  6  ,6 ' 3=    6   ! M '  M ,')'
 N  
    ! M  1 ,')')'



Aqui temos declarado um construtor que recebe dois parâmetros do tipo int. Portanto, a declaração do objeto a
seguir seria correta:

3=  = 6 '

Mas,
3=  ='

Poderia ' ser correcta, uma vez que temos declarado que a classe tem um construtor explícito, substituindo
assim o construtor padrão.

Mas o compilador não só cria um construtor padrão para você se você não especificar o seu próprio. Ele fornece
três funções membro especiais no total, que são declarados implicitamente, se você não declarar o seu
próprio. Estes são o    
%m , o m
  
 
%m , eo destrutor padrão.

× construtor de cópia ea cópia cópia operador de atribuição de todos os dados contidos em outro objeto para os
membros de dados do objeto atual. Para 3=  , o construtor de cópia declarada implicitamente pelo
compilador seria algo semelhante a:

à 3=  @ 3=    3=  € ®L ! M N' N, , M  M N')





Portanto, as duas declarações de objeto a seguir seria correta:


à 3=  = 6' 3=  =  = '  
  ]      =


 


 V
Isso é perfeitamente válido para criar indicadores que apontam para as aulas. Nós simplesmente temos que
considerar que, uma vez declarada, a classe se torna um tipo válido, por isso podemos usar o nome da classe
como o tipo de ponteiro. Por exemplo:V

®   1'

é um ponteiro para um objeto da classe ®  .

Como aconteceu com estruturas de dados, a fim de se referir diretamente a um membro de um objeto
apontado por um ponteiro, podemos usar o operador seta ( M ) de engano. Aqui está um exemplo com
algumas combinações possíveis:

à   :      =  
  
   

    '

 ®  !
   
6 
'
 K,  @
 N   4N
   6  '
D  %   N  !   
 1  
 '))'
*
à( N  ®  @  4N
   6  , !l  M '   M ,')
àà
 1  !®  6 , 16   ' ®  1  M N ®  796 , M N ®  ' M €
à 6 'M  4N
  6 '  7à9'  4N
 6D 
  #
 % @ #     ' 
  #1
à #%    1#  %    ' 
  # 7(9 % @#  7(9  %      ,
6 # 7à9 % 
à    9 7'
à =
,'
à   (')
à
àD
à*
(







D
*
(





Em seguida você tem um resumo sobre como você pode ler alguns ponteiro e operadores de classe
( 1 , € ,  , M , 79 ) que aparecem no exemplo anterior:

 '     
*X apontado por x

&X Endereço de x

xy membro y do objeto x

x, y> y membro do objeto apontado por x

(* X). Y y membro do objeto apontado por x (equivalente ao anterior)

x [0] primeiro objeto apontado por x

x [1] segundo objeto apontado por x

[N] x (N +1) th objeto apontado por x

Tenha certeza que você entender a lógica em todas essas expressões antes de prosseguir com as próximas
seções. Se você tiver dúvidas, leia novamente esta seção e / ou consultar as seções anteriores sobre ponteiros
e estruturas de dados.

Ã
! 
 
 ' V
As classes podem ser definidas não só com palavra-chave  , mas também com palavras-
chave 
 e
 ; .

×s conceitos de classe e de estrutura de dados são tão semelhantes que tanto palavras-chave
( 
 e  ) pode ser usado em C + + para declarar classes (ou seja, 
 s também pode ter
membros de função em C + +, não apenas os membros de dados). A única diferença entre ambos é que os
membros das classes declaradas com a palavra-chave 
 têm acesso público, por padrão, enquanto os
membros das classes declaradas com a palavra-chave  tem acesso privado. Para todos os fins palavras-
chave são equivalentes.

× conceito de união é diferente da de classes declaradas com 


 e  , já que os sindicatos só
armazenam um membro de dados em um momento, mas, no entanto, eles também são classes e assim
também pode se prender membros de função. × acesso padrão em classes de união é pública.

Ã
cc
& 

 
 
C + + incorpora a opção de utilizar os operadores padrão para realizar operações com classes para além dos
tipos fundamentais. Por exemplo:V

à  6 ,6 6  M ,  '


Isto é obviamente um código válido em C + +, uma vez que as diferentes variáveis da adição são todos os
tipos fundamentais. No entanto, não é tão óbvio que poderíamos realizar uma operação semelhante à seguinte:

à 
 
 ! '
 " .') 6 ,6 6  M ,  '




Na verdade, isso irá causar um erro de compilação, já que não temos definido o comportamento de nossa
classe deve ter com as operações de adição. No entanto, graças ao C + + recurso para sobrecarregar
operadores, nós podemos projetar classes capaz de executar operações usando os operadores padrão. Aqui
está uma lista de todos os operadores que podem ser sobrecarregados:

   

 

 M 1  M   M MM 1M  M  M M MM M M M   M&È € T& Z € M T M M € € MÈ 79


 6 M 1 M PN    9 7N    79

Para sobrecarregar um operador, a fim de usá-lo com aulas declaramos Ñ(



m
  , que são funções
regulares cujos nomes são os    -chave, seguida do sinal do operador que queremos sobrecarga. ×
formato é:

R NM        \   !) 11

Aqui você tem um exemplo que sobrecarrega o operador de adição (  ). Vamos criar uma classe para
armazenar vetores bidimensionais e, em seguida, vamos acrescentar duas delas:
 6à e , à6 . A
adição de dois vetores bidimensionais é uma operação simples como adicionar os dois = coordenadas para
obter o resultado = coordenar e adicionando os dois 5 coordenadas para obter o resultado 5 . Neste caso, o
resultado será  à6à  M 6 .

à   L  @  ,       =  
  
   

    '

 L  !
 K,  @
  6 5 =' L   !)' L    6  ' L     L  ')' L  @ @ L  
  =  L    !L    5  5 M   ' 5
D     ')
*
à(     !L 
 6à ' L  , à6 ' L  6  M   ,' 
 =  #6#  5'
  (')
àà
à
à
à
à
à
à
àD
à*
(







D
*
(



Pode ser um pouco confuso de ver muitas vezes de modo que o L  identificador. Mas, considere que
alguns deles se referem ao nome da classe (tipo) L  e alguns outros são funções com esse nome
(construtores devem ter o mesmo nome da classe). Não confundi-los:

à L    6  '     "


.; L  

 L     L  '  "
.;     L 

A função de    de classe L  é aquele que está encarregado de sobrecarregar o operador de
adição (  ). Esta função pode ser chamado de forma implícita usando o operador, ou explicitamente usando o
nome da função:

à  M   ,6  M     , '


As duas expressões são equivalentes.

×bserve também que nós incluímos o construtor vazio (sem parâmetros) e temos definido com um bloco vazio:

L   !)'

Isso é necessário, pois temos outro construtor declarado explicitamente:

L    6  '

E quando explicitamente declarar todos os construtores, com qualquer número de parâmetros, o construtor
padrão sem parâmetros que o compilador pode declarar automaticamente não seja declarado, por isso
precisamos declará-la nós mesmos, a fim de ser capaz de construir objetos desse tipo sem parâmetros . Caso
contrário, a declaração:

L  '

incluído no    não teria sido válido.

Enfim, tenho de avisá-lo que um bloco vazio é uma má aplicação de um construtor, uma vez que não cumpriu a
funcionalidade mínima que geralmente é esperado de um construtor, que é a inicialização de todas as variáveis
de membro de sua classe. No nosso caso o construtor deixa as variáveis = e 5 indefinido. Portanto, uma
definição mais aconselhável seria algo semelhante a isto:

L   != M (6 5 M (')'

que, para simplificar e mostrar apenas o ponto do código eu não ter incluído no exemplo.

Bem como uma classe inclui um construtor padrão e um construtor de cópia, mesmo que não são declarados,
mas também inclui uma definição padrão para o operador de atribuição ( M ) com a própria classe como
parâmetro. × comportamento que é definido por padrão é copiar todo o conteúdo dos membros de dados do
objeto passado como argumento (o do lado direito do sinal) para o outro no lado esquerdo:

à L   6 ' L  3 M '       ,


.;  ] 



A cópia função operador de atribuição é a função de membro único operador implementada por padrão. Claro,
você pode redefini-lo para qualquer outra funcionalidade que você deseja, como por exemplo, copiar apenas os
membros certa classe ou executar procedimentos de inicialização adicionais.

A sobrecarga de operadores não força o seu funcionamento para suportar uma relação com o habitual ou
significado matemático do operador, embora seja recomendado. Por exemplo, o código pode não ser muito
intuitivo, se você usar o    para subtrair duas classes ou  MM para preencher com zeros uma
classe, embora seja perfeitamente possível fazê-lo.

Embora o protótipo de uma função de    pode parecer óbvio, uma vez que leva o que está no lado
direito do operador como o parâmetro para a função de membro do operador do objeto em seu lado esquerdo,
a outros operadores pode não ser tão óbvio. Aqui você tem uma tabela com um resumo sobre como funciona o
operador diferentes têm de ser declaradas (substitua @ pelo operador, em cada caso):

M '  × 
  ! '   ! '  


@A + - * &! ~ + + - A:: operador @ () operador @ (A)

um @ ++- A:: operador @ (int) operador @ (A, int)

um @ b + - ^ / *% & | <==> = <=> = <<>> & & | |, A:: operador @ (B) operador @ (A, B)

um @ b = + = -= *= / =% = & = ^ = | = <<=> = [] A:: operador @ (B) -

a (b c. ..) () Um operador:: () (B, C. ..) -

a-> x -> Um operador::> () -

Sempre que
 é um objeto da classe E , , é um objeto da classe ? e  é um objeto da classe  .

Você pode ver neste painel que existem duas maneiras de sobrecarregar alguns operadores de classe: como
uma função de membro e como uma função global. Seu uso é indistinta, no entanto, devo lembrar que as
funções que não são membros de uma classe não pode acessar os membros private ou protected da classe a
menos que a função global é o seu amigo (a amizade é explicado mais adiante).




*

V
A palavra-chave   representa um ponteiro para o objeto cujo membro função está sendo executada. É um
ponteiro para o objeto em si.

Um de seus usos podem ser para verificar se um parâmetro passado para uma função de membro é o próprio
objeto. Por exemplo,V

à   3  6
  
   

    '

 D
5 !
 K,  @
    D
5   ')'

D  D
5@   D
5   !
*     MM     
'
à(     " ' )
àà
    !D
5
' D
5 , 1 €' M
à  M   ,  
  # 6 S
 ,# '
à   (')
à
à
à
à
àD
à*
(



Também é freqüentemente usada em   M funções membro que retornam objetos por referência
(evitando o uso de objetos temporários). Seguindo com os exemplos do vetor visto antes, poderíamos ter
escrito um   M função semelhante a esta:

à L  € L  @   M   L    != M  =' 5 M  5'


 N 1  ')





Na verdade, esta função é muito semelhante ao código que o compilador gera implicitamente para esta classe,
se não incluir um   M função de membro para copiar objetos dessa classe.

×  V
Uma classe pode conter
  membros, dados ou funções.

Membros de dados estáticos de uma classe também são conhecidos como "variáveis de classe", porque só
existe um valor único para todos os objetos da mesma classe. Seu conteúdo não é diferente de um objeto
desta classe para outra.

Por exemplo, pode ser usado para uma variável dentro de uma classe que pode conter um contador com o
número de objetos dessa classe que estão actualmente afectados, como no exemplo a seguir:V

à    ,  %      


  
   

    '

 D
5 !
 K,  @
    ' D
5  !  ')' Z D
5  ! M')')'

D  D
5@  M ('
*
à(     !D
5
' D
5 , 79' D
5  1 M N D
5' 
 
  '
  ' 
 D
5@   '
àà
  (')
à
à
à
à
à
à
àD
à*
(



De fato, membros estáticos têm as mesmas propriedades como variáveis globais, mas eles gostam de escopo
de classe. Por esse motivo, e para evitar que sejam declaradas várias vezes, só podemos incluir o protótipo
(sua declaração) na declaração da classe, mas não a sua definição (sua inicialização). Para inicializar um
membro de dados estáticos, que deve incluir uma definição formal fora da classe, no âmbito global, como no
exemplo anterior:

 D
5@  M ('

Porque é um valor variável única para todos os objetos da mesma classe, pode ser referido como um membro
de qualquer objeto dessa classe ou mesmo diretamente pelo nome da classe (é claro que isso só é válido para
membros estáticos):
à 
 
' 
 D
5@@ '


Essas duas chamadas incluídas no exemplo anterior, se referindo à mesma variável: a variável
estática  dentro da classe D
5 compartilhada por todos os objetos dessa classe.

Mais uma vez, devo lembrar que na verdade é uma variável global. A única diferença é o seu nome e eventuais
restrições de acesso externo à classe.

Assim como podemos incluir dados estáticos em uma classe, podemos incluir também funções estáticas. Eles
representam a mesma coisa: são funções globais que são chamados como se fossem membros do objeto de
uma determinada classe. Eles só podem fazer referência a dados estáticos, em nenhum caso a membros não-
estáticos da classe, bem como não permitir a utilização da palavra-chave   , já que faz referência a um
ponteiro de objeto e, de facto, essas funções não são membros de qualquer objeto, mas membros diretos da
classe.V

3



!  
Em princípio, os membros privados e protegidos de uma classe não pode ser acessado de fora da mesma classe
na qual elas são declaradas. No entanto, esta regra não afeta  .

Amigos são funções ou classes declaradas com o   -chave.

Se queremos declarar uma função externa, como amigo de uma classe, permitindo assim que esta função para
ter acesso aos membros privados e protegidos da classe, nós fazemo-lo, declarando um protótipo desta função
externa dentro da classe, e precedendo-o com a palavra-chave   : V

à E   "
.2  
  
   

    '

 ®  !
   
6 
'
 K,  @
 N   4N
   6  '
D     !   
 1  
 ')
*   ®  
  ®  ')'
à(
N  ®  @  4N
   6  , !l  M '   M ,') ®  
      ® 
àà
   M  
 1 '
à      ')
à
à     !  ®  6 ,'  4N
 6 ' , M 
    ' 
 ,  
à   (')
à
à
àD
à*
(







D
*
(



A 
 .; da função é um amigo de ®  . De dentro dessa função, temos sido capazes de acessar
os membros   
 e 
 de diferentes objetos do tipo ®  , que são membros
privados. ×bserve que nem na declaração de 
   nem em seu uso posterior no    temos
observado 
  um membro da classe ®  . Mas não é! Ele simplesmente tem acesso aos seus
membros privados e protegidos, sem ser membro.

As funções de amigo pode servir, por exemplo, a realização de operações entre duas classes
diferentes. Geralmente, o uso de funções é amigo de uma metodologia de programação orientada a objeto, por
isso sempre que possível, é melhor usar membros da mesma classe para realizar operações com eles. Tal como
no exemplo anterior, teria sido mais curto para integrar 
   dentro da classe ®  .



 V
Assim como temos a possibilidade de definir uma função de amigo, também podemos definir uma classe como
amigo do outro, garantindo que o acesso de primeira classe para os membros protected e private da segunda.V

à      à
  
   

    '

 /F
 '

  ®  !
   
6 
'
D K,  @
*     !   
 1  
 ')
à( N  N  /F
  ')'
àà
 /F
 !
à N @
à  '
à K,  @
à N   4     ! M ')
à     ®  ')'
à
N  ®  @ N  /F
  !l  M   6 
   M')
àD
à*     !
( F /F
 '
à ®  '
 F  4   '
    '
  N  F '

 

   (')

D
*
(







Neste exemplo, declaramos ®  como um amigo de /F


 modo que ®  funções membro
podem ter acesso aos membros protegidos e privados de /F
 , mais concretamente para /F
 @@
 , que descreve a largura do lado do quadrado.

Você também pode ver algo novo no início do programa: uma declaração vazia de classe /F
 . Isso é
necessário porque dentro da declaração de ®  nos referimos CSquare (como um parâmetro
em N   ). A definição de/F
 incluído mais tarde, então se não incluir uma declaração vazia
anterior para /F
 esta classe não seria visível a partir da definição de ®  .

Considere que as amizades não são correspondidos, se não especificar explicitamente assim. No nosso
exemplo, ®  é considerada como uma classe amigo por /F
 , mas ®  não
considera /F
 ser um amigo, então®  pode acessar o e privadas membros protegidos
de /F
 mas não da maneira inversa. É claro que poderíamos ter declarado também /F
 como
amigo ®  se quiséssemos.

×utra propriedade das amizades é que eles são     : × amigo de um amigo não é considerado para
ser um amigo a menos que explicitamente especificado.



 
 V
Uma característica fundamental de classes C + + é a herança. A herança permite criar classes que são
derivadas de outras classes, de modo que automaticamente inclui alguns dos seus "pais" os membros, além de
seus próprios. Por exemplo, vamos supor que queremos declarar uma série de classes de polígonos que
descrevem como a nossa ®  , ou como +  . Eles têm algumas propriedades comuns, como
ambos podem ser descritas por meio de apenas dois lados: altura e base.

Isso poderia ser representado no mundo das classes com uma classe :5 das quais se derivam as duas
outras: ®  e +  .

A classe :5 deve conter elementos que são comuns para ambos os tipos de polígono. No nosso
caso:  
 e 
 . E ®  e +  seriam suas classes derivadas, com características
específicas que são diferentes de um tipo de polígono para o outro.

As classes que são derivadas de outras herdar todos os membros acessível da classe base. Isso significa que se
uma classe base inclui um membro de E e obtemos que a outra classe com outro membro chamado ? , a classe
derivada contém ambos os membros E e ? .

A fim de derivar uma classe da outra, usamos dois pontos ( @ ) na declaração da classe derivada usando o
seguinte formato:

 N 44  @ , 44 K, 


11 !)'

×nde  N 44 é o nome da classe derivada e , 44 é o nome da classe em que se
baseia. × K,  especificador de acesso pode ser substituído por qualquer um dos especificadores de acesso
a outras    e N . Este especificador limita o acesso a níveis mais acessíveis para os membros
herdados da classe base: ×s membros com um nível mais acessíveis são herdadas com este nível em vez disso,
enquanto os membros com mais restritivas de acesso de nível igual ou manter o seu nível restritivas na classe
derivada . V

à      N
  
  

  :5 !
   @
   
6 
'
 K,  @
 N   4N
   6  , !l  M '   M ,')
D )'
*
à(  ®  @
,  :5 !

,  @
àà
    !   
 1  
 ')
à )'
à
à  +  @
,  :5 !
à
,  @
à     !   
 1  
   ')
à )'
àD
    !
à* ®  '
( +   '
à  4N
 6 '
   4N
 6 '
 "     ' "     '

  (' )



D
*
(




×s objetos das classes ®  e +  cada conter membros herdados :5 . Estes
são:  
 , 
 e  4N
  .

×    especificador de acesso é semelhante ao N . Sua única diferença ocorre de fato com a
herança. Quando uma classe herda de outra, os membros da classe derivada pode acessar os membros
protected herdado da classe base, mas não os seus membros particulares.

Desde que queríamos  


 e 
 para ser acessível aos membros das classes
derivadas ®  e +  e não apenas por membros da :5 , temos utilizado    de
acesso em vez de N .

Podemos resumir os tipos de acesso diferentes de acordo com quem pode acessá-los da seguinte forma:

  .   


 



membros da mesma classe sim sim sim

membros de classes derivadas sim sim não

não membros sim não não

×nde "não membros" representa qualquer acesso de fora da classe, como de    , a partir de outra classe
ou de uma função.

No nosso exemplo, os membros herdados por ®  e +  ter as permissões de acesso mesmo
que eles tinham na sua base de classe :5 :

à :5@  
       
 ®  @  
       

:5@  4N
      K, 

®  @  4N
     
, 


Isto é porque nós usamos o K,  palavra-chave para definir a relação de herança em cada uma das classes
derivadas:
 ®  @ K,  :5 ! )

Este K,  palavra-chave após os dois pontos ( @ ) indica o nível mais acessíveis os membros herdados da
classe que se lhe segue (neste caso :5 ) terá. Desde K,  é o nível mais acessível, especificando
essa palavra-chave da classe derivada vai herdar todos os membros com os mesmos níveis que tinham na
classe base.

Se especificar um nível de acesso mais restritivo como    , todos os membros públicos da classe base
são herdadas, que é protegida na classe derivada. Considerando que se especifique mais a restrição de acesso
a todos os níveis: N , todos os membros da classe base são herdadas como privado.

Por exemplo, se  "  era uma classe derivada da ; 6 que definimos como:

 " @    ; '

Tal conjunto    como o nível máximo de acesso para os membros da "  que herdou da ; . ×u
seja, todos os membros que estavam no público  ; ficaria protegida em "  . Claro, isso não
restringiria  "  para declarar seus próprios membros do público. Esse nível de acesso máxima é definida
apenas para os membros herdados da ; .

Se não especificar explicitamente qualquer nível de acesso para a herança, o compilador assume particular para
as classes declaradas com a   palavra-chave e público para as declaradas com 
 .

× 
 


V
Em princípio, uma classe derivada herda todos os membros de uma classe base, exceto:V

>V seu construtor e seu destruidorV


>V seu operador = () membros
>V seus amigos

Embora os construtores e destruidores da classe base não são herdados si, o seu construtor padrão (ou seja, o
construtor sem parâmetros) e seu destruidor é sempre chamado quando um novo objeto de uma classe
derivada é criado ou destruído.

Se a classe base não tem nenhum construtor padrão ou você quer que um construtor sobrecarregado é
chamado quando um novo objeto derivado é criado, você pode especificá-lo em cada definição de construtor da
classe derivada:

 N 4
 4   \   @ , 4
 4   \   !)

Por exemplo: V

à   
     N ;
  
  

 ; !


,  @  ;  ! "#; @    \   A # ') ;    ! " #; @  A 
  \   # ')
 )'

D  " @
,  ; !
*
,  @  "     ! " #" @  \    A  A # ')
à( )'
àà
 " @
,  ; !
à
,  @  "     @ ;  ! " # " @  \    A A  A # ')
à )'
à
à     !"  5  ( '   "  ( '
à
  (')
à
àD
à*
(







D
*
(

×bserve a diferença entre as quais  ; é construtor é chamado quando um novo "  objeto é criado e que
quando é um "  do objeto. A diferença é porque a declaração construtor da "  e "  :

à "          " @  ; 


 "     @ ; 
   
   " @  




. 
V
Em C + + é perfeitamente possível que uma classe herda os membros de mais de uma classe. Isso é feito
simplesmente separar as classes base diferentes com vírgulas na declaração da classe derivada. Por exemplo,
se tivéssemos uma classe específica para impressão em tela ( $

 ) e quisemos que nosso
classes ®  e +  também herdam seus membros, para além das de :5 podemos
escrever:V

à  ®  @
,  :56
,  $

'
  +  @
,  :56
,  $

'

aqui está o exemplo completo:

à   ^ . K 
  
  

  :5 !
   @
   
6 
'

,  @

D N   4N
   6  ,
* !
à l  M '   M ,'
)
(
)'
à
à  $

 !
à
 K,  @
à N  J   '

)'
à
 N  $

@ J   ! "  ')
à
  ®  @
,  :56
,  $

 !
à K,  @
     !    
 
 1 '))'
à
 +  @ K,  :56
,  $

 !

,  @
à     !   
 1  
   '))'
D
à     !
*
®  '

  +  '
(  4N
 6  '
   4N
 6 '
à 

     '
  

     '

   ('
)










D

*

(

à













D

*

(

à



V
 ! 
Antes de chegar a este ponto, é recomendável que você tenha uma compreensão adequada dos ponteiros e
herança de classe. Se qualquer uma das seguintes afirmações parecer estranho para você, você deve rever as
seções indicadas:V

x

' ) M 
 )

int a: b (int c) {} Classes

a-> b Estruturas de Dados

Classe A: b pública {}; Amizade e herança


 



V
Uma das principais características de classes derivadas é que um ponteiro para uma classe derivada é de tipo
compatível com um ponteiro para sua classe base. Polimorfismo é a arte de tirar proveito desse recurso
simples, mas poderosa e versátil, que traz Metodologias ×rientada a ×bjetos para o seu pleno potencial.

Vamos começar por reescrever o nosso programa sobre o retângulo eo triângulo da seção anterior, tendo em
conta esta propriedade compatibilidade ponteiro:V

à   :     ,


  
   

    '

 :5 !
    @
   
6 
'
 K,  @
D N   4N
   6  , !l  M '   M ,'))'
*
à(  ®  @ K,  :5 !
K,  @
àà
    !   
 1  
 '))'
à
à  +  @ K,  :5 !
à K,  @
à     !   
 1  
   '))'
à
à     !®  '   +  ' :5 1 5à M € ' :5 1 5 M € '
M  4N
 5à 6 'M  4N
 5 6 ' 
       '
àD

      '
à*   (')
(







D
*
(






Em função   , criamos dois ponteiros que apontam para objetos de


classe :5 ( 5à e 5 ). Então vamos atribuir referências ao  e   a esses ponteiros, e
porque ambos são objetos de classes derivadas de :5 , ambos são operações de atribuição é válida.

A única limitação no uso 5à 1 e 1 5 vez de  e   é que ambos 5à 1 e 1 5 são do
tipo 1 :5 e, portanto, só podemos utilizar esses ponteiros para se referir aos membros
que ®  e +  herdam :5 . Por essa razão, quando nós chamamos a %   membros,
no final do programa, tivemos de usar diretamente os objetos  e   em vez de os ponteiros 5à
1 e 1 5 .

A fim de utilizar %   com os ponteiros para a classe :5 , esse membro deve também ter sido
declarado na classe :5 , e não apenas em suas classes derivadas, mas o problema é
que ®  e +  implementar diferentes versões de %  , por isso não pode aplicá-lo na classe
base. Isto é, quando se tornam membros virtuais em mãos:
 ’
V
Um membro de uma classe que pode ser redefinida em suas classes derivadas é conhecida como um membro
virtual. Para declarar um membro de uma classe como virtual, que deve preceder sua declaração com a
palavra-chave N 
 : V

à    ,  N 
 
  
   

    '

 :5 !
    @
   
6 
'
 K,  @
D N   4N
   6  , !l  M '   M ,')
* N 
     !   ( '))'
à(
 ®  @ K,  :5 !
àà
K,  @
à     !   
 1  
 '))'
à
à  +  @ K,  :5 !
à K,  @
à     !   
 1  
   '))'
à
    !®  ' +   ' :5  ' :5 1 5à M € ' :5 1 5
àD
6 'M  4N
 5 6 ' 
 6 a  5à   ' 
 6 a  5   ' 

à*   (')
(







D
*
(







D
*
(

Agora as três classes ( :5 , ®  e +  ) têm todos os membros da


mesma:  
 , 
 ,  4N
  e E   .

A função de membro    foi declarada como virtual na classe base, porque é tarde redefinido em cada
classe derivada. Você pode verificar se quiser que se você remover esse N 
 palavra-chave da declaração
de %   dentro :5 , e depois de executar o programa, o resultado será ( para os três polígonos ao
invés de ( , à( e ( . Isso é porque em vez de chamar o correspondente %   função para cada objeto
( ®  @    , +  @@ a   e :5@    , respectivamente), :5@@ a 
 será chamado em todos os casos, uma vez que as chamadas são através de um ponteiro cujo tipo é 1
:5 .

Portanto, o que o N 
 não é palavra-chave para permitir que um membro de uma classe derivada com o
mesmo nome de um na classe base deve ser chamado apropriadamente de um ponteiro e, mais precisamente
quando o tipo do ponteiro é um ponteiro para a classe base mas está apontando para um objeto da classe
derivada, como no exemplo acima.
Uma classe que declara ou herda uma função virtual é chamada de 
m% Ñ .

Note que, apesar da sua virtualidade, também temos sido capazes de declarar um objeto do tipo :5 e
chamar o seu próprio J   função, que sempre retorna 0.






V
classes base abstratas são algo muito semelhante ao nosso :5 classe do nosso exemplo anterior. A
única diferença é que no nosso exemplo anterior, temos definido um válido %   função com um mínimo de
funcionalidade para os objetos que eram de classe :5 (como o objeto  ), enquanto em uma classe
abstrata de base poderíamos deixar essa%   membro funcionar sem a aplicação a todos. Isso é feito
acrescentando M ( (igual a zero) para a declaração da função.

Um resumo da classe base CPolygon poderia ficar assim:V

à    ,  :5


  :5 !
    @
   
6 
'
K,  @
 N   4N
   6  , !l  M '   M ,')
 N 
  %   M (')'

D
*

×bserve como nós anexado M ( para %   N 


  em vez de especificar uma aplicação para a
função. Este tipo de função é chamada de Ñ m  , e todas as classes que contêm pelo menos uma
função virtual pura são 

   .

A principal diferença entre uma classe base abstrata e uma classe regular polimórficos porque é que nas classes
de base abstrata, pelo menos, um dos seus membros não tem aplicação não podemos criar instâncias (objetos)
do mesmo.

Mas uma classe que não pode instanciar objetos não é totalmente inútil. Nós podemos criar ponteiros para isso
e tirar proveito de todas as suas capacidades polimórficas. Portanto uma declaração como:

:5  '

não seria válida para a classe base abstrata que acabamos de declarar, porque tenta instanciar um objeto. No
entanto, as seguintes indicações:

à :5 1 5à' :5 1 5'




seria perfeitamente válido.

Isto é assim por quanto tempo :5 inclui uma função virtual pura e, portanto, é uma classe abstrata de
base. No entanto, os ponteiros para essa classe abstrata de base pode ser usado para apontar para objetos de
classes derivadas.

Aqui você tem o exemplo completo:

à    ,   ,


  
   

    '
  :5 !
    @
   
6 
'
K,  @

N   4N
   6  , !l  M '   M ,')
D N 
  %   N  M (')'
*
à(  ®  @ K,  :5 !
àà K,  @
à  %   N  !   
 1  
 '))'
à
 +  @ K,  :5 !
à
K,  @
à  %   N  !   
 1  
   '))'
à
à     !®  '   +  ' :5 1 5à M € ' :5 1 5 M € 'M  
àD  4N
 6 '  ,
 5  5àM a    ' 
 6 a  5   '
à*   (')
(







D
*
(







Se você revisar o programa que você irá notar que nos referimos a objetos de classes diferentes, mas
relacionados com um tipo único de ponteiro ( :5 1 ). Isto pode ser tremendamente útil. Por exemplo,
agora podemos criar uma função de membro da classe base abstracta :5 que é capaz de imprimir na
tela o resultado da %   função, embora:5 em si não tem aplicação para essa função:

à   :
 ,  N 
     
     , , 
  
   

    '

  :5 !
    @
   
6 
'
D K,  @
* N   4N
   6  , !l  M '   M ,')
à( N 
  %   N  M ('
N  E   N  !
   M a    '))'
àà
à  ®  @ K,  :5 !
à K,  @
à  %   N  !   
 1  
 '))'
à
à  +  @ K,  :5 !
à K,  @
 %   N  !   
 1  
   '))'
àD
à*     !®  '   +  ' :5 1 5à M  :5 1 5 M € 'M  4N

( 6 'M  4N


 5 6 'M E  5à  'M E  5  '
à   (')






D
*
(







D
*

membros Virtual e classes abstratas conceder C + + as características polimórficas que fazem programação
orientada a objetos como um instrumento útil em grandes projetos. Claro, temos visto muito simples usa esses
recursos, mas esses recursos podem ser aplicados a arrays de objetos ou objetos alocados dinamicamente.

Vamos terminar com o mesmo exemplo de novo, mas desta vez com os objetos que são alocados
dinamicamente:

à  E.;  \      " 


  
   

    '

 :5 !
    @
   
6 
'
 K,  @
D N   4N
   6  , !l  M '   M ,')
* N 
  %   N  M ('
à( N  E   N  !
   M a    '))'
àà
 ®  @ K,  :5 !
à K,  @
à  %   N  !   
 1  
 ')) '
à
à  +  @ K,  :5 !
à K,  @
à  %   N  !   
 1  
   '))'
àD
    !:5 5à 1 M N ®  ' :5 5 1 M N +  'M  4N
 5à
à* 6 'M  4N
 5 6 'M E  5à  'M E  5  '
( =
5à'
à =
5'
   (')





D
*
(







D
×bserve que o 5 ponteiros:

à :5 5à 1 M N ®  ' :5 5 1 M N +  '


são declaradas sendo do tipo ponteiro para :5 mas os objetos dinamicamente alocados tenham sido
declarados com o tipo de classe derivada diretamente.

 
 ! ' 
Função modelos são funções especiais que podem operar com m 
)  . Isso nos permite criar um
modelo de função cuja funcionalidade pode ser adaptado para mais de um tipo ou classe, sem repetir o código
inteiro para cada tipo.

Em C + +, este pode ser conseguido usando m &


  
 . Um parâmetro do modelo é um tipo
especial de parâmetro que pode ser usado para passar um tipo como argumento: como regular os parâmetros
de função pode ser usada para passar os valores para uma função, parâmetros do modelo permitem a
passagem também tipos para uma função. Estes modelos de função pode usar esses parâmetros como se
fossem qualquer outro tipo regular.

× formato para declarar a função de modelos com parâmetros de tipo é:

   "


 4      "  '
   5    "  '

A única diferença entre os dois protótipos é o uso de qualquer palavra-chave  ou a palavra-
chave 5  . Seu uso é indiferente, pois ambas as expressões têm exatamente o mesmo significado e se
comportam exatamente da mesma maneira.

Por exemplo, para criar um modelo de função que retorna o maior um dos dois objetos que podemos usar: V

à      5+5  5+5 < = 5+5


 5+5 6 , !
   6 , ,V @ ')



Aqui nós criamos uma função de modelo com 5+5 como parâmetro do modelo. Este parâmetro do modelo
representa um tipo que ainda não foi especificado, mas que pode ser usado na função de modelo como se fosse
um tipo normal. Como você pode ver, o modelo de função < = retorna o maior dos dois parâmetros deste
tipo ainda indefinido.

Para utilizar este modelo de função usamos o seguinte formato para chamar a função:

  "
 4   \   '

Por exemplo, para chamar < = para comparar dois valores inteiros do tipo  , podemos escrever:

à  =6 5' < =    =6 5 '




Quando o compilador encontra esta chamada para uma função de modelo, ele usa o modelo para gerar
automaticamente a função de substituir cada aparição de 5+5 pelo tipo passado como o parâmetro do
modelo atual (  neste caso) e depois chama-lo. Este processo é realizado automaticamente pelo compilador
e é invisível para o programador.

Aqui está o exemplo completo:

à  +    "
.;  à(
  
   

    '

    + + < = + 6 + , ! 
 +' 
 M  , V @ ,'
    
 ')

     !
D  M 6 [ M 6 O'
*   M à(6  M 6 6 [ M < =     6 O '  M < =    6  ' 
 [  '
à( 
   '
  (')
àà
à
à
à
à
à
à
àD
à*
(

Neste caso, usamos + como o nome do parâmetro do modelo, em vez de 5+5 porque é mais curto e de fato
é um modelo de parâmetro de nome muito comum. Mas você pode usar qualquer identificador que quiser.

No exemplo acima foi utilizado o modelo de função < =  duas vezes. A primeira vez com argumentos do
tipo  eo segundo com argumentos do tipo  . × compilador tem instanciado e chamado então cada vez
que a versão apropriada da função.

Como você pode ver, o tipo + é usado dentro do < =  função de modelo mesmo para declarar novos
objetos desse tipo:

+ 
'

Portanto, 
 será um objeto do mesmo tipo como os parâmetros de
 e , quando o modelo é
instanciado com um tipo específico.

Neste caso específico em que o tipo genérico + é usado como parâmetro para < = o compilador pode
descobrir automaticamente que tipo de dados tem para criar uma instância sem explicitamente especificá-lo
nos parênteses em ângulo (como nós fizemos antes de especificar   e   ). Assim, poderíamos ter
escrito em vez disso:

à  6 O' < =  6 O '




Uma vez que tanto e O são do tipo  , o compilador pode automaticamente descobrir que o parâmetro do
modelo só pode ser  . Este método implícito produz exatamente o mesmo resultado:

à   8
.;    RR  à(
  
   

    '

    + + < = + 6 + , !
   6 ,V 6 , ')

     !
D  M  6 [ M 6 O'
  M à(6  M 6 6 [ M < =  6 O 6  M < =   ' 
 [  ' 
   '
*
  (')
à(
àà
à
à
à
à
à
à
àD

Note como neste caso, chamamos o nosso modelo de função < =  sem especificar explicitamente o tipo
de ângulo entre parênteses  . × compilador determina automaticamente o tipo é necessária em cada
chamada.

Porque a nossa função de modelo inclui apenas um parâmetro do modelo (  + ) e do modelo de função
em si aceita dois parâmetros, ambos da + tipo, não podemos chamar de nosso modelo de função com dois
objetos de diferentes tipos de argumentos:

à  '
  6 [ M < = 6  '


Isso não seria correto, desde a nossa < = modelo de função espera dois argumentos do mesmo tipo, e
neste convite a ele que use objetos de dois tipos diferentes.

Nós também podemos definir a função de modelos que aceitam mais de um parâmetro do tipo, simplesmente
especificando mais parâmetros de modelo entre os colchetes. Por exemplo:

à      +6  G +    + 6 G , !


   6 , ,V @ ')



Neste caso, nosso modelo de função     aceita dois parâmetros de tipos diferentes e retorna um objeto
do mesmo tipo do primeiro parâmetro ( + ) que é passado. Por exemplo, depois daquela declaração que
poderíamos chamar     com:

à  6 O'
  6 M      6   6 O '


ou simplesmente:

M    6 O '

embora O e  têm diferentes tipos, uma vez que o compilador pode determinar a instanciação de qualquer
maneira adequada.
 
V
Temos também a possibilidade de escrever modelos de classe, de modo que uma classe pode ter membros que
utilizam parâmetros do modelo como tipos. Por exemplo:V

à      +
  5  !N   + 79'
 K,  @ 5     +6 +  
 !N  7(9 M  ' N  7à9 M
  
'))'



D
*

A classe que acabamos de definir serve para armazenar dois elementos de qualquer tipo válido. Por exemplo,
se quiséssemos declarar um objeto desta classe para guardar dois valores inteiros do tipo  com os valores
de 115 e 36 poderíamos escrever:

5    5,O  àà6  '

esta mesma classe também seria usado para criar um objeto para armazenar qualquer outro tipo:

5   
  5" 6(6 6àD '

A função de membro somente no modelo de classe anterior foi definido em linha com a declaração de classe em
si. No caso de se definir uma função membro fora da declaração do modelo de classe, devemos sempre
preceder a definição com o    prefixo:

à       à((


  
   

    '

    +
  5  !+ 6 ,'
 K,  @ 5     +6 +  
 ! M  6 , M  
') + < =  ')'

D     + + + 5  @ < =  ! N +' N M  ,V @ ,'
*   N')
à(
    !5     5,O  à((6  ' 
 5,O  =  '
àà
  (')
à
à
à
à
à
à
àD
à*
(






×bserve que a sintaxe da definição de GetMax função de membro:

à      + + + 5  @ < = 




Confuso com tantos + s '? Há três + 's nesta declaração: × primeiro é o parâmetro do modelo. × segundo + se
refere ao tipo retornado pela função. E o terceiro + (o ângulo entre parênteses) é também uma exigência:
Especifica que a função do modelo de parâmetro este também é o parâmetro do modelo de classe.

  


3
' V
Se queremos definir uma implementação diferente para um modelo quando um tipo específico é passado como
parâmetro do modelo, podemos declarar uma especialização desse modelo.

Por exemplo, vamos supor que temos uma classe muito simples chamado 5  que pode armazenar
um elemento de qualquer tipo e que tem apenas uma função de membro chamada 
  , o que aumenta
seu valor. Mas nós achamos que quando se armazena um elemento do tipo  que seria mais conveniente
ter uma implementação completamente diferente com um membro da função de     K
 , por isso
decidimos declarar uma especialização de modelo para esse tipo de classe:V

à   3   C.;  
  
   

    '

     
@
     +
  5  !    +'
 K,  @ 5    + M    ! ') + 
   !       '))'
D
*     C.;      @
à(    
 5     !
àà
   '
à K,  @ 5      !  M   ')
à   K
  !
à      M BB € € M    BCB     M BEB M BB '
à     '))'
à
à     !5     5   ' 5   5   BOB ' 
 5     
5 
   '
àD
  (')
à*
(







D
*
(





Esta é a sintaxe usada no modelo de especialização da classe:


     5     ! )'

Antes de mais nada, aviso que precede o nome do modelo de classe com um vazio     lista de
parâmetros. Este é declarar explicitamente como um modelo de especialização.

Mas mais importante que esse prefixo, é o   parâmetro de especialização após o nome do modelo de
classe. Este parâmetro de especialização em si identifica o tipo para o qual vamos declarar uma classe de
modelo de especialização (  ).×bserve as diferenças entre o modelo de classe genérica e especialização:

à      +  5  ! )'


      5     ! )'

A primeira linha é o modelo genérico, ea segunda é a especialização.

Quando declaramos especializações de uma classe de modelo, devemos também definir todos os seus
membros, mesmo aqueles exatamente igual à classe de modelo genérico, porque não há "herança" dos
membros a partir do modelo genérico para a especialização.


%  ' * 

  V
Além dos argumentos de modelo que são precedidas pela  ou 5  palavras-chave, que
representam tipos, modelos também podem ter regular os parâmetros digitados, semelhantes aos encontrados
em funções. Como exemplo, ter um olhar para este modelo de classe que é usado para conter sequências de
elementos:V

à  +    FHI  
  
   

    '

    +6  P
  5 F
 !+  ?[ 7P9'
 K,  @
 N    ,   =6  N + ' + <  ,   = ') '
D
*     +6  P
à( N  +6P 5 F
 @   ,   =6  N + ! ?[ 7=9 M N ')
àà
    +6  P +6P 5 F
 + @@ <  ,   = !
à    ?[ 7=9')
à
à     !5 F
   6  5R' 5 F
  
 6  5"' 5   , (à(( ' 5
à 5"  ,   BA B '
à   (')
à
àD
à*
(







D
*
(

Também é possível definir valores padrão ou tipos de parâmetros do modelo de classe. Por exemplo, se a
definição do modelo anterior de classe foram:

     + M  6  P M à(  !)' 5 F




Podemos criar objetos usando os parâmetros de modelo padrão, declarando:

5 F
  5 F'

Qual seria equivalente a:

5 F
   6 à( 5 F'

   $  


  V
Do ponto de vista do compilador, os modelos não são funções normais ou classes. Eles são compilados em
demanda, significando que o código de uma função de modelo não é compilado até uma instanciação com
argumentos de modelo específico é necessário. Naquele momento, quando uma instância for necessário, o
compilador gera uma função específica para esses argumentos do modelo.

Quando os projetos crescem é usual dividir o código de um programa em diferentes arquivos de código
fonte. Nestes casos, a interface ea implementação são geralmente separados. Tomando uma biblioteca de
funções como exemplo, a interface geralmente consiste de declarações dos protótipos de todas as funções que
podem ser chamados. Estes são geralmente declarados em um arquivo "header" com uma extensão h. Ea
implementação (a definição dessas funções) está em um arquivo independente, com código C + +.

Como os modelos são compilados quando requerido, isso força uma restrição para projetos multi-arquivo: a
execução (definição) de uma classe de modelo ou a função deve estar no mesmo arquivo como sua
declaração. Isso significa que não podemos separar a interface em um arquivo de cabeçalho separado, e que
deve incluir tanto a interface e implementação em qualquer arquivo que usa os modelos.

Já que nenhum código é gerado até que um modelo é instanciado quando necessário, compiladores estão
dispostos a permitir a inclusão de mais de uma vez o arquivo de mesmo modelo com as duas declarações e
definições em um projeto sem gerar erros de ligação.




Namespaces permitem entidades do grupo, como classes, objetos e funções sob um nome. Desta forma, o
escopo global podem ser divididos em "sub-espaços, cada uma com seu próprio nome.

× formato de namespaces é:

     " 


!
  
)

×nde   "  é qualquer identificador válido e    é o conjunto de classes, objetos e funções
que estão incluídos dentro do namespace. Por exemplo:V

à    5P   !
  6 ,')



Neste caso, as variáveis de


 e , são variáveis normais declarada dentro de um namespace
chamado 5P   . Para acessar essas variáveis de fora do5P   namespace temos que usar o
operador de escopo @@ . Por exemplo, para acessar as variáveis anteriores de fora 5P   podemos
escrever:

à 5P   @
 5P   @ ,


A funcionalidade dos namespaces é especialmente útil no caso em que há uma possibilidade de que um objeto
global ou função usa o mesmo identificador como um outro, causando erros de redefinição. Por exemplo:

à   P     àà
  
   

    '

   !  
  N M ')

     
 !
D 
 N M 6àà')
*
à(     ! ,
   @  N  ' 
  
 @@ N
 '
àà
  (')
à
à
à
à
à
à
àD
à*

Neste caso, há duas variáveis globais com o mesmo nome: N . Uma delas é definida dentro do
namespace   e outro no  
 . Sem erros redefinição acontecer graças aos namespaces.


 V
A palavra-chave
 é usada para introduzir um nome de um espaço para a declarativa região atual. Por
exemplo:V

à   G
  
   

    '

     !
  = M '
  5 M à(')

D     
 !
* 
 = M 6àà'
à( 
 5 M 6àD')
àà
    !
à
  @ = '
à
  
@ 5' 
 =  ' 
 5  ' 
   @ 5  ' 
  
@ =
à  '
à   (')
à
à
àD
à*
(






Note como neste código, = (sem qualquer qualificativo nome) refere-se a  @ = Considerando que 5 se
refere à  
@ 5 , exatamente como o nosso as declarações especificadas. Nós ainda temos acesso
à  @ 5 e  
@ = usando seus nomes totalmente qualificados.

A palavra-chave usando também pode ser usado como uma directiva relativa à introdução de um namespace
inteiro:

à   G
  
   

    '

   !  
  = M '
  5 M à(')

D     
 !
* 
 = M 6àà'
à( 
 5 M 6àD')
àà
    !
à
     ,
'   =  ' 
 5  ' 
  
@ =  ' 
 
à  '
à   (')
à
à
à
àD
à*
(





Neste caso, desde que tenham declarado que estávamos


     . , todos os usos diretos
de = e 5 sem qualificadores nome estava se referindo às suas declarações no    . .

 e
    ter validade apenas no mesmo bloco em que estão estabelecidas ou em todo o
código se eles são usados diretamente no escopo global. Por exemplo, se tivéssemos a intenção de usar
primeiro os objetos de um namespace e então os de outro, poderíamos fazer algo como:

à   P   =  6
  àà
  
   

    '

     !
  = M ')

     
 !
D 
 = M 6àà')
*
à(     !!

       
 ' 
 =  ' !)
àà

     
' 
 =  ')
à   (')
à
à
à
à
à
àD
à*
(









V

Podemos declarar nomes alternativos para namespaces existentes de acordo com o seguinte formato:

    l4 
4 M'V



V
Todos os arquivos na biblioteca C + + padrão de declarar todas as suas entidades no  namespace. É por
isso que geralmente incluíram o
     ' declaração em todos os programas que usou qualquer
entidade definida no   .

M
Exceções fornecem uma maneira de reagir a circunstâncias excepcionais (como erros de runtime) no nosso
programa de transferência de controle para funções especiais chamados m 
.

Para capturar exceções, devemos colocar uma porção de código sob inspeção exceção. Isto é feito colocando a
parte do código em um  * . Quando uma circunstância excepcional surge dentro desse bloco, será
apresentada uma exceção que transfere o controle para o manipulador de exceção. Se nenhuma exceção é
lançada, o código continua normalmente e todos os manipuladores são ignorados.

Uma exceção é lançada, usando a palavra-chave throw de dentro do bloco try. manipuladores de exceção são
declarados com a palavra-chave  , que deve ser colocado imediatamente após o bloco try:V

à   3= .; G = .; 


 3= .;  b
  
   

    '

    !
  
 !
  l (')
D    !
  #$

 = .; P  = .;# 
*  ')
à(   (')
àà
à
à
à
à

× código sob a manipulação de exceção é fechado em uma   N de bloco. Neste exemplo, esse código
simplesmente gera uma exceção:

O ('

Uma expressão de jogar aceita um parâmetro (neste caso o valor inteiro ( ), que é passada como um
argumento para o manipulador de exceção.

× manipulador de exceção é declarada com a  


 de palavras-chave. Como você pode ver, segue-se
imediatamente a chave de fechamento das   bloquear. × formato de captura é semelhante a uma função
normal, que sempre tem pelo menos um parâmetro. × tipo desse parâmetro é muito importante, pois o tipo do
argumento passado pela expressão throw é marcada contra ele, e somente no caso de eles corresponderem, a
exceção é capturada.

Podemos encadear vários manipuladores (catch expressões), cada uma com um tipo de parâmetro
diferentes. Apenas o manipulador que corresponde ao seu tipo com o argumento especificado na instrução
throw é executado.

Se usamos reticências (  ) como o parâmetro de  


 , que o manipulador vai pegar qualquer exceção,
não importa qual o tipo do  exceção é. Isso pode ser usado como um manipulador padrão que captura
todas as exceções não capturadas pelos manipuladores, se isso é especificado no passado:

à   !
   ]  F

 )
      !
  #3= .; # ')
     !
  #3= .;  # ')
   !
  = .;  ; # # ')


Neste caso, o último manipulador iria pegar qualquer exceção lançada com qualquer parâmetro que não é nem
um  nem um .

Após uma exceção tem sido tratado o programa de execução é retomada após o  5M bloco, e não após
o  indicação!.

Também é possível aninhar  5M blocos dentro de mais externa   blocos. Nestes casos, temos a
possibilidade de que um interno   
 para a frente do bloco a excepção ao seu nível externo. Isso é
feito com a expressão  l' sem argumentos.Por exemplo:

à   !
   !
   ]  F

 )
    !
  l '))
   !
  #3= .;# ')

D
*
à(
àà

 !
' V

Quando declarar uma função que pode limitar o tipo de exceção que possam, direta ou indiretamente lançar
anexando um  sufixo para a declaração de função:V

" 5"
       l   '

Isto declara uma função chamada 5"


  que leva um agument do tipo  e retorna um elemento do
tipo " . A única exceção que esta função pode lançar uma exceção do tipo  . Se ele lança uma exceção
com um tipo diferente, directa ou indirectamente, não pode ser capturada por um regular  tipo de
manipulador.

Se esse  especificador for deixado vazio sem nenhum tipo, isso significa que a função não é permitido
lançar exceções.Funções sem O especificador (funções regulares) estão autorizados a lançar exceções de
qualquer tipo:

à  5"
       l  '    = .2    
  5"
      '     = .2    

&

V
A biblioteca C + + padrão fornece uma classe base especificamente concebido para declarar objetos a serem
lançados como exceções. Ela é chamada  = .; e é definido no  =   arquivo de cabeçalho sob
o     . Essa classe tem o padrão normal e copiar os construtores, operadores e destruidores, além
de uma função membro virtual adicional chamado  que retorna uma seqüência de caracteres NULL-finalizada
(  1 ) e que pode ser substituído em classes derivadas para conter algum tipo de descrição do exceção.V

à   3= .2   ; 
= .;  

  
   
  
  =  

    '
  53=  @ K,  = .; !
 N 
   1 F
  O  !
   #  = .;  
# ')) 5 ='
D
*     !
à(  
!
àà
 l 5 =')
à   = .; € ! ,
  l   ')
à   (')
à
à
à
à
àD
à*
(





Nós colocamos um manipulador de exceção que pega objetos por referência (note o comercial depois o tipo),
pois esta captura também classes derivadas de = .; , como o nosso 5 = objeto da classe 53=   .

Todas as exceções geradas por componentes da biblioteca C + + padrão lançar exceções derivadas deste @
= .;@ classe.São eles:

'  ' 

bad_alloc Descartado pelo novo em caso de falha de alocação

bad_cast Descartado por dynamic_cast quando não com um tipo de referência

bad_exception Descartado quando um tipo de exceção não corresponde a nenhuma das capturas

bad_typeid Descartado por typeid

ios_base: falha Descartado por funções na biblioteca iostream

Por exemplo, se usamos o operador de N ea memória não pode ser atribuído, uma exceção do
tipo ,4 é lançada:
à  
 !
  1 5 5 M N  7à(((9')
 ,4 € !
  #3     ] #  ')




D

Recomenda-se incluir todas as alocações de memória dinâmica dentro de um bloco try que trava esse tipo de
exceção para realizar uma ação de limpeza em vez de uma finalização anormal do programa, que é o que
acontece quando esse tipo de exceção é lançada e não pegou. Se quiser forçar uma ,4 exceção para
vê-lo em ação, você pode tentar alocar uma enorme variedade; No meu sistema, tentando alocar 1.000
milhões  s jogou uma ,4 exceção.

Porque ,4 é derivado do padrão da classe base = .; , podemos lidar com essa mesma exceção
pegando referências à = .; da classe:

à   : ;  = .; ,4


     

  
  =  

    '
     !
  
 !
D  1 5 5 M N  7à(((9')
*   = .; € !
  # = .;  ;@ #  l 
à(  ')
  (')
àà
à
à
à
à
à

 
 
Convertendo a expressão de um determinado tipo em outro tipo é conhecido como m  . Nós já vimos
algumas maneiras de conversão de tipo:V

à '  


V
As conversões implícitas não requerem qualquer operador. Eles são executados automaticamente quando o
valor é copiado para um tipo compatível. Por exemplo:V

à 
 M (((6

  ,6 , M '


Aqui, o valor de
 foi promovido a partir 
 para  e nós não tivemos que especificar qualquer tipo de
vazamento do operador. Isso é conhecido como uma conversão padrão. conversões Standard afetam os tipos
de dados fundamentais, bem como permitir conversões, tais como a conversão entre tipos numéricos
( 
 para  ,  para " , ,  para  ...), ou de , , e algumas conversões de
ponteiro. Algumas destas conversões pode implicar uma perda de precisão, que o compilador pode sinalizar
com uma advertência. Isto pode ser evitado com uma conversão explícita.

As conversões implícitas incluem também construtor ou operador de conversões, que afetam as classes que
incluem construtores ou funções específicas do operador para realizar conversões. Por exemplo:
à  E !)'
  ? ! K,  @ ? E  !))' M  ,  E6 ?'




Aqui, uma conversão implícita aconteceu entre os objetos da  E e  ? , pois ? tem um construtor
que leva um objeto da classe E como parâmetro. Portanto conversões implícitas de
 para ? são permitidos.

 '  


V
C + + é uma linguagem fortemente tipada. Muitas conversões, especialmente aqueles que implicam uma
interpretação diferente do valor, necessitam de uma conversão explícita. Já vimos duas notações para a
conversão explícita: funcional e c-como a seleção de elenco:V

à    M ((('
  ,6 , M   '  M6   .;
 , M   '  "
  .; 


A funcionalidade destes operadores de conversão explícita é suficiente para a maioria das necessidades de tipos
de dados fundamentais. No entanto, estes operadores podem ser aplicados indiscriminadamente em classes e
ponteiros para classes, que pode levar a um código que ao ser sintaticamente correta pode causar erros de
execução. Por exemplo, o código a seguir está sintaticamente correta:

à      M 
  
   

    '

 D
5 !
 " 6 O')'

  E   !
D  =6 5'
* K,  @ E     6  , != M 6 5 M ,')
à(  
  !   =  5'))'
àà
    !D
5 ' E   1 '  M E   1 €D' 
 M 
  '
à   (')
à
à
à
à
à
àD
à*
(



× programa declara um ponteiro para E   , mas, em seguida, ele atribui a ele uma referência a um
objeto de outro tipo incompatível com explícita tipo-casting:

 M E   1 €D'

Tradicional explícita tipo de fundição permite converter qualquer ponteiro ponteiro em qualquer outro tipo,
independentemente dos tipos eles apontam. A chamada subseqüente ao membro 
 vai produzir tanto
um erro em tempo de execução ou de um resultado inesperado.
Para controlar esses tipos de conversões entre as classes, temos quatro operadores de casting
específico: 5 4 ,  4 ,  4 e 4 . × seu formato é seguir o novo
tipo de ângulo fechado entre colchetes (  ) e logo após, a expressão a ser convertido entre parênteses.

 l45  5 4  = ;


 l45   4  = ;
 l45   4  = ;
 l45  4  = ;

×s equivalentes a tradicional carcaça tipo para essas expressões seriam:

P l45 = ;
 l45  = ;

mas cada um com suas próprias características especiais:


G
 V

5 4 pode ser usado somente com ponteiros e referências a objetos. Sua finalidade é garantir que o
resultado da conversão de tipo é um objeto válido completo da classe solicitada.

Portanto, 5 4 sempre é bem sucedida quando lançamos uma classe para uma das suas classes base:V

à  ? !)'


  D N @ K,  ? !)' ? ,' ? , 1' D N  ' D N  1 ' , M
 5 4 ? 1 €  '   [@  NMM,
  M 5 4 D N 1 € , '   @ ,    N



D

A segunda conversão, neste pedaço de código produziria um erro de compilação desde a derivados de
conversões de base não são permitidas com 5 4 a menos que a classe base é polimórfico.

Quando uma classe é polimórfico, 5 4 realiza uma verificação especial durante o tempo de execução
para garantir que a expressão produz uma completa válido objeto da classe solicitada:

à   D5 4 :


     

  
  =  

    '

  ? ! N 
 N  
5  !))'
  D N @ K,  ? !  ')'

D     !
*   !? 1 , M N D N ' ? 1 :?? M N ? ' D N  1 '  M 5 4
à( D N 1 :?E '
   MM ( 
  #   
      "
 #  '  M 5 4
àà
D N 1 :?? 6
à    MM ( 
  #   
   
   "
 #  ')   = .; €
à !
  #3= .;@#   l  ')
à   (')
à
à
à
àD
à*
(




 
à 

)5 4 requer o Run-Time Type Information (RTTI) para manter o controle
dos tipos de dinâmicas. Alguns compiladores suportam esse recurso como uma opção que está desabilitada por
padrão. Este deve estar habilitado para a verificação de tipo em tempo de execução usando 5 4 para
funcionar corretamente.

× código tenta executar duas dinâmicas lança a partir de objetos do tipo ponteiro 1 ? ( :?E e :?? ) para
um objeto do tipo ponteiro D N  1 , mas só o primeiro é bem sucedida. ×bserve as suas respectivas
inicializações:

à ? , 1 M N D N ' :?? ? 1 M N ? '




Mesmo que ambos são indicadores do tipo 1 ? , , aponta para um objeto do tipo D N  ,
enquanto :?? aponta para um objeto do tipo ? . Assim, quando as respectivas tipo de peças fundidas são
realizadas usando 5 4 , , está apontando para um objeto cheio de classe D N  ,
enquanto :?? está apontando para um objeto da classe ? , que é um objeto da classe
incompleta D N  .

Quando 5 4 não pode converter um ponteiro, porque não é um objeto completo do requerido de
classe como a conversão em segundo lugar no exemplo anterior, ele retorna um ponteiro nulo para indicar a
falha. Se 5 4 é usado para converter para um tipo de referência e na conversão não for possível,
uma exceção do tipo ,4 é acionada em seu lugar.

5 4 também pode lançar ponteiros nulos, mesmo entre os ponteiros para classes independentes, e
também pode lançar qualquer tipo de ponteiros para ponteiros ( N  1 ).


G
V
 4 pode realizar conversões entre os ponteiros para classes relacionadas, não só da classe derivada
de sua base, mas também de uma classe base de seus derivados. Isso garante que pelo menos as classes são
compatíveis se o próprio objeto é convertido, mas não há verificação de segurança durante a execução é
realizada para verificar se o objeto a ser convertido é de fato um objeto completo do tipo de destino. Portanto,
é responsabilidade do programador para garantir que a conversão é segura. Por outro lado, a sobrecarga dos
controlos de segurança do tipo de 5 4 é evitado.V

à  ? !)'


  D N @ K,  ? !)' ? 1  M N ? ' D N  1 , M  4
 D N 1  '


Isso seria válido, apesar de , seria apontar para um objeto da classe incompleta e poderia levar a erros de
execução, se dereferenced.

 4 também pode ser usado para executar qualquer não-ponteiro conversão de outros que também
poderiam ser realizados implicitamente, como por exemplo a conversão de padrão entre os tipos fundamentais:

à 
  M àà*'
  M  4     '
×u qualquer conversão entre classes com construtores explícitos ou funções de operador conforme descrito em
"conversões implícitas" acima.

  G


V
 4 converte qualquer tipo de ponteiro para ponteiro qualquer outro tipo, mesmo de classes
independentes. × resultado da operação é um binário simples cópia do valor de um ponteiro para o
outro. Todas as conversões de ponteiro são permitidos: nem o conteúdo apontado nem o tipo de ponteiro em si
é marcada.

Ele também pode converter ponteiros ou de tipos inteiros. × formato em que este valor representa um ponteiro
inteiro é específico de plataforma. A única garantia é que um pointer cast para um tipo inteiro grande o
suficiente para contê-la plenamente, é concedido a poder ser lançado de volta para um ponteiro válido.

As conversões que podem ser executadas por  4 mas não por  4 não têm usos
específicos, em C + + são operações de baixo nível, cuja interpretação resulta em um código, que geralmente é
específico do sistema e, portanto, não-portáteis. Por exemplo:V

à  E !)'
  ? !)' E 1  M N E6 ? M , 1  4 ?1  '



Isto é válido C + + código, apesar de não fazer muito sentido, já que agora temos um ponteiro que aponta
para um objeto de uma classe de incompatibilidade e, portanto, dereferencing é inseguro.

 G
V
Este tipo de vazamento manipula o constness de um objeto, seja para fixar ou a ser removido. Por exemplo,
para passar a const argumento para uma função que espera um parâmetro de não-constante:V

à   4  =
  
   

    '

N     1  !
   ')

     !
   1  M # =  =  # '  ;  4   1   '
D   (')
*
à(
àà
à
à
à

 V
5  permite verificar o tipo de uma expressão:

5   = ;

Este operador retorna uma referência a um objeto de constante do tipo 5 4 " que é definido no cabeçalho
do arquivo padrão 5 " . Este valor retornado pode ser comparada com outra usando os
operadores MM e & M ou pode servir para obter uma seqüência terminada por caractere nulo que representa o
tipo de dados ou nome da classe usando o seu   membro.V

à   +5   , 
     

  
 5 "

    '

     !
  1 6 ,6  M (6 , M ('
  5   M& 5  , ! 
  # , ;   "    @ A # ' 
  #S@# 
D
5       BA B ' 
  #, S@#   5  ,     BA B ')
*   (')
à(
àà
à
à
à
à
à

Quando 5  é aplicada às classes 5  usa o RTTI para controlar o tipo de objetos dinâmicos. Quando
typeid é aplicado a uma expressão cujo tipo é uma classe polimórfica, o resultado é o tipo de derivado objeto
mais completa:

à   : ] " 6  5 


     

  
 5 "
 
  =  


    '

  ? ! N 
 N  "  !))'
  D N @ K,  ? !)'
D
*     !
à(   ? 1 ! M N ? ' ? , 1 M N D N ' 
  #S@#  5       BA B
   BA B ' 
  #1 S@#  5  1      BA B ' 
  #, 1 S @ #  5  , 1
àà
 = .; € !
  #3= .;@#  l   ')
à   (')
à
à
à
à
à
àD
à*
(

×bserve como o tipo que 5  considera para ponteiros é o tipo de ponteiro em si (tanto
 e , são do
tipo  ? 1 ). No entanto, quando 5  é aplicado a objetos (como  1 e 1 , ) 5  produz seu
tipo dinâmico (ou seja, o tipo de seus derivados objeto mais completa).

Se o tipo de 5  avalia é um ponteiro precedido pelo operador dereference ( 1 ), e este ponteiro tem um
valor nulo, 5  lança um ,45  exceção.


    
directivas Preprocessor são linhas incluídas no código dos nossos programas que não são declarações do
programa, mas diretrizes para o pré-processamento. Estas linhas são sempre precedidas por um cardinal
(  ). × pré-processador é executado antes da compilação real de código começa, portanto, o pré-processador
digere todas estas diretrizes antes de qualquer código é gerado pelas declarações.

Estas directivas de pré-processamento abrange apenas através de uma única linha de código. Assim como um
caractere de nova linha é encontrada, a directiva de pré-processamento é considerada como final. Nenhum
ponto e vírgula (;) é esperado no final de uma directiva de pré-processamento. A única forma de uma directiva
de pré-processamento pode se estender por mais de uma linha é precedendo o caractere newline no final da
linha por uma barra invertida ( A ). V
! 
 5! +5 !V
Para definir macros pré-processamento, podemos usar   "  . Seu formato é:

 D "    "   


, 
.;

Quando o pré-processador encontra presente directiva, que substitui qualquer ocorrência de   "  no
resto do código por 
, 
.; . Esta 
, 
.; pode ser uma expressão, uma declaração, um bloco ou
simplesmente nada. × pré-processador não entende C + +, ele simplesmente substitui qualquer ocorrência
de   "  de 
, 
.; .V

à  D "  +E?034/RU3 à((


  , à 7+E?034/RU39'
  ,  7+E?034/RU39'

Após o pré-processador substitui +E?034/RU3 , o código torna-se equivalente a:

à  , à 7à((96
  ,  7à((9'

Este uso de # define como definidor constante já é conhecido por nós de tutoriais anteriores, mas 
 "  pode trabalhar também com os parâmetros para definir macros de função:

 D "  < = 6 , 6 , @V ?

Isso substituir qualquer ocorrência de < = seguido por dois argumentos a expressão de substituição, mas
também substituindo cada argumento por seu identificador, exatamente como seria de esperar se fosse uma
função:

à     "
.;  
  
   

    '

  "  < = 6 ,   , @V  ,

     !
  = M 6 5' 5 M < = =6  ' 
 5  ' 
 < = 6 =  '
D   (')
*
à(
àà
à
à
à

macros definido não são afetados pela estrutura do bloco. Uma macro dura até que é indefinido com a directiva
de pré-processamento # undef:

à  D "  +E?034/RU3 à((


  , à 7+E?034/RU39'
 
 " +E?034/RU3
   "  +E?034/RU3 ((
 ,  7+E?034/RU39'

Isto irá resultar no mesmo código:

à  , à 7à((96
  ,  7((9'

As definições de função macro aceitar dois operadores especiais (  e   ) na seqüência de substituição:


Se o operador  é usado antes de um parâmetro é usado na seqüência de substituição, esse parâmetro é
substituído por uma seqüência literal (como se fosse entre aspas duplas)

à  D "   =  =
 
    '

Isso seria traduzido em:


  #  # '

× operador   concatena dois argumentos não deixando espaços em branco entre eles:

à  D "   6 ,


   ,
  6   #  # '

Isto também ser traduzido em:


  #  # '

Porque as substituições de pré-processamento acontecer antes de qualquer C + + verificar a sintaxe, as


definições de macro pode ser uma característica difícil, mas tenha cuidado: um código que depende fortemente
de macros complicadas podem parecer obscuras para outros programadores, uma vez que a sintaxe que eles
esperam é, em muitas ocasiões diferentes das expressões regulares programadores esperam em C + +.

  
5!!+5! !+5!+5 !+55!V

Essas diretrizes permitem incluir ou descartar parte do código de um programa, se uma determinada condição
seja atendida.

 " " permite uma seção de um programa a ser compilado somente se a macro que é especificado como o
parâmetro foi definido, não importa qual o seu valor. Por exemplo:V

à  R" " +E?034/RU3


  ,  7+E?034/RU39'
   "

Neste caso, a linha de código  ,  7+E?034/RU39' só é compilado se +E?034/RU3 foi previamente
definido com   "  , independentemente do seu valor. Se não foi definida, essa linha não será incluída na
compilação do programa.
 R" " serve para o exato oposto: o código entre  " " e   " directivas só é compilado se o
identificador especificado não foi previamente definido. Por exemplo:

à  +E?034/RU3 " "


   "  +E?034/RU3 à((
   "
  ,  7+E?034/RU39'

Neste caso, se, quando chegar a este pedaço de código, o +E?034/RU3 macro não foi definido ainda, que seria
definida como um valor de 100. Se ele já existisse, seria manter o valor anterior já que o   "  directiva
não seria executado.

×  " ,   e   " (ou seja, "else if") as directivas servem para especificar algumas condições a serem
cumpridas para que a parte do código que cercam a ser compilado. A condição que segue  " ou   " só
pode avaliar expressões constantes, incluindo expressões macro. Por exemplo:

à  R" +E?034/RU3 ((


 
 " +E?034/RU3
   "  +E?034/RU3 ((

  " +E?034/RU3 (


 " +E?034/RU3
   "  +E?034/RU3 (

D  
* 
 " +E?034/RU3
à(   "  +E?034/RU3 à((
àà   "
à
à  ,  7+E?034/RU39'
à

×bserve como toda a estrutura de  " ,   " e   directivas acorrentado termina com   " .

× comportamento do  " " e  " " também pode ser conseguido usando os operadores
especiais  "   e  "  & , respectivamente, em qualquer  " ou   " directiva:

à "&   "   +E?034/RU3


   "  +E?034/RU3 à((
   "  "   E®®EQ4/RU3
   "  +E?034/RU3 E®®EQ4/RU3
 ,  7+E?034/RU39'


 
 
 5 V
Ao compilar um programa e um erro acontece durante o processo de compilação, o compilador mostra uma
mensagem de erro com referências ao nome do arquivo onde o erro ocorreu e um número de linha, por isso é
mais fácil encontrar o código gerando o erro.

A    directiva permite-nos controlar ambas as coisas, os números de linha dentro do código de arquivos,
bem como o nome do arquivo que queremos que aparece quando um erro ocorre. Seu formato é:

 PK     #"   #

×nde K  é o número da linha nova que será atribuído para a linha de código seguinte. ×s números de linha
de sucessivas linhas será aumentado um por um a partir deste ponto.

#P # é um parâmetro opcional que permite redefinir o nome do arquivo que será mostrado. Por exemplo:V
à  0  ( #N %N   ,
#
  V'

Este código irá gerar um erro que será mostrado como erro no arquivo #N %N    ,
.;# , linha 20.


  5V
Esta directiva aborta o processo de compilação quando ele for encontrado, gerando uma compilação de erros
que pode ser especificado como parâmetro:V

à  44 
 
 R" "
  G        S   % &
   "

Este exemplo aborta o processo de compilação se o nome da macro 44 


 
 não está definido (este nome
de macro é definido por padrão em todos os compiladores C + +).

 
   ' 5 V
Esta directiva também tem sido usado assiduamente em outras seções deste tutorial. Quando o pré-
processador encontra um  
 directiva substitui-lo por todo o conteúdo do arquivo especificado. Há duas
maneiras para especificar um arquivo para ser incluído: V

à  R
 # F
N#
  
 "  

A única diferença entre as duas expressões são os locais (diretórios) onde o compilador vai olhar para o
arquivo. No primeiro caso, onde o nome do arquivo é especificado entre aspas, o arquivo é procurado no
mesmo diretório que inclui o arquivo que contém a directiva. No caso de que ele não está lá, o compilador
procura o arquivo no diretório padrão onde ele está configurado para procurar pelos arquivos de cabeçalho
padrão.
Se o nome do arquivo é colocado entre parênteses de ângulo   o arquivo é procurado diretamente onde o
compilador está configurado para procurar pelos arquivos de cabeçalho padrão. Portanto, os arquivos de
cabeçalho padrão são normalmente incluídos no ângulo entre parênteses, enquanto outros arquivos de
cabeçalho específicos estão incluídos o uso de aspas.




5 

V
Esta diretiva é usada para especificar diversas opções para o compilador. Essas opções são específicas para a
plataforma e compilador que você usa. Consulte o manual ou a referência do seu compilador para obter mais
informações sobre os possíveis parâmetros que podem ser definidos com   .

Se o compilador não oferece suporte a um argumento específico para o   , é ignorado - nenhum erro é
gerado.V

!   
 V
×s nomes de macro a seguir são definidos a qualquer momento:V


  
 

__LINE__ Valor inteiro que representa a linha atual do arquivo de código fonte a ser compilado.

__FILE__ Uma string literal contendo o nome da presumida do arquivo fonte a ser compilado.

Uma seqüência literal, sob a forma "Mmm dd / aaaa", contendo a data em que começou o processo
__DATE__
de compilação.
Uma seqüência literal, sob a forma "hh: mm: ss" com o momento em que começou o processo de
__TIME__
compilação.

Um valor inteiro. Todos os compiladores C + + tem este constante definida para algum valor. Se o
__cplusplus compilador é totalmente compatível com o padrão C + + o seu valor for igual ou superior a
199711L dependendo da versão da norma que respeitar.

Por exemplo:

à   : ;       3


  
    

    '

    !
  #3 S  K    # 440RP344' 
  #  F
N# 448R0344   #A #
 ' 
  #/
 , .;  .
# 44DE+344 ' 
  ## 44+R344  # A# ' 
  #$
   %
 N 44 
 
  # 44 
 
 '
   (')
D
*
à(
àà
à
à

V
M 

8&

 
  
C + + fornece as seguintes classes para realizar a saída ea entrada de caracteres para / de arquivos: V

>V !
) classe Stream para escrever em arquivosV
>V !
) classe Stream para ler arquivos
>V !
) classe Stream para ler e escrever de / para arquivos.

Essas classes são derivadas, direta ou indiretamente das classes   e   . Nós já usamos objetos
cujos tipos eram essas classes:   é um objeto da classe   e  ,
 é um objeto da
classe   . Therfore, já estamos utilizando as classes que estão relacionadas com o nosso arquivo de
córregos. E, de fato, podemos usar o nosso arquivo de córregos da mesma forma que já são usados para
usar   e O
    , com a única diferença que temos de associar esses riachos com arquivos físicos. Vamos
ver um exemplo:V

à   $ .2  ,%    F


N 7E F

  
   
  
 " 

    '

     !"  5"  ' 5"     # =  =# ' 5"   N    

  F
N #A  # ' 5"    '
   (')
D
*
à(
àà
à

Esse código cria um arquivo chamado =  = e insere uma frase para ele da mesma maneira que
estamos acostumados a ver com a  ,
 , mas usando o fluxo de arquivo 5"  vez.

Mas vamos ir passo a passo:



  V

A primeira operação executada em um objeto de uma dessas classes é associá-lo a um arquivo real. Este
procedimento é conhecido como a     . Um arquivo aberto é representado por um programa, um
objeto de fluxo (uma instância de uma dessas classes, no exemplo anterior, este foi 5"  ) e qualquer
operação de entrada ou de saída realizada sobre este objeto de fluxo será aplicado ao arquivo físico que lhe
estão associados .

Para abrir um arquivo com um objeto de fluxo que usamos a função de membro     :

  "   6  '

×nde  é uma seqüência terminada por caractere nulo do tipo  1  (do mesmo tipo que tem
strings literais), que representa o nome do arquivo a ser aberto, eo  é um parâmetro opcional com uma
combinação das seguintes bandeiras:V

ios:: in Aberto para as operações de entrada.

ios:: out Aberto para as operações de saída.

ios::
Abra no modo binário.
binary

ios:: Defina a posição inicial no final do arquivo.


comeu Se este sinalizador não estiver definido para qualquer valor, a posição inicial é o começo do arquivo.

Todas as operações de saída são realizadas no final do arquivo, anexando o conteúdo com o conteúdo
ios:: app atual do arquivo. Esta bandeira só pode ser usada em correntes abertas para as operações de saída
apenas.

ios:: Se o arquivo aberto para operações de saída já existia antes, seu conteúdo anterior é apagado e
trunc substituído por um novo.

Todos estes sinalizadores podem ser combinados usando o operador ×R bit a bit ( ). Por exemplo, se
queremos abrir o arquivo =  ,  em modo binário para adicionar dados que poderia fazê-lo pelo seguinte
chamada para função de membro     :

à "  5"  ' 5"     # =  , # 6 @@ 


 @@  @@ ,  5 '


Cada um dos ,  funções de membro das classes "  , "  e "  tem um modo padrão
que é usada se o arquivo é aberto, sem um segundo argumento:



%   
' 

ofstream ios:: out

ifstream ios:: in

fstream ios:: in | ios:: out

Para "  e "  classes, @@  e @@ 


 , respectivamente, estão automaticamente e
assumiu, mesmo que de um modo que não incluí-los é passado como segundo argumento para o  
 função de membro.

× valor padrão é aplicado somente se a função é chamada sem especificar qualquer valor para o parâmetro
mode. Se a função é chamada com qualquer valor nesse parâmetro o modo padrão é substituído, não
combinado.

Fluxos de arquivo aberto em modo binário e executar operações de entrada e de saída independentemente de
quaisquer considerações formato. Binário arquivos não são conhecidos como   

#  , e algumas
traduções podem ocorrer devido a formatação de alguns caracteres especiais (como a nova linha e caracteres
de retorno de carro).

Desde a primeira tarefa que é executada em um objeto de fluxo de arquivos é geralmente para abrir um
arquivo, essas três classes incluem um construtor que chama automaticamente o    função de membro e
tem os mesmos parâmetros exatamente como esse membro. Portanto, também poderíamos ter declarado o
anterior 5"  objeto e conduziu a operação de abertura mesmo em nosso exemplo anterior, por escrito:

5"  "   # =  , # 6 @@ 


 @@  @@ ,  5 '

Combinando a construção do objeto e da abertura de fluxo em uma única instrução. Ambas as formas de abrir
um arquivo são válidos e equivalentes.

Para verificar se um fluxo de arquivo foi bem-sucedida abertura de um arquivo, você pode fazê-lo, chamando
ao membro  4,   sem argumentos. Esta função de membro retorna um valor bool da verdade
no caso que de fato o objeto stream está associado a um arquivo aberto, ou false caso contrário:

 5"   4   !  1 [6  


 J 1  )


 
  V
Quando terminarmos com a nossa entrada e saída de operações em um arquivo devemos fechá-lo para que
seus recursos estejam disponíveis novamente. A fim de fazer isso temos que chamar o fluxo da função de
membro   . Esta função de membro leva sem parâmetros, e que ele faz é para liberar os buffers
associados e feche o arquivo:V

5"    '

Uma vez que esta função membro é chamado, o objeto de fluxo pode ser usado para abrir um outro arquivo,
eo arquivo está disponível novamente para ser aberto por outros processos.

No caso em que um objeto é destruído enquanto ainda associado a um arquivo aberto, o destruidor chama
automaticamente a função de membro   .

   V
arquivo de texto correntes são aqueles em que não incluem o @@ ,  5 bandeira no seu modo de
abertura. Esses arquivos são projetados para armazenar texto e, portanto, todos os valores que a entrada ou
saída de / para eles pode sofrer algumas transformações de formatação, que não necessariamente
correspondem às suas binário valor literal.

operações de saída de dados em arquivos de texto são executadas da mesma maneira que nós operamos
com  ,
 : V

à   3  
  F
N   = 73=
     

  
 " 

    '
     !5"  "   # =  =# '
  5"   4   !5"   #3 S
    A # ' 5"  #S 
    3 A #
 ' 5"    ')
D   
  #P; " JN  ,   F
N# '
*   (')
à(
àà
à
à
à
à
à

A entrada de dados de um arquivo também pode ser realizada da mesma forma que fizemos com   :

à   0
  F
N   = 3
     

  
 " 
  
  

    '

     !   ' 5"  "   # =  =# '
  5"   4   !
D    5"    !    6 5"  ' 
    ') 5"    ')
*
à(   
  #P; " JN  ,   F
N# '
àà
  (')
à
à
à
à
à
à
àD
à*
(




Este último exemplo lê um arquivo texto e imprime seu conteúdo na tela. ×bserve como usamos uma função
de membro novo, chamado ,  que retorna verdadeiro no caso em que o fluxo está pronto para / saída de
operações de entrada. Criamos um laço while que termina quando na verdade 5"    não é mais
verdade, o que vai acontecer ou se o fim do arquivo foi alcançado ou se algum outro erro ocorreu.

’!
 


 
 V
Além de ,  , que verifica se o fluxo está pronto para / saída de operações de entrada, existem outras
funções de membro para verificar a estados específicos de um riacho (todos eles retornam um valor booleano):

ruim ()
Retorna true se uma operação de leitura ou gravação falha. Por exemplo, no caso em que tentamos
escrever para um arquivo que não está aberto para a escrita ou se o dispositivo em que tento escrever
não tem espaço sobrando.

fail ()

Retorna true nos mesmos casos tão ruim (), mas também no caso de um erro de formato acontece,
como quando um caractere alfabético é extraído quando estamos a tentar ler um número inteiro.

eof ()

Retorna true se um arquivo aberto para leitura chegou ao fim.

bom ()
É a bandeira do estado mais genérico: ele retorna false nos mesmos casos em que chamar qualquer
uma das funções anteriores retornaria verdadeiro.

A fim de restaurar as bandeiras de estado marcado por qualquer dessas funções membro já vimos que
podemos usar a função de membro    , que leva sem parâmetros.V


  
   ! V
Tudo o que eu / o córregos objetos têm, pelo menos, um ponteiro de fluxo interno:

"  , como   , tem um ponteiro conhecido como o m


 
 que aponta para o elemento a
ser lido na próxima operação de entrada.

"  , como   , tem um ponteiro conhecido como o m


   que aponta para o local onde
o elemento seguinte tem de ser escrito.

Finalmente, "  , herda tanto, a chegar e colocar os ponteiros, de   (que é derivada de ambos
os   e   ).

Esses ponteiros internos córrego que apontam para a leitura ou escrita locais dentro de um fluxo pode ser
manipulado usando as funções de membro a seguir: V

 V
Estas duas funções de membro não tem parâmetros e retorna um valor do tipo membro 45 , que é um
tipo de dados inteiro que representa a posição atual do ponteiro do stream get (no caso de   ) ou o
ponteiro de fluxo de venda (no caso de   ). V

CC  V
Estas funções permitem alterar a posição dos ponteiros stream get e put. Ambas as funções são
sobrecarregadas com dois tipos de protótipos. × primeiro protótipo é:

 [   .; '
 [   .; '

Usando este protótipo do ponteiro de fluxo é alterado para a posição absoluta  .; (contando a partir do
início do arquivo). × tipo para este parâmetro é o mesmo que aquele retornado por funções   e   : o
tipo de membro 45 , que é um valor inteiro.

× protótipo outros para estas funções é:

 [ "" 6  .; '


 [ "" 6  .; '

Usando este protótipo, a posição do ponteiro ou colocar recebe é definido para um valor de deslocamento em
relação a algum ponto específico determinado pelo parâmetro    . ""  é do tipo membro ""45 ,
que também é um tipo inteiro. E  .; é do tipo  [ , que é um tipo enumerado ( 
 ) que determina
o ponto de onde é contada a partir de deslocamento, e que pode ter qualquer dos seguintes valores:V

ios:: beg compensado, contados a partir do fluxo de

ios:: act offset contados a partir da posição atual do ponteiro de fluxo

ios:: end offset, contados do término do fluxo

× exemplo a seguir usa as funções de membro que acabamos de ver para obter o tamanho de um arquivo:

à   +  "   , .;


     

  
 " 

    '
     !
     J  " ' 5"  "   # =  =# ' ,   M 5"     ' 5"   [ (6
 
  #$  S@# " M  .  # ,5  A# '
  (' )
D
*
à(
àà
à
à
à
à

×
    V
Em arquivos binários, para entrada e saída de dados com os operadores de inserção e extração (  e  ) e
funciona como    não é eficiente, já que não precisam de qualquer formato de dados, e os dados não
podem utilizar os códigos usados por separação arquivos de texto para separar os elementos (como, newline,
espaço, etc ..).

Fluxos de arquivo incluem duas funções de membro projetado especificamente para entrada e saída de dados
binários em seqüência:  N e  . × primeiro (  N ) é uma função de membro
do   herdada por "  . E  é uma função membro de   que é herdado
por "  . ×bjetos da classe "  têm ambos os membros. Seus protótipos são:

l     54,[ '


     54,[ '

×nde   54,[ é do tipo "ponteiro para char (  1 ), e representa o endereço de um array de bytes,
onde os elementos de dados são armazenados ou lidos a partir do qual os elementos de dados a serem
gravados são tomadas. ×   parâmetro é um valor inteiro que especifica o número de caracteres a
ser lida ou escrita de / para o bloco de memória.V

à   0
  F
N , %    
     

  
 " 

    ' " @@  C 45 '
  ?[ 1'

     ! "   F
N  # =  , # 6 @@  @@ ,  5 @@ 
'
  "   4   ! "    M  '  ?[ M N  79' "   [ (6 @@ ,
D 
  #  K   F
N    %   ] # '
*
à( =
 ?[9 7')
  
  #P; " JN  ,   F
N# '
àà
  (')
à
à
à
à
à
à
àD
à*
(






Neste exemplo, o arquivo inteiro é lido e armazenado em um bloco de memória. Vamos examinar como isso é
feito:
Primeiro, o arquivo é aberto com o @@ 
bandeira, o que significa que o ponteiro começa será
posicionado no final do arquivo. Dessa forma, quando chamamos ao membro    , vamos obter
diretamente o tamanho do arquivo. ×bserve o tipo que temos usado para declarar variáveis   :

 45 '@ " @

" @@ 45 é um tipo específico usado para o posicionamento e arquivo de buffer e é o tipo
retornado por "     . Este tipo é definido como um tipo inteiro, por isso podemos realizar nela as
mesmas operações que realizamos sobre qualquer outro valor inteiro, e pode seguramente ser convertidos para
outro tipo inteiro grande o suficiente para conter o tamanho do arquivo. Para um arquivo com um tamanho de
2GB em que poderíamos usar  :

à   C 6  C M   "     '




Uma vez que tenhamos obtido o tamanho do arquivo, pedimos a atribuição de um bloco de memória grande o
suficiente para manter o arquivo inteiro:

 ?[ M N  79'

Logo depois, passamos a definir o ponteiro começar no início do arquivo (lembre-se que abrimos o arquivo com
este ponteiro no final), em seguida, ler o arquivo inteiro e, finalmente, fechá-lo:

à "   [ (6 @@ ,  ' 8    ' "      ?[ '



Neste ponto, poderia operar com os dados obtidos a partir do arquivo. Nosso programa simplesmente anuncia
que o conteúdo do arquivo está na memória e depois termina.

    3
' V

Quando operar com fluxos de arquivo, estes estão associados a um buffer interno do tipo  ,
" . Este
buffer é um bloco de memória, que age como intermediário entre o fluxo eo arquivo físico. Por exemplo, com
um "  , cada vez que a função de membro  (que escreve um único personagem) é chamado, o
personagem não foi escrita diretamente para o arquivo físico com o qual o fluxo é associado. Em vez disso, o
personagem está inserido no buffer de fluxo de intermediários que.

Quando o buffer é liberado, todos os dados contidos nele são gravados no meio físico (se é um fluxo de saída),
ou simplesmente libertado (se é um fluxo de entrada). Este processo é chamado
   e tem lugar
em qualquer das seguintes circunstâncias:V

>V -
  
  !
 ) antes de fechar um arquivo de todos os buffers que ainda não foram
liberados estão sincronizados e todos os dados pendentes são escritos ou lidos ao meio físico.V
>V -
  !! ) amortecedores têm um determinado tamanho. Quando o buffer estiver
cheio, é automaticamente sincronizado.
>V M 
 + 
 
 ) Quando certos manipuladores são utilizados em rios, uma
sincronização explícita ocorre. Estes manipuladores são: "
 e  .
>V M 
 +
! '   3
'    ) chamada de fluxo de função de
membro 5  , que leva sem parâmetros, faz uma sincronização imediata. Esta função retorna
um  valor igual a Mà se o fluxo não tem buffer associado ou em caso de falha. Caso contrário (se o
buffer corrente foi sincronizada com êxito) ele retorna ( .
× 
 


Um  é a quantidade mínima de informações que podemos imaginar, uma vez que apenas armazena um valor
1 ou 0, o que representa sim ou não, ligado ou desligado, verdadeiro ou falso, etc .. ou seja: dois estados
possíveis de cada um frente ao outro, sem qualquer possibilidade de sombras. Vamos considerar que os dois
possíveis valores de um bit são 0 e 1.

Várias operações podem ser realizadas com bits, quer em conjunto com outros pedaços ou sozinhos. Essas
operações recebem o nome de  .2  ,  , uma palavra que vem do nome de um dos matemáticos
que contribuíram mais para esse campo: George Boole (1815-1864).

Todas estas operações têm um comportamento estabelecidos e todos eles podem ser aplicados a qualquer bit,
não importa qual o valor que eles contêm (0 ou 1). Em seguida, você tem uma lista das operações booleanas
básicas e uma tabela com o comportamento de que a operação com cada combinação possível de bits. V

M xV
Esta operação é realizada entre dois bits, que chamaremos de
 e , . × resultado da aplicação da presente
operação e é 1 se os dois
 e , são iguais a 1 e 0 nos demais casos (isto é, se uma ou ambas as variáveis é
0).

M< V


<

0 00

0 10

1 00

1 11

×Ú ×®
Esta operação é realizada entre dois bits (
 e , ). × resultado é 1 se qualquer um dos dois bits for 1, ou se
ambos são 1. Se nenhum for igual a 1, o resultado é 0.

×®=V


=

0 00

0 11

1 01

1 11

$×®  V
Esta operação é realizada entre dois bits (
 e , ). × resultado é 1 se qualquer um dos dois bits é 1, mas não
no caso em que ambos são. Há pois, se nem deles ou ambos são iguais a 1, o resultado é 0.

$×®;V


;

0 00
0 11

1 01

1 10

H×  V
Esta operação é realizada em um único bit. Seu resultado é a inversão do valor real do bit: se ele foi definido
para 1 se torna 0, e se ele for 0, torna-se 1:

H×AV

A

0 1

1 0

Estas são as quatro operações básicas booleano (AND, ×R, X×R e N×T). Combinando estas operações,
podemos obter qualquer resultado possível a partir de dois bits.

Em C + +, estes operadores podem ser usados com variáveis de qualquer tipo de dados inteiro, a operação
booleana é realizado para todos os bits de cada variável envolvida. Por exemplo, supondo-se duas
variáveis:
 e , , ambos do tipo
    , onde
 contém 195 (11000011 em binário) e , contém 87
(ou 01010111 em binário). Se escrever o seguinte código:

à
     M à*'

    , M D'

    '  M €,'


Isso quer dizer que fizemos um bit a bit E operação entre


 e , . A operação é realizada entre os bits das duas
variáveis que estão localizados na mesma posição: × bit mais à direita de  vai conter o resultado de realizar a
operação AND entre os bits mais à direita de
 e , :

A mesma operação também é realizada entre a segunda bits de ambas as variáveis, eo terceiro, e assim por
diante, até que a operação é realizada entre todos os pedaços de ambas as variáveis (cada um apenas com o
mesmo pedaço de outra variável).

× binário valor final de  é 01000011, ou seja, 67 em números decimais. Assim, à* D é igual a  .
V
P


Desde que éramos crianças, todos nós temos usado para expressar quantidades decimais. Esta nomenclatura
que parece tão lógico para nós pode não parecer assim para um habitante de Roma Clássica. Para eles, cada
símbolo que eles escreveram para expressar um número sempre representou o mesmo valor:V

R à RR  RRR  RL  L 

Tudo o F

sempre sinais representa o valor de 1 (um) onde eles são colocados, eo L signo sempre
representa um valor de 5 (cinco). No entanto, que não tem lugar em nosso sistema decimal. Quando nós
escrevemos o símbolo decimal 1 não estamos sempre a falar de um valor de um (I em algarismos
romanos). Por exemplo:

à R à( > à(( 

Nestes casos, o nosso símbolo 1 não tem sempre um valor de um (ou eu em algarismos romanos). Por
exemplo, no segundo caso, o símbolo de uma representa um valor de dez (ou X em romano) e no terceiro, 1
representa um valor de cem (ou C).

Por exemplo:

 não é equivalente a 2 7 5, poderia ser decomposto em vez de 200 70 5:

((  (  MMM 

portanto, o primeiro "2" sinal é equivalente a 200 (2 x 100), o segundo "7" sinal é equivalente a 70 (7 x 10)
Considerando que o último sinal que corresponde ao valor de cinco (5 x 1).

Isso é porque o nosso sistema é um sistema numeral posicional. Como tal o valor de um algarismo depende de
sua posição dentro do número inteiro a ser representada. Todo o acima pode ser matematicamente
representado em uma forma muito simples. Por exemplo, para representar o valor 182.736 podemos supor que
cada algarismo é o produto de si mesmo, multiplicada por 10 powered para o seu lugar como expoente, a partir
da direita, com 10 0 , na sequência com 10 1 , 10 2 , e assim por diante:

.  

IV
Tal como o nosso "normal" são números 
>J (ou radix 10), porque temos 10 algarismos diferentes (do
0 ao 9):

(àD*

octals os números incluem apenas as representações para os valores de 0-7:

(à

e, por conseguinte, a sua base matemática é 8. Em C + + números octais são denotados por início sempre com
um ( dígito. Vamos ver como é que iria escrever os primeiros números em octal:V

    MMMMM MMMMMMM ( ( C  (à à 


 (    (   I (  F
  ( 
  (    (    (à( D   (àà * N (à à(  C (à àà C (à à
C (à à  C (à à F
 C (à à F
C (( à  C   (à à  C  

Assim, por exemplo, o número 17 (dezessete, ou XVII, em romano) é expresso (à como um número octal em
C + +. Podemos aplicar o mesmo mecanismo que vimos anteriormente para números decimais para os
números octal simplesmente por considerar que sua base é 8. Por exemplo, se o número octal (à :
portanto, o número octal (à é expressa em 29.363 em números decimais.

× . 




>"V
Como os números decimais possuem 10 dígitos diferentes para serem representadas (0123456789) e números
octal tem 8 (01234567), números hexadecimais ter 16 dígitos diferentes, que são representados pelos números
0-9 e as letras A, B, C, D, E e F, que, juntos, servem-nos para representar os 16 símbolos diferentes que
precisamos expressar base 16 números:V

    =   MMMMMMMMMMM MMMMMMM ( ( C  (=à à 


 (=    (=   I (= 
F
  (=    (=    (=    (=D D   (=* * N (=E à(  C (=? àà
C (= à C (=D à  C (=3 à F
 C (=8 à F
C (=à( à  C   (=àà
à  C  

Em C + +, números hexadecimais são precedidos por (= (zero, x).

Mais uma vez podemos utilizar o mesmo método para traduzir um número de uma base para outra:

  
 
V
×ctal e hexadecimal números têm uma vantagem considerável sobre os nossos números decimais no mundo
dos bits, e é que as suas bases (8 e 16) são múltiplos perfeito de 2 (dois 3 e 2 4 , respectivamente), o que nos
permite realizar conversões mais fácil a partir dessas bases para binário do que de números decimais (cuja
base é 2x5). Por exemplo, suponha que queremos traduzir a seguinte seqüência binária para números de
outras bases:

àà((ààààà(à((à(à((

A fim de traduzi-lo em decimal seria preciso realizar uma operação matemática semelhante ao que usamos
anteriormente para converter de hexadecimal ou octal, o que nos daria o número decimal 212628.

No entanto a passagem desta seqüência em octal só vai nos levar de alguns segundos e até mesmo os menos
qualificados em matemática, pode fazê-lo apenas por vê-la: Desde 8 é 2 3 , vamos separar o valor binário em
grupos de 3 números:V

àà( (àà ààà (à( (à( à((

e agora só temos de traduzir para radix numberal octal cada grupo separadamente:

àà( (àà ààà (à( (à( à((      

dando o número 637.224 como resultado. Esse mesmo processo pode ser inversamente realizados para passar
de octal para binário.
A fim de realizar a operação com os números de hexadecimal só temos para executar o mesmo processo, mas
separar o valor binário em grupos de 4 números, porque 16 = 2 4 :

àà ((àà ààà( à((à (à(( 3   * 

Portanto, a expressão 110011111010010100 binários podem ser representados em C + + ou como 212628


(decimal), com 0.637.224 (octal) ou como 0x33e94 (hexadecimal).

× código hexadecimal é especialmente interessante em ciência da computação desde hoje, os computadores


são baseados em bytes composto de 8 bits binários e, portanto, corresponde a cada byte com o intervalo que 2
números hexadecimal pode representar. Por isso, é tão freqüentemente utilizada para representar valores
traduzidos para ou de base binária.

®!0 

®!0 

 
Ã77P 
+ 


   
     3


! 

× padrão C + + biblioteca é uma coleção de funções, constantes, classes, objetos e modelos que estende a
linguagem C + + fornecendo funcionalidade básica para executar várias tarefas, como aulas de interagir com o
sistema operacional, os recipientes de dados, manipuladores de operar com eles e algoritmos comumente
necessário.

As declarações dos diferentes elementos fornecidos pela biblioteca são divididas em vários cabeçalhos que
devem ser incluídas no código, a fim de ter acesso aos seus componentes:V

algoritmo complexo exceção lista pilha

bitset csetjmp fstream localidade stdexcept

cassert csignal funcionais mapa strstream

cctype cstdarg iomanip memória streambuf

cerrno cstddef ios novo string

cfloat cstdio iosfwd numéricos typeinfo

ciso646 cstdlib iostream ostream utilitário

climits cstring istream fila valarray

clocale ctime iterador conjunto vector

CMATH deque limites sstream

Ela pode ser dividida em:

P 
ÃV
×s elementos da biblioteca da linguagem C também estão incluídos como um subconjunto da biblioteca C + +
padrão. Estes abrangem muitos aspectos, a partir de funções de utilidade geral e macros para funções de
entrada / saída e funções de gerenciamento dinâmico de memória:V



 Biblioteca C Diagnostics (cabeçalho)

   Personagem funções de manipulação (cabeçalho)

   C erros (cabeçalho)


!
!
 Características dos tipos de ponto flutuante (cabeçalho)

 "#" "#" IS× 646 grafias alternativas operador (cabeçalho)

 Tamanhos dos tipos integrais (cabeçalho)

 
 
 C biblioteca de localização (cabeçalho)

à 
 Biblioteca C numéricos (cabeçalho)

$ $  local não pula (cabeçalho)



 biblioteca C para lidar com sinais (cabeçalho)



 tratamento de argumentos variável (cabeçalho)

!! Standard definições C (cabeçalho)

   biblioteca C para executar / ×utput operações de entrada (cabeçalho)

 Standard C Library General Utilitários (cabeçalho)

   C Strings (cabeçalho)

 C Time Library (cabeçalho)

Ã77 

' )
 
x V
c 
 

 : V

 limites numéricos (cabeçalho)

 Dinâmica de memória (cabeçalho)

  ! Digite informações (cabeçalho)

' Standard classe de exceção (classe)

 
x
 ( :

  classes de exceção (cabeçalho)

P 
2
  :

 componentes Utility (cabeçalho)

! 
 Função objetos (cabeçalho)

(
×s elementos de memória (cabeçalho)

 
&  :
  Biblioteca C + + Strings (biblioteca)

 
 
3
' :

 

 Localização biblioteca (cabeçalho)

P 
Ã77
' )&

 

 &V
 
à   : V

 Bitset (modelo de classe)

  Dupla fila acabou (modelo de classe)


Lista (modelo de classe)



Mapa (modelo de classe)


Chave-mapa múltipla (modelo de classe)

 -Set múltiplo (modelo de classe)

  G  Prioridade da fila (modelo de classe)

!
Fila FIF× (modelo de classe)

 $  Set (modelo de classe)


Pilha LIF× (modelo de classe)

  Vector (modelo de classe)

 

  :


  definições Iterator (cabeçalho)

P 
   :

&   Standard Template Library: Algoritmos (biblioteca)

 
 
:

   biblioteca de números complexos (cabeçalho)




Biblioteca para matrizes de valores numéricos (cabeçalho)

  numéricos operações generalizadas (cabeçalho)

P 
Ã77
' )c 8P 
! 

V
Fornece funcionalidade de usar uma abstração chamada %
 especialmente projetado para realizar
operações de entrada e saída em seqüências de caracteres, como arquivos ou strings.
Essa funcionalidade é fornecida através de várias classes, como mostra no mapa seguinte relação com os
nomes de cabeçalho do arquivo correspondente no topo:

You might also like