Buscar

Programar em C++

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 141 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 141 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 141 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

PDF gerado usando o pacote de ferramentas em código aberto mwlib. Veja http://code.pediapress.com/ para mais informações.
PDF generated at: Fri, 06 Dec 2013 10:37:21 UTC
Programar em C++
Conteúdo
Páginas
Objetivo 1
Por que C++? 1
Diferenças entre C e C++ 2
Introdução 3
Alô, Mundo! 6
Variáveis e constantes 12
Ponteiros 18
Vetores 20
Estruturas 29
Operadores 34
Decisão e controle de fluxo 37
Laços 39
Funções 42
Referências de dados 44
Entrada e saída de dados 49
Entrada e saída de dados 2 58
Manipulando strings 73
Classes 81
Encapsulamento 96
Herança 99
Polimorfismo 112
Friend 117
Classes internas 119
Sobrecarga de operadores 120
Alocação dinâmica de memória 122
Exceções 129
Namespace 129
Templates 129
Compilação 131
Lista de Palavras Reservadas do C++ 133
Lista de Sequências de Escape 133
Tabela ASCII 134
C++11 135
Referências
Fontes e Editores da Página 136
Fontes, Licenças e Editores da Imagem 137
Licenças das páginas
Licença 138
Objetivo 1
Objetivo
O livro Programar em C++ tem por objetivo apresentar os fundamentos desta linguagem, de modo que o estudante
possa desenvolver diferentes tipos de softwares em alto e baixo nível para os diversos ambientes existentes, desde
aplicações para GNU/Linux ou Windows até programas para microcontroladores, além de fornecer a base para os
estudos avançados de C++.
Por ser um livro específico sobre a linguagem C++, é altamente recomendável que o leitor tenha conhecimentos
prévios sobre a linguagem C.
Espera-se que este livro aborde:
•• Aspectos teóricos
•• Aspectos práticos
•• Os erros comuns
Para tanto cada tópico deverá ter uma explicação teórica, citar os erros mais comuns e exercícios.
Por que C++?
Imagine que você deve fazer um programa para fazer a máquina de um pequeno relógio de pulso funcionar, então
você pensa:
•• Bom, isso pode ser feito com Assembly...
•• Porém, pensando melhor, você decide mudar de linguagem quando você pondera.
•• O problema maior é que se eu tiver que mudar o processador do relógio, vou ter que refazer o programa. É melhor
usar linguagem "C".
•• Depois você termina por avaliar outra possibilidade:
•• Bem, se eu já estou pensando em "C" é melhor usar "C++", depois vai ser mais fácil de entender o código,
reaproveitar em outras coisas e ainda vai ser mais fácil de expandir para outros modelos de relógio.
E assim é o que podemos perceber como C++ é poderosa, flexível e abrangente. Ela pode ser usada para programar
qualquer tipo de hardware, desde os mais simples até os mais complexos. Além disso, C++ é uma linguagem que
gera programas em código de máquina, que funcionam com ou sem a participação de sistemas operacionais no
dispositivo.
Alguns profissionais afirmam que C++ é a linguagem mais poderosa que existe, veja algumas características dela:
• É um superconjunto da linguagem C, e contém vários melhoramentos;
• Deu origem a grandes linguagens como Java e D;
• É a porta para a programação orientada a objetos;
• C++ pode virtualmente ser efetivamente aplicado a qualquer tarefa de programação;
•• Há vários compiladores para diversas plataformas tornando a linguagem uma opção para programas
multiplataforma.
A linguagem C++ é utilizada em projetos como:
• Compiladores;
• Editores;
• Ferramentas de programação;
• Jogos;
• Programas de redes.
Até ao momento foram realizadas 3 grandes revisões à linguagem:
Por que C++? 2
•• 1ª em 1985;
•• 2ª em 1990;
• 3ª em 1998 a que deu origem ao ANSI \ ISO standard a que ficou comummente denominada de Standard C++.
Esta versão é suportada por todos os compiladores C++ famosos incluindo Microsoft’s Visual C++, Borland’s
C++ Builder e GCC. Esta foi revista em 2003.
C++ é considerada uma linguagem que está entre linguagem de alto nível (em inglês, high level language) e
linguagem de baixo nível (em inglês, low level language). Dito de outra forma, é uma linguagem que está próxima
da linguagem humana (linguagem de alto nível), mas ao mesmo tempo permite estar próximo da maneira como o
computador processa, próximo do Assembly (uma linguagem de baixo nível).
Diferenças entre C e C++
Quem sabe programar em C++, é capaz de programar C, devido à semelhança entre as linguagens e o fato do C++
ser uma extensão do C. Contudo o C não é completamente um subconjunto do C++. Grande parte de código C pode
ser perfeitamente compilado em C++, mas existem algumas pequenas diferenças sintáticas e semânticas entre as
linguagens que tornam alguns trechos de código C válidos em código C++ inválido, ou códigos que exibem
comportamentos diferentes em cada linguagem.
Algumas diferenças básicas:
• O C permite a conversão implícita entre o tipo de dado void* para ponteiros para outros tipos, algo que o C++ não
permite.
• O C permite que constantes de caracteres sejam inseridas em chamadas de funções com parâmetros tipo char*,
em C++ é preciso declarar o parâmetro como const char *;
Além destas pequenas diferenças, C++ tem um conjunto de características que a torna fundamentalmente diferente
de "C". Esse conjunto, torna possível programar em C++ de um modo totalmente diferente do modo de programar da
linguagem "C". O que traz a diferença é o modo da orientação na montagem do código.
Chamamos o modo de programar em "C" de orientado a procedimentos e chamamos o modo do "C++" de orientado
a objetos. Muitas pessoas confundem as coisas quando começam a programar usando um compilador C++, pois esta
linguagem permite programar nos dois modos. Essa é uma das características que a torna mais flexível.
Apesar de C++ permitir programar em modo orientado a procedimentos, podemos dizer que nestes casos estamos
programando em "C", usando um compilador C++. Quando usamos C++ programamos em modo orientado a
objetos. Devido a estas características, o C++ permite programar em modo misto, ou seja, escrevendo partes do
código orientadas a procedimentos e outras orientadas a objetos.
As diferenças entre os dois modos de programar serão esclarecidas nos capítulos subsequentes. Por hora nos basta
deixar claro que os dois modos são diferentes. Usar estes dois modos de programar ao mesmo tempo é uma das
facilidades que o C++ permite, enquanto que outras linguagens orientadas a objetos como Java, Eifel, etc, não
permitem.
Esta página é somente um esboço.
Ampliando-a você ajudará a melhorar o Wikilivros.
Introdução 3
Introdução
Pensando no código
Considerando o conjunto de operações e eventos que nosso programa deve executar temos diversas maneiras de criar
o código, porém o mais difícil é criar um código eficiente, rápido e compacto. Na verdade, diversos fatores podem
interferir nestes aspectos da programação, entre eles, a escolha do compilador, o método de estruturar o código, a
orientação do mesmo, etc... Em termos gerais, um código torna-se mais próximo do ideal a medida que suas partes
tornam-se mais simples de se analisar e quando todos os processos estão bem definidos e especializados. Quando
temos um código que contém muito mais exceções do que regras, este precisa de uma reestruturação.
Podemos definir C++ como um "superconjunto" da linguagem C, ou seja, uma linguagem com mais funcionalidades
que a linguagem C. Embora este seja o ponto de vista de quem já tem um conhecimento da linguagem C, ela é muito
mais que isto. Podemos mudar completamente a forma de criar o programa quando usamos os recursos avançados da
linguagem, as estruturas de decisão (por exemplo, if-else ou switch) podem ser simplificadas e a organização
do código pode ser bem mais globalizada e genérica, possibilitando a reutilização do código em diversas situações
diferentes.
Vejamos como as funcionalidades da linguagem C++ podem ajudar a redefinir os meios de programação que
aprendemos com o bom e velho estilo C.
Dois modos de programar
Observando o modo de programar que as linguagens oferecem desde os primórdiosda computação, podemos notar
vários métodos que foram sendo superados e outros que se estabelecem por um momento. O modo de programar
mais usual e bem mais difundido é conhecido como modelo estruturado sequencial. Em síntese, refere-se a forma
de programar onde uma instrução segue a outra numa sequência que inicia e termina em um fluxo parcialmente
"previsível".
A programação estruturada ainda pode ser classificada em dois modos: um orientado a procedimentos e outro
orientado a objetos. Os dois podem ser confundidos por quem não tem muita experiência, mas o uso de um ou do
outro implica em características próprias para cada caso. Logo, é preciso entender bem os conceitos antes de definir
se um código é procedural ou orientado a objetos.
O modelo sequenciado procedural é bem simples de implementar, porém, aumenta a complexidade para tarefas mais
bem trabalhadas e sofisticadas. Isto ocorre devido a estrutura do modelo, que exige rotinas cada vez mais extensas.
Não raramente é possível encontrar rotinas que, em alguns casos, tornam-se comparáveis a programas completos,
usando como referência o número de linhas de instruções. O uso deste modelo, muitas vezes dificulta a manutenção
e expansão do código, caso isto não seja feito de maneira muito bem organizada.
O segundo modelo é o orientado a objetos. O que significa isso e o que muda no modo de programar, caso o
adotemos em vez do modelo anterior?
A orientação define o modo de abordar o problema para tentar solucioná-lo:
•• O modelo de orientação a procedimentos se preocupa em fornecer meios para resolver o problema sem
contabilizar, a princípio, os dados que serão usados durante o processo.
•• O modelo de orientação a objetos se preocupa com os elementos que são necessários para a solução de um
problema. Sob este ângulo, os dados são os elementos principais na análise do problema.
Este livro traz uma visão dos problemas sob a óptica da orientação a objetos, enquanto que o livro "Programar em C" 
traz a análise sob a óptica da orientação a procedimentos. Isto não quer dizer que devamos escolher a orientação a 
objetos como o modo mandatório de programação, mas que podemos contar com seus recursos sempre que esta 
escolha facilite a resolução do problema. Portanto, cabe sempre uma análise para definir se o problema é melhor
Introdução 4
tratado por uma abordagem orientada a objetos ou a procedimentos.
Um pouco sobre orientação a objetos
A programação orientada a objetos é um paradigma de programação que visa organização, produtividade e
sustentabilidade.
A apresentação dos conceitos de orientação a objetos é bastante abrangente, o que implica na abordagem de diversos
aspectos, como modelagem, estudo de performance de modelos, aplicabilidade de técnicas, estruturação de objetos,
otimização, manutenção do código, entre outros. Por este motivo, nosso objetivo aqui não é apresentar a orientação a
objetos em sua totalidade. Para um estudo mais detalhado do tema sugerimos o livro POO, que trata especificamente
deste tema. O objetivo aqui é apresentar como a orientação a objetos se aplica na linguagem C++, porém os
conceitos aqui apresentados devem ser suficientes para a estruturação de programas de bom nível.
A ideia principal por traz do modelo de programação orientado a objetos está em transformar entidades do mundo
real em identificadores dentro do programa (objetos), trabalhando-os como entidades da linguagem que possuem
características e operações próprias. Esta abordagem transforma o programa em um meio de simulação de situações
virtuais por meio de entidades de código que tem comportamento predefinido. Esta abstração é uma aliada do
programador por permitir idealizar sistemas mais sofisticados de uma maneira bastante intuitiva.
Todas as linguagens orientadas a objectos contêm os princípios de:
•• Encapsulamento
É um mecanismo para esconder os detalhes envolvidos no processamento de uma ação. Por exemplo, quando
usamos um telefone, não precisamos lidar diretamente com o circuito interno; a interface do telefone cuida
desse problema.
•• Polimorfismo
Isso permite o uso de uma única interface ― uma única forma de uso ― para objetos de tipos diferentes; em
particular, a mesma interface para objetos de uma classe e objetos de classes derivadas dessa.
•• Herança
Como o nome sugere, isso permite que uma classe herde de outra suas características, podendo também
introduzir suas próprias ou alterar as características herdadas. O uso de herança acaba poupando trabalho e
melhorando a organização do código.
Paradigmas da Programação:
Desde o início da programação, já passamos pelos seguintes paradigmas:
• Não estruturada - exemplos: COBOL, FORTRAN, BASIC (anos 50-60)
• Procedimental ou Procedural - exemplos: C, Pascal (anos 70)
• Modular - exemplo: Modula II (anos 80)
• Abstracção de tipos de dados - exemplo: Ada (anos 80)
• Programação Orientada a Objectos - exemplos: C++, Java, Delphi (Object Pascal) entre outras. (décadas
80-90-2000)
Introdução 5
Objetos
Objeto é, genericamente, uma entidade de armazenamento e manipulação de dados. O mesmo deve ser criado para
processar os dados que armazena e recebe, sendo sensível a entradas do programa principal para fornecer as saídas
esperadas pelo mesmo. Por estes motivos o objeto deve ser pensado como uma entidade de dados autônoma,
encarregada de processar todos os dados que mantém.
Da mesma forma que podemos usar tipos de dados nativos da linguagem podemos criar nossos tipos de dados. Na
linguagem C podemos criar tipos de dados compostos que chamamos de estruturas, estes são criados com a palavra
chave struct. C++ possibilita o uso de estruturas de dados e introduz um novo tipo chamado de classe. Como o
nome sugere, uma classe refere-se a um conjunto de características dadas a um grupo de "indivíduos", ou seja, grupo
de objetos. Por este motivo, classe é a definição de tipo de objeto.
Em C++ as classes de objetos são criadas através da palavra chave class. Esta nomenclatura é usada por muitas
outras linguagens de programação mais caracteristicamente restritas a orientação a objetos. Estes aspectos facilitam
um pouco o aprendizado por programadores já familiarizados com estas linguagens quando iniciam a programação
em C++.
O processo de criação de um objeto segue a sequência:
•• Definir os dados e procedimentos que a classe deve conter;
•• Criar a classe de objetos;
•• Declarar (instanciar) o objeto.
A definição de uma classe de objetos deve ser feita de forma a tornar, preferencialmente, todos os dados protegidos
de interferências de códigos externos ao objeto. Por este motivo um objeto deve ser uma parte do código do
programa com uma certa autonomia. Este deve ter controle sobre seus dados e ser capaz de provê-los e lidar com
eventos a eles relacionados. Dentro de seu escopo de responsabilidades, a entidade deve essencialmente "ter vida
própria".
Alô, Mundo! 6
Alô, Mundo!
Olá mundo!
É comum, no aprendizado de uma linguagem de programação, que seu primeiro programa faça com que o
computador exiba "Olá mundo!". Na linguagem C++ este primeiro programa já introduz muitos conceitos sobre a
linguagem. Veja o código do nosso primeiro programa:
#include <iostream>
using namespace std;
int main ()
{
 cout << "Olá mundo!"; 
 return 0;
}
Assim como para começar a dirigir não é necessário saber toda a mecânica do carro, para programar não precisamos
logo de início nos prender a todos os detalhes.
No programa acima, vamos dar atenção apenas ao conteúdo que se encontra entre as chaves:
 {
 cout << "Olá mundo!";
 return 0;
 }
• cout << "Olá mundo!";
A palavra cout vem de Console OUT (saída do console), onde geralmente temos a saída no monitor. O cout é
seguido do operador << e da frase que se quer informar entre aspas: "Olá mundo!", intuitivamente, isso nos leva a
ideia de que a sequência de caracteresserá levada ao cout.
•• return 0;
Este comando termina o programa, o estudaremos melhor no capítulo sobre funções e retornos.
ATENÇÃO:
Caso seu sistema operacional seja o Microsoft Windows, você deve adicionar imediatamente antes de return 0;
a seguinte linha:
•• system ("pause");
A função system() executa um comando do Windows. É como se o próprio usuário digitasse pause no prompt
do MSDOS. Este comando deve ser evitado, pois diminui a portabilidade do programa, já que pause só existe nos
sistemas Microsoft. No entanto, se está usando Windows é necessário adicionar esta linha, caso contrário o
computador escreveria "Olá mundo!" e fecharia o programa antes que pudéssemos ler qualquer coisa. Uma forma
elegante de lidar com estas peculiaridades do Windows é usar predefinições, de forma que o programa seja portável
para qualquer sistema operacional:
#if defined(_MSC_VER)
// estas linhas serão executadas apenas quando o programa
// for compilado por alguma versão do Microsoft Visual C
 system("pause"); 
Alô, Mundo! 7
#endif
Em sistemas parecidos com UNIX, como GNU/Linux ou FreeBSD, pode-se usar um terminal de linha de comando
facilmente, pois os mesmos possuem o recurso facilmente acessível, mesmo quando o usuário está usando a interface
gráfica. Por isso, para esses sistemas um comando para solicitar pausa ao sistema não é necessário.
Entrada de dados e comentários no código
Comentário é um recurso muito útil em programação. Ele permite que o programador adicione texto ao programa
para facilitar o entendimento do programa por parte de outros programadores, ou até dele mesmo. Os comentários
são usados para explicar trechos de código, adicionar cláusulas e qualquer texto em geral.
Vamos agora para um programa mais completo com entrada de dados e comentários dentro do código:
// Este é um comentário de uma linha
/*
 Este é 
 um comentário
 de várias
 linhas 
*/
#include <iostream>
using namespace std;
int main ()
{
 int x;
 cout << "Digite um número: ";
 cin >> x;
 cout << "\nVocê digitou o número: " << x << endl;
 system ("pause"); 
 return 0;
}
Comentários no programa
Observemos esta linha:
 // Este é um comentário de uma linha
Esta é uma linha de comando para o preprocessador (ou precompilador).
O que é o preprocessador? Durante o processo de montagem do programa em formato binário existem três fases
principais: O preprocessamento, a compilação e a fase de ligação (link). O preprocessador é um programa invocado
pelo compilador para remover comentários e substituir certas partes do programa conforme a necessidade do código
criado pelo programador.
O preprocessador faz algumas alterações no texto fonte, que basicamente consistem em eliminar pedaços de código 
e/ou substituí-los por outros (copy-paste). Enfim, o mesmo altera o código fonte contendo comandos iniciados com 
# e outros comandos específicos, por outro código sem comandos de preprocessamento, puramente em linguagem
Alô, Mundo! 8
C++.
Ao analisar o código, o preprocessador encontra a sequência // e vai eliminar o texto que está a seguir até ao fim
da linha.
Mais uma forma de adicionar comentários:
/*
 Este é 
 um comentário
 de várias
 linhas 
*/
A linguagem C++ permite também fazer comentários por mais do que uma linha. Chama-se comentário por bloco e
o que faz é eliminar tudo o que encontrar entre a sequência inicial /* e o final */.
A vantagem de termos esta possibilidade é poder comentar o nosso código. Existem algumas regras de boa conduta
para comentários que foram criadas por pessoas que já têm muito tempo nisto:
•• Uma é criar logo no topo um comentário a dizer o que é o nosso programa, e o que faz numa forma geral;
•• Outra é fazer comentários a cada função que aparece no código a explicar;
•• Outra é comentar uma linha mais obscura, mais difícil de entender, que não é óbvia;
•• A outra é não comentar tudo. O comentar deve ser para sobressair.
Esta última regra pode ser esquecida quando o programa é didático, neste caso pode-se usar o programa como texto
comentado.
Incluindo cabeçalhos
#include <iostream>
O símbolo # é uma chamada de atenção ao compilador a dizer que aquela linha é para o preprocessador, depois
temos o "include" (que basicamente diz para incluir código). Incluir o quê?
Deve incluir o ficheiro/arquivo iostream. (in+out+stream, "fluxo de entrada e saída", padrão) (na maioria das
vezes, como entrada padrão temos o teclado e como saída temos o monitor) (este ficheiro/arquivo contém
declarações das funções e definições que o nosso código fonte irá necessitar)
Este código que será incluído é chamado de cabeçalho devido a uma característica evidente, o fato de ser código de
declaração inicial do programa, que deve estar no topo do arquivo/ficheiro.
Existem outros arquivos (ficheiros cabeçalho), o iostream é para fluxos de entrada e saída, mas temos muitos
mais para matemática, manipulação de tempo, tratamento de caracteres, etc...
Na maioria das vezes, os arquivos de cabeçalho fazem parte de uma biblioteca. Podemos ver na parte dos anexos,
algumas bibliotecas que existem juntamente com as funções de cada uma. Nós próprios podemos criar uma
biblioteca com código e nosso próprio cabeçalho. E até podemos comprar bibliotecas existentes comercialmente,
através de empresas especializadas em desenvolvimento, que também terão seus arquivos/ficheiros de cabeçalhos.
Mas, o que são bibliotecas? São arquivos com um conjunto de códigos que alguém fez antes. As que enunciamos
antes são as "standard", são aquelas que têm as funcionalidades básicas, pertencentes aos padrões da linguagem.
Repare-se que precisamos da biblioteca até para escrever (no ecrã)/(na tela) (stream + out) que nos permite utilizar o
cout.
O ficheiro/arquivo iostream está envolvido em < >, isto significa que o preprocessador deve procurar o
ficheiro/arquivo no sítio/diretório usual (que é onde o compilador usa como padrão para os "includes"). Se
tivéssemos o ficheiro/arquivo iostream envolvido em "" significaria que o preprocessador deveria procurá-lo
dentro de uma lista de diretórios de inclusão, "includes", iniciando pelo diretório atual.
Alô, Mundo! 9
As bibliotecas são compostas por 2 partes: um índice de todas as funções e definições e declarações, o cabeçalho, e
depois a definição de todas as funções existentes no índice, arquivos de código.
As directivas de preprocessamento não terminam com o ponto e vírgula como nas instruções.
Namespace
using namespace std;
Observando esta linha, alguns tradicionais programadores em linguagem C, têm uma novidade: namespaces são
espaços de nomes dentro do código, eles funcionam, entre outras coisas, como um meio de evitar duplicação de
nomes dentro de um projeto extenso, que geralmente contam com inúmeros arquivos.
O C++ usa os namespaces para organizar os diferentes nomes usados nos programas. Cada nome usado no
ficheiro/arquivo biblioteca "standard iostream" faz parte do "namespace" chamado de std.
O objeto de saída padrão, cout, está definido dentro do "namespace" std, ele é um objeto da classe "ostream" "output
stream", para acessá-lo temos que referenciá-lo como "std::cout". Para evitar que tenhamos que informar "std::"
todas as vezes que precisarmos usar os recursos deste "namespace", podemos informar que estamos usando-o dentro
do arquivo atual, conforme vemos na linha declarada no início deste tópico.
O "namespace" permite que as variáveis sejam localizadas em certas regiões do código. Declarar o "namespace std"
permite que todos os objectos e funções da biblioteca "standard input-output" possam ser usados sem qualquer
qualificações específicas, desta maneira, não é mais necessário o uso de "std::".
Este é um conceito avançado que podemos explorar mais, vamos deixá-lo para depois.
Função "main"
int main(){}
Como na linguagemC, a função principal de entrada do programa a partir do sistema operacional é a função main.
Por isso mesmo ela é obrigatória em qualquer programa. Se não existisse uma "main function", não haveria entrada
para que o sistema iniciasse o programa.
Todas as funções são declaradas e usadas com o operador ( ), assim é que o compilador reconhece que estas são
funções. A ideia de ter funções é permitir o encapsulamento de uma ideia ou operação, dar um nome a isso e depois
chamar essa operação de várias partes do programa simplesmente usando o seu nome. As funções declaradas como
membros de uma classe de objetos podem ser chamadas de métodos.
Do ponto de vista funcional, um código dentro de uma função executa operações em outra parte do programa, que
não é aquela de onde foi chamada, por este motivo as mesmas contam com um mecanismo de passagem de dados, ao
declarar uma função indicamos quais os dados que entram e o que ela deve fornecer a quem lhe chamou. Pode-se
dizer que, tal qual uma função matemática, a função em C/C++ poderá ser substituída, depois de sua execução, pelo
valor que ela retorna, este valor será especificado antes do nome da função na declaração da mesma, conforme
vemos no início deste tópico.
O int significa que a função vai retornar um inteiro. Existem outros tipos de dados como, por exemplo, os seguintes:
• int que é a abreviatura de inteiro;
• char que é a abreviatura de caratere;
• float que é a abreviatura de "floating point number", ou seja, uma representação para número real.
Vejamos um exemplo:
Quando criamos uma função soma, obviamente só para ilustração pois isso não é necessário, podemos fazer:
int soma(int a, int b)
{ return a + b;
}
Alô, Mundo! 10
Agora imagine que tenhamos que somar 2 e 3, colocando o resultado em outra variável chamada valor, para isto
faremos:
valor = soma(2, 3);
Primeiro analisamos qual é o resultado e depois substituímos a função pelo valor que ela retorna:
valor = 5;
Simples, não?
; - Final de sequência de instruções
O ponto e vírgula funciona como ponto final, separa as instruções e contextos. Repare que apenas as funções, ou
melhor, as definições de funções e as diretivas de preprocessamento é que não têm o ";"
É importante notar que o código poderia ser todo escrito quase numa linha tipo:
int main (){int a; cout << "Hello world! Digite um número:\n"; cin >> a;cout <<
 "Você digitou o número: " << a<<"\n"; system ("pause"); return 0;}
É realmente o ";" que faz a terminação das instruções.
Ao encontrar as chaves "{}", o compilador reconhece como um delimitador de bloco, ou "body", corpo. O corpo de
uma função ou bloco de código começa com "{" e termina com "}", como temos as instruções agrupadas, já não há
necessidade de colocar o ";" no final para indicar onde é o fim do bloco.
No nosso exemplo existem 2 instruções no corpo da função. As instruções são executadas por ordem: do topo até ao
fim a menos que existam funções que alterem o fluxo da leitura ou que existam códigos de controle de execução
"execution control codes", que alteram o caminho de execução.
Entrada e saída (cin/cout)
cout << "Hello world! Digite um número:\n";
(c+out) Podemos utilizar este objeto porque pusemos o header e o namespace std. As informações serão
direcionadas através do iostream, um subsistema de entrada e saída da biblioteca padrão. O que este objeto nos
permite é enviar o que temos entre aspas para a saída (out), que é o monitor neste caso.
Quem já conhece a linguagem C, certamente está familiarizado com os streams da biblioteca padrão, o stdin, o
stdout e o stderr... A linguagem C++ implementa os mesmos dispositivos sob a forma de objetos.
O cout envia dados para o "standard output device", que é usualmente o monitor, a abstração do elemento de saída
padrão é observada na presença de um objeto que representa a saída física de dados para o meio externo.
Observa-se que temos o operador <<, neste caso podemos verificar mais uma das funcionalidades da linguagem, pois
este operador é usado para deslocamento de bits na sua funcionalidade padrão, neste caso a sua função foi substituída
por outra, transferir os dados a sua direita para o "output stream" do seu lado esquerdo.
O cout é um objeto da biblioteca "standard C++" que tem como uma de suas funções imprimir strings no "standard
output" (que normalmente é o/a ecrã/tela).
Da mesma forma que podemos formatar o texto enviado a saída padrão na linguagem C, também podemos fazê-lo
com os objetos do C++, por exemplo, se acrescentássemos "<< hex <<" entre uma variável e a saída:
cout<< hex << n; 
O resultado seria impresso em hexadecimal;
Para entrada de dados temos:
cin >> a;
Alô, Mundo! 11
O que esta linha faz é colocar o valor que foi digitado numa área de memória que foi chamada de "a".
Da mesma forma que o cout existe para saída de dados, temos outro objeto para entrada através do teclado, este
objeto é chamado de Console IN - cin, seguindo a mesma analogia. Observe que o operador >> é usado para dar
ideia de que os dados estão vindo do cin para a variável "a".
cout << "Você digitou o número: " << a << "\n";
Aqui voltamos a utilizar o objeto cout primeiro para imprimir no/na ecrã/tela a frase "Você digitou o número: ",
depois vai buscar o valor que está naquela área de memória a que chamamos de "a" e por fim coloca o fim de linha
através de "\n", em C++ podemos usar um finalizador de linha chamado endl, o uso do mesmo é mais eficiente pois
descarrega os dados do stream logo após a finalização da linha.
função system("pause")
system ("pause");
A maioria dos compiladores quando estão executando em modo gráfico fecha o console de saída assim que o
programa finaliza. Isto impede que possamos ver o que aconteceu, principalmente quando o programa contém
apenas umas poucas instruções.
A função system(), faz parte do padrão da linguagem C, ela executa uma chamada de sistema, ou seja, ela passa um
comando para o sistema, que neste caso é "pause", como já informamos no início deste capítulo, este comando é
destinado a sistemas da Microsoft®. Coloquei esta linha para que o programa não finalizasse sem que pudéssemos
ver uma janela com o resultado, se não o fizesse a janela abriria e fecharia sem que pudéssemos ver o aconteceu
durante a execução do programa.
Em sistemas como GNU/Linux, FreeBSD, Solaris®, etc... temos acesso a terminais de console e compiladores em
linha de comando, assim basta compilar o programa sem esta linha e depois executá-lo, para ver o resultado.
Retornando valor
return 0
Faz com que a função retorne o valor zero, como esta função é a principal do programa, por onde o sistema
operativo/operacional iniciou a execução do mesmo, este retorno é recebido pelo sistema, é comum que valores
diferentes de zero sejam interpretados como erro do programa.
Esta instrução manda retornar o valor zero para o sistema operativo/operacional (Windows, Unix, ...). Este zero
representa a dizer que o programa finalizou normalmente. Pode acontecer que o programa não finalize como seria de
esperar, ele tem um crash (ou porque ficou com falta de memória.). O sistema operativo/operacional necessita de
lidar com estas terminações anormais de uma forma diferente das normais. Por isso é que o programa diz ao sistema
operativo/operacional que terminou normalmente.
Questão: porque é que o sistema operativo necessita de saber que o programa terminou bem?
Variáveis e constantes 12
Variáveis e constantes
Constantes
Compatível com a linguagem C, o C++ mantém as constantes básicas e introduz algumas novas funcionalidades
possibilitadas pelo modificador const.
O uso do modificador const tem duas funções principais:
1.1. Resguarda da inviolabilidade de valores apontados por ponteiros;
2.2. Auxílio na compreensão das características de funções, durante a implementação.
Simbólicas
Constantes simbólicas podem ser criadas com as diretivas do preprocessador #define. Neste modoos valores, de
fato, não são interpretados imediatamente pelo compilador, antes são identificados e substituidos pelo
preprocessador no estágio anterior à compilação. Por exemplo:
#define BUFFER_LENGTH 2048
...
...
...
char data[BUFFER_LENGTH];
Observe que o valor 2048 será usado logo abaixo no código, depois que o preprocessador substituir a constante
simbólica BUFFER_LENGTH pelo valor que lhe foi atribuído.
Note que as constantes são escritas com todas as letras maiúsculas, isso não é uma regra, mas ajuda a identificar o
que é constante simbólica dentro do programa, sendo adotado pela maioria dos desenvolvedores como uma boa
prática de programação.
Neste caso, podemos definir valores simbólicos compostos, por exemplo:
#define BUFFER_LENGTH 2048
#define N_BUFFERS 100
#define MASTER_LENGTH ( BUFFER_LENGTH * N_BUFFERS )
...
...
...
char screen[MASTER_LENGTH];
Os valores podem ser simbólicos em formato de código, o que permite criar programas com melhor legibilidade.
Para isso podemos colocar expressões com funcionalidades bem definidas substituídas por nomes que as
identifiquem. Por exemplo:
float a[3];
#define PRINT_VECTOR cout << a[0] << " , " << a[1] << " , " << a[2] << endl
...
...
Variáveis e constantes 13
PRINT_VECTOR;
Desta forma, todas as vezes que quisermos mostrar o valor do vetor de três coordenadas podemos usar a constante
PRINT_VECTOR.
Literais
Constantes literais podem ser declaradas da mesma forma que na linguagem "C", ou seja, podemos definir valores
fixos em qualquer parte do programa, expressando-os diretamente no código através de seu valor significativo. Por
exemplo, podemos definir números:
256 //decimal
0400 //octal
0x100 //hexadecimal
Também podemos definir valores para caracteres ou cadeias de caracteres, como segue:
'a' // um caractere
"abc" // uma cadeia de caracteres
"\xF3\x23\x12" // uma cadeia de caracteres representada por seus 
valores em hexadecimal
Temos ainda a possibilidade de declarar constantes compostas por valores e operadores:
(4.23e14 * (12.75 + 12976.18/36)) // constante composta
Enumerações
Valores enumerados são muito recorrentes nos ambientes de programação, por isso podemos contar com a
declaração de enum em C++ também, o que segue a mesma sintaxe que temos em "C":
enum seq {A,B,C,D};
seq x;
ou ainda:
enum nomes {LANY=100,SANDRA=200,MARCIA=300,RODRIGO=400};
nomes x;
Porém, observamos uma diferença: a palavra enum pode ser dispensada na declaração da variável, enquanto que em
C é obrigatório,apesar desta pequena diferença a funcionalidade do recurso é a mesma, ou seja, pode-se definir
variáveis que assumem estritamente os valores presentes na declaração de enumeração.
Este recurso torna-se útil na padronização de valores a serem usados como entrada de funções, por exemplo. Pode
ser considerada como uma funcionalidade mnemônica, seu uso não altera o código final caso modifiquemos o
programa para que use variáveis inteiras ou strings de mesmo valor do enum.
A seguinte sintaxe:
seq x = 3;
Não é permitida, mesmo que o valor presente no enum seja avaliado como 3 pelo compilador em tempo de 
compilação. Isso pode parecer confuso, mas lembre-se de que os valores serão atribuidos pelo compilador, logo isso
Variáveis e constantes 14
evita que o mesmo programa seja compilado em ambientes diferentes e tenha comportamento diferente.
Variáveis
As variáveis no C++ podem ser usadas da mesma forma que na linguagem "C", porém algumas poucas diferenças
podem ser destacadas, principalmente aquelas que trazem à linguagem C++ características próprias da orientação a
objetos.
Tipos
Como na linguagem "C", os tipos nativos do compilador em uso são referenciados por:
 char
 int
 float
 double
Que correspondem a números com tamanho relativos, com os significados respectivos: caractere, inteiro, ponto
flutuante e ponto flutuante de dupla precisão. De qualquer forma a extensão dos mesmos depende da máquina que se
pretende programar. Considerando que nem sempre teremos que programar apenas computadores, poderemos ter
extensões bem distintas dependendo do hardware a ser programado, por exemplo, computadores domésticos
tipicamente tem processadores de 32 ou 64 bits hoje em dia, enquanto que dispositivos embarcados podem ter
processadores de 8, 16 ou 32 bits. Portanto, o compilador para cada caso atribui faixas diferentes para cada tipo em
cada situação.
A linguagem C++ introduz o tipo bool, que representa o valor booleano, falso ou verdadeiro, o que não existe na
linguagem "C", porém seu tamanho na memória depende da capacidade de otimização do compilador usado.
Tipicamente os compiladores para computadores usam uma variável do tamanho de char para representar o valor, o
que poderia ser considerado um desperdício, mas devido à abundância de memória não chega a ser inadequado.
Porém em sistemas pequenos há compiladores que armazenam o valor booleano em apenas um bit. Obviamente, se o
processador possuir recursos de manipulação de bits isso é muito útil e pode ser usado como um fator de melhoria da
qualidade do software desenvolvido. Em outros ambientes, onde a manipulação de bits traga prejuízo para o
desempenho usa-se a estratégia padrão de desperdiçar um pouco de espaço em favor de uma agilidade maior nas
operações. Portanto, embora as variações de utilização do espaço sejam muitas, o compilador sempre fará a mais
apropriada para cada ambiente de utilização da linguagem.
Modificadores
O C++ conta com os modificadores de amplitude (short,long) presentes na linguagem "C" e modificadores de
acesso, alguns exclusivos do C++, que estão diretamente ligados a características da POO (programação orientada a
objetos). Desta forma descreveremos apenas os tipos relevantes exclusivamente para a programação na linguagem
escopo do livro presente sem nos aprofundarmos na teoria por trás dos mesmos. A prática do uso dos mesmos é
melhor indicada como meio de aprofundamento do tema.
Assim contamos com os modificadores da linguagem "C":
static
short
long
unsigned 
signed
Variáveis e constantes 15
const
A linguagem C++ introduz um novo modificador chamado const, que tem comportamento variado dependendo do
local onde está sendo declarado. Sua função, basicamente, é estabelecer um vínculo entre declaração e
obrigatoriedade da coerência no uso do símbolo declarado.
A princípio, quando declaramos uma constante com este modificador fazemos com que seja obrigatório o uso do
símbolo de forma que o mesmo não possa ter seu valor alterado. Assim, se fizermos:
const int x = 4;
O inteiro x não poderá deixar de ter valor igual a 4. Qualquer tentativa de modificar o valor da constante ao longo do
programa será reportada como erro pelo compilador. Porém podemos considerar esta funcionalidade como óbvia e
trivial, ainda temos o uso do modificador de uma forma mais proveitosa, na passagem de parâmetros para funções,
por exemplo:
void inhibitX(const int *x)
{
...
...
 BASEADDRESS = z*((*x) - 23p*71);
...
...
}
Neste caso, a função acima recebe um valor inteiro através de um ponteiro, que não obrigatoriamente precisa ser
constante no escopo fora da função, porém dentro da mesma a variável será constante. Fazendo este simples
procedimento teremos como fazer com que um símbolo seja variável fora da função e constante dentro da mesma, de
forma que dentro do escopo da mesma só façamos leituras do seu valor. O artifício cria duas consequëncias
importantes: a primeira é a melhor legibilidade do código, visto que ao usarmos uma função teremos certeza de que
os valores não serão alterados dentro da função; a segunda é que poderemos evitar erros inadvertidos de atribuição
de valores à variável quando da construção da função.
volatile
Uma variável "volátil", como a própria expressão sugere, é uma variável que pode ser modificadasem o
conhecimento do programa principal, mesmo que esta ainda esteja declarada dentro do escopo onde o programa está
sendo executado. Isso está relacionado, principalmente a processos concorrentes e "threads", estes podem alterar o
conteúdo da variável em eventos fora da previsibilidade do tempo de compilação. Em outras palavras, o compilador
não pode prever com segurança se pode otimizar trechos de programa onde esta variável se encontra.
A palavra reservada volatile é destinada as situações onde uma variável pode ter seu valor alterado por fatores
diversos, e portanto, não pode ser otimizada. Usando-a o programador informa ao compilador que não deve interferir
na forma com que o programa foi escrito para acesso a esta variável. Desta forma impede que erros inseridos por
otimização estejam presentes na versão final do executável.
O uso desta palavra implica em mudança no comportamento do compilador durante a interpretação do código. As
classes de objetos do tipo voláteis só poderão ser acessadas por rotinas que declarem aceitar como entrada dados
voláteis, da mesma forma que apenas objetos voláteis podem acessar variáveis voláteis. Esta "amarração" faz com
que o uso de tais variáveis se torne mais seguro.
Podemos declarar variáveis voláteis da seguinte forma:
volatile int x;
Variáveis e constantes 16
Enquanto que para funções que acessam tais variáveis teremos consequências visíveis na montagem do código, por
exemplo, se tivermos o seguinte trecho de programa:
int x = 1265;
void main_loop()
{
 while( x == 1265)
 {
 // fazer alguma coisa
 }
}
Poderemos ter uma otimização gerada pelo compilador como segue:
int x = 1265;
void main_loop_optimized()
{
 while( true )
 {
 // fazer alguma coisa
 }
}
Considerando que em um programa que foi desenhado para ambiente multitarefa isso não pode ser considerado
verdadeiro, pois o programa pode estar esperando que uma das tarefas modifique o estado da variável para
prosseguir seu curso, a otimização acima será um desastre, uma vez que a função acima jamais será encerrada.
Para evitar isso fazemos:
volatile int x = 1265;
void main_loop()
{
 while( x == 1265)
 {
 // fazer alguma coisa
 }
}
E o compilador não poderá mais avaliar que o valor de x pode ser otimizado para o valor corrente, pois informamos
na declaração que o valor da variável pode ser alterado sem seu conhecimento. Desta forma o mesmo não alterará o
algorítmo e fará o teste da variável dentro do while.
Variáveis e constantes 17
Nomeando tipos
A linguagem "C" possui recursos de nomeação de tipos simples e compostos através das palavras chaves typedef e
struct. Adicionada a estas o C++ acrescenta a palavra chave class. Vejamos como devemos definir um novo tipo
através desta palavra chave.
A palavra class atribui a um conjunto de tipos de dados o estado de modelo de objeto. Este conceito é fundamental
para o modo avançado de programar usando o C++. Com este identificador declaramos objetos, da mesma forma que
declaramos estruturas.
Uma classe pode ser definida em um cabeçalho "header", da seguinte forma:
class nome_da_classe
{ <tipo_1> variavel_1;
 <tipo_2> variavel_2;
 .
 .
 .
 <tipo_n> variavel_n;
 -----
 <tipo_n> nome_funcao ( <tipo_1> variavel_1, <tipo_2> variavel_2, <tipo_3> variavel_3 ...);
};
O mais interessante de observar é a presença de uma função dentro da declaração acima. Então poderíamos
perguntar: Por que colocar uma função dentro de um tipo? A resposta é simples: Para manipular os dados dentro do
tipo! Não apenas por esta característica, mas por várias outras que aboradaremos nos capítulos seguintes, o tipo class
é extremamente flexível e poderoso.
É importante ressaltar que em C++ a declaração do identificador: enum, struct, class, etc... é dispensado quando se
declara uma variável ou objeto para o referido tipo. Desta forma podemos ter também as seguintes declarações como
válidas, além do uso padrão da linguagem "C":
struct data{ int a; 
 int b; 
 int c; 
 };
class object{ int a;
 char b; 
 long w;
 float p;
 void getData();
 };
...
...
...
...
void func()
{ data x;
 object y;
Variáveis e constantes 18
 ...
 ...
 y.getData();
}
Como podemos ver na função acima se a variável x for declarada para uma estrutura data o uso da palavra struct
não é obrigatório, assim como também não o é para outros tipos de dados compostos.
Ponteiros
Ponteiros
Em linguagem "C", podemos definir variáveis ponteiro, ou seja, variáveis que armazenam o endereço de outras
variáveis. Este recurso é largamente explorado pela linguagem, embora que deva ser usado com cautela por
iniciantes devido ao seu poder destrutivo. Como linguagem "irmã mais nova" o C++ também permite o uso de
ponteiros, o que a distingue de muitas outras linguagens orientadas a objeto. Embora seja muito difundida a idéia da
criação de linguagens que não suportem acesso a ponteiros, basicamente pressupondo que todos os programadores
são inexperientes, a falta deste recurso limita as capacidades de interação de programas com o hardware. Em outras
palavras, a falta de um meio de manipular ponteiros faz a linguagem limitada ou dependente de fabricantes de
bibliotecas que acessem o hardware.
A disponibilidade do uso de ponteiros em C++ agrega um poder a mais ao conjunto da linguagem, porém implica em
necessidade de cautela na elaboração de programas que usam deste recurso. Certamente, nem todos os
programadores precisam ser considerados inaptos, a priori, através da supressão ou inserção de complicadores de
recursos criados explicitamente para forçá-los a não usar dos recursos. Por isso, a linguagem C++ disponibiliza o
recurso para quem deseja utilizá-lo e também apresenta diversos outros recursos que são alternativas ao uso de
ponteiros quando eles não são imprescindíveis.
O operador *
O operador *, chamado de apontador, funciona em C++ da mesma forma que em C. Considerando que tenhamos
uma variável ponteiro p:
• Em p armazena-se o endereço de memória que queiramos manipular. Na maioria das vezes obtemos o endereço
de outra variável e colocamos em p;
• Se p é um ponteiro, *p é o valor apontado por p, ou seja, o valor que está armazenado no endereço de memória
que queremos ler ou alterar.
Na declaração de variáveis, uma variável declarada com * é um ponteiro.
Exemplo:
 int *px;
Muitas vezes, iniciantes podem se sentir confusos porque quando declaramos um ponteiro usamos o * e quando
atribuímos endereços a ele não usamos o *. A conceituação básica é a seguinte:
• Declaramos o ponteiro com *, para que o compilador identifique que a variável é um ponteiro;
• Usamos o ponteiro sem *, para acessar o endereço que ele aponta na memória;
• Usamos o ponteiro com *, para acessar o valor do dado armazenado na posição de memória;
Ponteiros 19
O operador &
Na linguagem "C", o operador & tem duas funções básicas, funciona como operador da função lógica AND e como
operador de leitura de endereços. Para operações com vetores, isso é usado da seguinte forma:
 int a = 12;
 int *pa;
 ...
 ...
 pa = &a;
 ...
 ...
 *pa = 100;
Ou seja, declaramos a variável a, depois declaramos um ponteiro pa, através do operador & obtemos o endereço de a
e atribuímos o valor 100 à variável usando o ponteiro ao invés da variável a. Desta forma alteramos o valor de a
indiretamente.
Um outro uso de & (que não tem similar em "C") pode ser visto mais adiante, em ../Referências de dados/, mas, para
isto, é necessário estudar o que são ../Funções/.
O ponteiro "this"
Imagine que tenhamos criado um objeto qualquer de uma classe X, se quisermos ter acesso ao ponteiro que contém a
posição de memóriaonde está armazenado este objeto basta chamar o ponteiro "this". O ponteiro "this" é uma das
características dos objetos em C++ e algumas outras linguagens que suportam orientação a objetos. Ele é um
membro inerente a todos os objetos que instanciamos em programas escritos em C++.
Faremos uma breve explanação a respeito de objetos para esclarecer este tópico. Objeto são parecidos com
estruturas, uma diferença básica é que estes possuem "habilidades específicas" representadas por funções que estão
dentro do seu escopo. Vejamos um exemplo:
struct Data
{ int x,y;
 int get_x(){ return x;}
 int get_y(){ return y;}
 int set_x(int a){ return x=a;}
 int set_y(int b){ return y=b;}
};
Observe que a estrutura acima apresenta dois inteiros e duas funções para cada um deles, uma que atribui o valor e
outra que lê o valor de uma das mesmas. Detalhes das implicações a respeito desse modo de operar os valores serão
dados nos capítulos seguintes que tratam de objetos. Por ora vamos nos ater a um conceito fundamental importante
para a noção de ponteiros em C++, a identidade de um objeto.
Veja, temos uma estrutura de dados que está na memória, os dados estão lá (variáveis x e y), porém as funções não
estarão lá, pois se tivéssemos que copiar uma função para cada estrutura que criássemos o programa tomaria um
tamanho monstruoso. O que se faz é apenas guardar o endereço da estrutura em um ponteiro especial, o ponteiro
this. Assim, o compilador poderá criar uma única cópia de função para todas as estruturas que criarmos e depois
quando a função quiser manipular os dados de uma estrutura em particular, o fará através do ponteiro this.
Examinemos os detalhes mais de perto... Digamos que instanciemos um objeto "A" da classe Data:
Ponteiros 20
 Data A;
 A.set_x(2);
 A.set_y(7);
Para acessar estas funções o compilador fará:
 Data A;
 A.set_x(2);
// { Data *this = &A;
// return this->x = 2;
// }
 A.set_y(7);
// { Data *this = &A;
// return this->y = 7;
// }
Desta forma podemos perceber como diferentes conjuntos de dados podem ser manipulados pela mesma função.
Quando declaramos uma função dentro de uma estrutura de dados esta rotina recebe um ponteiro com o endereço do
conjunto de dados que deve tratar toda vez que for invocada pelo programa. Assim, sempre acessará os dados através
deste ponteiro, o this. Como todos os objetos precisam ser identificados por esse ponteiro, ele é definido para
qualquer objeto com o mesmo nome: this.
Vetores
Vetores e Matrizes
Façamos uma pequena revisão de conceitos:
•• Vetores e matrizes são variáveis compostas homogêneas, ou seja, são agrupamentos de dados que
individualmente ocupam o mesmo tamanho na memória e são referenciados pelo mesmo nome, geralmente são
individualizadas usando-se índices.
•• Vetores distinguem-se das matrizes apenas pela característica de ter dimensão (1 x n) ou (n x 1), essencialmente
vetores são matrizes linha ou matrizes coluna.
Em linguagem "C" vetores e matrizes são usados abundantemente para compor estruturas de dados necessárias para
composição de diversos recursos. Esta usa, mais explicitamente, vetores de caracteres para definir cadeias de texto, o
que é conhecido como o mais trivial uso de vetores. Além deste recurso, o "C" também define meio de criação de
matrizes tipo (n x m), provendo, desta forma os recursos necessários para criação destes conjuntos de dados.
A linguagem "C++" suporta os mesmos recursos e permite a criação de matrizes de objetos. Uma vez que um objeto
é essencialmente um tipo de dado criado pelo programador, todas as características básicas legadas aos "tipos" em
geral são observados nos tipos criados (classes de objetos).
Vetores 21
Vetores
Os vetores em C++ seguem a mesma notação da linguagem "C", via de regra declara-se o tipo seguido de um
asterisco. Para acessar o valor apontado pela variável usa-se um asterisco de forma semelhante, como pode ser visto
no trecho de código abaixo:
int *x;
int a = 3;
x = &a;
cout <<" O valor do conteúdo da posição 0x"; // O valor da posição 0x23A0209112 
cout << hex << x << "de memória é " << *x << endl; // de memória é 3
Matrizes
Podemos imaginar que uma matriz é um conjunto de vetores que ocupam uma determinada área de memória
referenciada por um nome comum. Matrizes de tipos primitivos são conseguidas através de associações do operador
[ ], como por exemplo:
char A[32][16];
int B[12][26][10];
Definindo nossas classes de objetos poderemos declarar matrizes de objetos:
class Record
{ int D;
 float X,Y;
 char desc[12];
 public:
 Record();
 void addFData(float A, float B);
 float getFDataX();
 float getFDataY();
 ...
 ...
 ...
};
void function()
{
 Record A[32][16];
 ...
 ...
 ...
Ou seja, podemos adotar a mesma sintaxe para criar matrizes de objetos. Este procedimento pode ser usado com o
cuidado de se avaliar antes a quantidade de memória disponível para que a matriz não ultrapasse esse limite físico,
muitas vezes delimitada pelo hardware ou pelo sistema operacional. Lembremos que, um objeto precisa do espaço
Vetores 22
equivalente a soma de suas variáveis internas para ser alocado na memória.
Declarando arranjo
Os arrays permitem fazer o seguinte:
int a1, a2, a3,….a100; é equivalente a ter int a[100];
Ou seja permite declarar muitas variáveis de uma forma bem simples, poupa escrita e é bastante compreensível.
• O número que está dentro de brackets [] é o size declarator. Ele é que vai permitir ao computador dizer quantas
variáveis a serem geradas e logo quanta memória deverá ser reservada. A memória reservada para as variáveis
vão ser todas seguidas, um int a seguir ao outro
•• Há uma forma para não dizer o valor deste size declarator, mas isso apenas acontece antes da compilação, ou seja
o compilador é que vai fazer esse preenchimento por nós, visualizando o nosso código e contanto os membros que
colocámos. Isto é um automatismo dos compiladores recentes. chama-se a isto iniciação implícita que vamos ver
nesta secção.
•• As variáveis geradas pelos arrays vão ser todos do mesmo tipo.
•• Reparem que o valor do size declarator é um número. É literal, ele não vai mudar quando o programa estiver a
correr. Por isso quando não soubermos o número de elementos o que fazemos?
Veja uma tentativa:
 #include <iostream>
 using namespace std;
 int main ()
 {
 int numTests;
 cout << "Enter the number of test scores:";
 cin >> numTests;
 int testScore[numTests];
 system (“pause”);
 return 0;
 }
Isto vai dar um erro de compilação, porque o array está a espera de uma constante e não uma variável. Há uma
maneira de contornar isto que é através da memória dinâmica que vamos dar mais tarde, num capitulo próprio, pois
isto vai envolver muitos conceitos.
Constantes
Reparem que há uma diferença entre literais e constantes, apesar de em ambos os casos o valor não é alterado
durante a execução do programa, a constant é um nome que representa o valor, o literal é o valor.
Declarar constantes
É exatamente como declarar uma variável com duas diferenças:
1.1. A declaração começa com a palavra const. Isto vai dizer ao compilador que é uma constante e não uma variável
2.2. Teremos de atribuir logo o valor na declaração, ou seja, é fazer a iniciação
Exemplo:
const int numTests = 3;
Vetores 23
Portanto se tentarmos colocar um outro valor ao numTest, isso vai dar um erro de compilação
Array index
a[100] é composto por a[0], a[1],… a[99]
Pergunta: Porque é que o índex começa em zero e não um? Ou seja temos as 100 posições que pedimos mas o índex
começa no zero e não no 1. A razão disto tem a ver com offset – que refere ao valor adicionado para o endereço base
para produzir a segunda address. Bem não entendi bem! Eu explico de novo: O endereço (address)do primeiro
elemento do array, é o mesmo do que o endereço base do próprio array. ah espera aí, o que estão a dizer é que o
endereço do array é igual ao do primeiro elemento do array. Assim o valor que teria de ser adicionado, ao endereço
base do array, para conseguirmos o endereço do primeiro elemento seria zero. Agora sim, percebi!
Erro: Um erro comum é esquecer que o index começa no zero, e portanto quando se querem referir ao último
elemento, esquecem-se que têm de subtrair uma unidade. O que advém desse esquecimento é que podem estar a
alterar memória pertencente a uma variável, instrução,..de um outro programa. – Ou seja vai existir violação de
dados.
Se o array for declarado globalmente em vez de ser localmente, então cada elemento é inicializado ao valor defaut
que é zero.
Iniciação
Iniciação, se bem se recordam é atribuir um valor a uma variável ao mesmo tempo que declaramos a variável.
Podemos fazer a iniciação de um array de 2 maneiras:
1) explicit array sizing
int testScore[3] = { 74, 87, 91 };
float milesPerGallon[4] = { 44.4, 22.3, 11.6, 33.3};
char grades[5] = {'A', 'B', 'C', 'D', 'F' };
string days[7] = {"Sunday", "Monday", "Tuesday", "Wednesday","Thursday", "Friday", "Saturday"};
Pergunta: O que é que acontece se dermos mais valores de atribuição do que elementos do array?
int a[3] = { 74, 87, 91, 45 };
Isto vai dar um erro de compilação “too many initializers”
Pergunta: O que é que acontece se tivermos menos valores do que os elementos
int a[3] = { 74 };
Não acontece nada simplesmente não temos valores para a[1] e a[2]. Porém em alguns compiladores os elementos
não inicializados ficam com os valores defaut, que no caso dos ints é 0 no caso dos floats é 0.0 e nos caracteres é o
caractere nulo ("\0"). No entanto se não inicializarmos um dos elementos, os restantes elementos terão de ser não
inicializados pois caso contrário teremos um erro de compilação
2) implicit array sizing
int testScore[ ] = { 74, 87, 91 };
float milesPerGallon[ ] = { 44.4, 22.3, 11.6, 33.3};
char grades[ ] = {'A', 'B', 'C', 'D', 'F' };
Aqui o compilador faz o trabalho por nós, conta os elementos e preenche o número de elementos
Vetores 24
Caracter array
char name[ ] = {'J', 'e', 'f', 'f', '\0' };
char name[ ] = "Jeff";
Ambas as inicializações são permitidas. Porém tomar atenção á ultima iniciação! Quando colocámos as aspas duplas
o compilador acrescenta o "\0" na array que cria! Não tem []!! Esta até costuma ser a preferida pelos programadores,
é ao estilo de strings (Na verdade as strings são arrays de char mas vamos falar disso num capitulo próprio)
O char "\0" é o escape sequence para caracterer null. Este escape sequence sinaliza ao cout o fim do character array.
É o último elemento do array preenchido! Se não tivéssemos este carácter apareceriam estranhos caracteres a seguir
ao "jeff", chamados "caracteres-lixo". (porquê?) Isto não significa que o último elemento deva ser sempre o null
carácter
Arrays de várias dimensões
Podemos ter duas dimensões
tipo_da_variável nome_da_variável [altura][largura];
como também poderíamos ter infinitas
tipo_da_variável nome_da_variável [tam1][tam2] ... [tamN];
Iniciando
float vect [6] = { 1.3, 4.5, 2.7, 4.1, 0.0, 100.1 };
int matrx [3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
char str [10] = { 'J', 'o', 'a', 'o', '\0' };
char str [10] = "Joao";
char str_vect [3][10] = { "Joao", "Maria", "Jose" };
Peguemos no exemplo:
int a [2][3]={1,2,3,4,5,6,}
Na memória teríamos as coisas assim. ou seja os elementos são seguidos e do mesmo tipo
a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
1 2 3 4 5 6
Portanto ter int a [2][3] é equivalente a ter int a [6] o nome que se dá é que é diferente.
Pergunta: será pedido espaço par 6 ints ou antes um espaço com o tamanho de 6 ints? Como nós sabemos que os
arrays os elementos têm endereços de memoria consecutivos, por isso, não podem ser pedidos 6 ints, pois se fosse
esse o caso, poderia acontecer que eles não ficassem juntos.
Vetores 25
Const Constant arrays
const int daysInMonth [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
Recordar que temos de inicializar quando queremos fazer uma constante array
Atribuir valores ao array
#include <iostream>
using namespace std;
int main ()
{
 int testScore[3];
 cout << "Enter test score #1: ";
 cin >> testScore[0];
 cout << "Enter test score #2: ";
 cin >> testScore[1];
 cout << "Enter test score #3: ";
 cin >> testScore[2];
 cout << "Test score #1: " << testScore[0] << endl;
 cout << "Test score #2: " << testScore[1] << endl;
 cout << "Test score #3: " << testScore[2] << endl;
 system (“pause”);
 return 0;
}
Podemos atribuir o valor 1 a 1, mas para poupar escrita de programação é melhor utilizar as funções anteriormente
revistas como o for
#include <iostream>
using namespace std;
int main ()
{
 int testScore[3];
 for (int i = 0; i < 3; i++)
 {
 cout << "Enter test score #" << i + 1 << ": ";
 cin >> testScore[i];
 }
 for (i = 0; i < 3; i++)
 {
 cout << "Test score #" << i + 1 << ": " << testScore[i] << endl;
 }
 system (“pause”);
 return 0;
}
Ou melhor ainda podemos usar uma constante, para tornar o nosso código mais abstracto.
#include <iostream>
using namespace std;
Vetores 26
const int MAX = 3;
int main ()
{
 int testScore[MAX];
 for (int i = 0; i < MAX; i++)
 {
 cout << "Enter test score #" << i + 1 << ": ";
 cin >> testScore[i];
 }
 for (i = 0; i < MAX; i++)
 {
 cout << "Test score #" << i + 1 << ": " << testScore[i] << endl;
 }
 system (“pause”);
 return 0;
}
Lembram-se da história de termos o endereço do array igual ao endereço do 1º elemento do array?
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
 int testScore[3] = { 74, 87, 91 };
 cout << testScore[0] <<"\n";
 cout << testScore <<"\n"; //array base e não um elemento particular do array
 system ("pause");
 return 0;
}
Pois bem vemos que quando mandamos imprimir o array, ele dá um endereço. Pois o valor do nome do array é o
endereço do array.
Arrays como statements de funções
Pegando no programa
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
{
 int testScore[MAX];
 for (int i = 0; i < MAX; i++)
 {
 cout << "Enter test score #" << i + 1 << ": ";
 cin >> testScore[i];
 }
 for (i = 0; i < MAX; i++)
Vetores 27
 {
 cout << "Test score #" << i + 1 << ": " << testScore[i] << endl;
 }
 system ("pause");
 return 0;
}
Vamos torná-lo mais modular, escrevendo uma função para atribuir valores ao array e outa função para mostrar os
valores do array
#include <iostream>
using namespace std;
void assignValues(int[], int);
void displayValues(int[], int);
const int MAX = 3;
int main ()
{
 int testScore[MAX];
 assignValues(testScore, MAX);
 displayValues(testScore, MAX); 
 system ("pause");
 return 0;
}
void assignValues(int tests[], int num)
{
 for (int i = 0; i < num; i++)
 {
 cout << "Enter test score #" << i + 1 << ": ";
 cin >> tests[i];
 }
}
void displayValues(int scores[], int elems)
{
for (int i = 0; i < elems; i++)
 {
 cout << "Test score #" << i + 1 << ": "<< scores[i] << endl;
 }
}
Arrays como argumentos de funções
// arrays as parameters
#include <iostream>
using namespace std;
void printarray (int array[], int length) /*função com 2 argumentos,um deles é um array */
{
 for (int n=0; n<length; n++)
 cout << array[n] << " ";
 cout << "\n";
Vetores 28
}
intmain ()
{
 int a[] = {5, 10, 15};
 printarray (a,3); //passo array como argumento
 system (“pause”);
 return 0;
}
Este exemplo por acaso está muito curioso
Pergunta: mas agora deveríamos perguntar se neste caso tínhamos uma passagem por valor ou referência.
Quando um array é passado para uma função, a função recebe não a cópia do array mas invés disso o endereço,
address do primeiro elemento do array, que é igual ao valor do array (base).
Assim todas as modificações que se efectuarem na função que foi chamada irão repercutir-se no array passado.
Vamos confirmar:
 #include <iostream>
 using namespace std;
 void doubleThem(int a[], int size);
 int main()
 {
 int a;
 int myInts[10] = {1,2,3,4,5,6,7,8,9,10};
 doubleThem(myInts, 10); //passei o array base
 for (a=0; a<10; a++)
 {
 cout << myInts[a] <<”\t”;
 }
 system (“pause”);
 return 0;
 }
 void doubleThem(int a[], int size)
 {
 int i;
 for (i = 0; i < size; i++)
 {
 a[i] = 2 * a[i];
 }
 }
Estruturas 29
Estruturas
Breve revisão
Conceito
Da linguagem "C" também temos o conceito de estrutura, do qual faremos uma pequena revisão agora. Como todos
sabemos, nem todos os dados que precisamos usar podem ser agrupados em matrizes. Frequentemente usamos dados
de diversos tipos diferentes, com tamanhos diferentes. Para tipos de dados de diferentes tamanhos existem estruturas
de armazenamento de dados heterogêneos.
O especificador struct é usado para esta finalidade. Com ele podemos criar tipos que armazenam dados compostos
por agrupamentos de outros tipos primitivos da linguagem. Geralmente, os dados são armazenados de forma a
facilitar a identificação de cada campo de dados que pretende-se manter, para isso usamos nomes para cada campo
dentro da estrutura de dados, de forma a ter um meio de acessá-la depois.
Estruturas são blocos básicos de informação e são manipulados de maneira primitiva. Basicamente o compilador
instrui a montagem de um código que manipula-as de forma a copiar, referenciar e obter posição na memória. Todas
as outras formas de tratar os dados devem ser providas pelo código do programa.
Implementação
Para criar um tipo de dados composto heterogêneo, basicamente, cria-se uma lista de tipos e nomes de variáveis
separadas por ponto e vírgula. Podemos imaginar esta lista como um bloco de código, em linguagem C, onde estão
presentes apenas as declarações de variáveis. Para isso temos a seguinte sintaxe:
struct Estrutura
{
 <Tipo A> NomeVariavelA;
 <Tipo A> NomeVariavelA2;
 <Tipo A> NomeVariavelA3;
 <Tipo B> NomeVariavelB;
 <Tipo C> NomeVariavelC;
 <Tipo D> NomeVariavelD;
 ...
 ...
 <Tipo Z> NomeVariavelZ;
} [<NomeVariavelComposta>];
O nome da variável composta pode ser omitido na declaração da estrutura e depois definido onde for mais
apropriado, geralmente, dentro de algum bloco de código onde venha a ser usado. Podemos ver logo abaixo, o
exemplo de uma declaração de estrutura:
struct Estrutura
{
 int Inteiro;
 double PontoFlutuante;
 char Caracteres[10];
};
Estruturas 30
int main()
{
 Estrutura MinhaVariavelComposta;
 ...
 ...
 ...
 return 0;
}
Acessando dados internos
O modo de acesso a variáveis internas de uma estrutura é feito através do operador ponto ".", porém, quando usamos
ponteiros para guardar o endereço de uma estrutura usamos o operador seta "->". Vejamos um pequeno trecho de
código:
 Estrutura st;
 Estrutura *pst;
 
 st.Inteiro = 200;
 pst = &st;
 
 pst->PontoFlutuante = 23.976;
Estruturas em C++
As estruturas em C++ funcionam de modo análogo ao apresentado em linguagem "C". A diferença, a princípio,
notável entre elas nas duas linguagens é que em "C++" o especificador struct não precisa ser escrito quando criamos
a estrutura:
Em C, para criar uma estrutura de dados chamada st, declaramos:
 struct Estrutura st;
Para fazer o mesmo em C++, declaramos:
 Estrutura st;
Este simples detalhe revela uma característica importante das estruturas em C++: Nesta linguagem as estruturas são
tratadas como tipos primitivos de objetos. Elas têm características semelhantes às classes, que veremos nos capítulos
subsequentes.
As estruturas em C++ também podem conter funções além de dados. Este fato vem da ideia de modelo de objeto que
as estruturas mantém nesta linguagem. Objetos devem ter propriedades (variáveis) e métodos (funções membro), por
isso temos a possibilidade de criar funções dentro do corpo das estruturas, com a finalidade de lidar com os dados
que elas mantém.
Estruturas 31
Construtores
Os construtores são funções que são criadas automaticamente sempre que tentamos criar um objeto. Eles funcionam
da mesma maneira que construtores de classe. A esses que são criados automaticamente são os chamados de defaut.
Se escrevermos o código:
#include <iostream>
#include <string>
using namespace std;
const int MAX = 3;
 struct Person 
 {
 string name; 
 int height;
 };
 int main ()
 {
 Person p1;
 cout << "The person's name is " << p1.name << " and height is " << p1.height << endl;
 system (“pause”); 
 return 0;
 }
O resultado é:
The person's name is and height is -858993460
Aqui é criado um defaut constructor no momento em que criamos a instância p1 ie com a linha Person p1;
Como as variáveis membro não foram iniciadas, o valor de name está vazio e o na variável height está um valor
qualquer – que é lixo!
Constructor sem argumentos
Podemos ter um construtor sem argumentos que ao contrário do defaut constructor designa valores defaut às
variáveis membro.
 struct Person 
 {
 string name; 
 int height;
 Person() //construtor sem argumentos
 {
 name = "No name assigned";
 height = -1;
 }
 };
•• O nome do construtor é sempre igual ao nome da estrutura, sem exceção.
•• O construtor não retorna qualquer valor, sem exceção
Refazendo o nosso exemplo
Estruturas 32
 #include <iostream>
 #include <string>
 using namespace std;
 const int MAX = 3;
 struct Person {
 string name;
 int height;
 Person()
 {
 name = "No name assigned";
 height = -1;
 }
 };
 int main ()
 {
 Person p1; 
 cout << "The person's name is "<< p1.name << " and height is " << p1.height << endl;
 system (“pause”);
 return 0;
 } 
Repare que demos valores defaut ás variáveis. Agora não estamos no caso de ter p1.name=??? Por mais instâncias
que criemos eles vão ter sempre valores padrão.
Constructor com argumentos
Termos um constructor sem argumentos é um melhoramento face ao defaut constructor pois agora temos valores
defaut para as variáveis membro. Porém seria melhor se conseguíssemos inicializar as variáveis membro com
valores dados pelo utilizador enquanto o programa estivesse e a correr. E realmente podemos fazer se passarmos
argumentos.
 #include <iostream>
 #include <string>
 using namespace std;
 const int MAX = 3;
 
 struct Person 
 {
 string name;
 int height;
 Person() //constructor sem argumentos
 {
 name = "No name assigned";
 height = -1;
 }
 Person(string s, int h) //constructor com 2 argumentos
 {
 name = s;
 height = h;
 }
Estruturas 33
 }; 
 
 int main ()
 {
 int metro;
 string strName;
 cout << "Entre com o nome da pessoa: ";
 getline(cin, strName);
 cout << "Enter height in metro: ";
 cin >> metro;
 cin.ignore(); 
 Person p1(strName,metro); 
 cout << "The person's name is " << p1.name << " and height is " << p1.height << endl;
 system (“pause”);
 return 0;}
Repare que os argumentos do construtor têm de estar na ordem esperada
Separar o construtor prototype da implementação
 #include <iostream>
 #include <string>
 using namespace std;
 const int MAX = 3;
 
 struct Person {
 string name;
 int height;
 
 Person(); //construtor sem argumento
 Person(string, int); //construtor com dois parâmetros, apenas é
 necessário dizer o tipo dos parâmetros – o nome não é necessário)
 };
 
 Person::Person()
 {
 name = "No name assigned";
 height = -1;
 }
 
 Person::Person(string s, int h)
 {
 name = s;
 height = h;
 }
 
 int main ()
 {
Estruturas 34
 int metro;
 string strName;
 cout << "Enter person's name: ";
 getline(cin, strName);
 cout << "Enter height in inches: ";
 cin >> metro;
 cin.ignore(); 
 Person p1(strName, inches); 
 cout << "The person's name is " << p1.name << " and height is " << p1.height << endl;
 system (“pause”);
 return 0;
}
•• Vamos ver a função main(): declarámos 2 variáveis uma int e outra string. Pedimos para a pessoa escrever o nome
e colocámos o valor na variável string, depois pedimos a altura e colocámos na variável int. Depois chamámos o
construtor com dois argumentos e passamos as variáveis anteriores como argumentos. Por fim mandámos
imprimir os valores das variáveis membro da estrutura.
•• Repare que para definirmos fora o construtor recorremos ao operador scope ::
 Person::Person()
 Person::Person(string s, int h)
•• Repare que no prototype dos construtor apenas tivemos de dizer o tipo dos parâmetros
Operadores
Os operadores realizam, como o nome sugere, operações entre dois tipos de dados. Existem muitos operadores, mas
citaremos aqui os fundamentais e, conforme as necessidades dos tópicos posteriores, citaremos todos os demais.
Compatibilidade
Os operadores padrões da linguagem "C" podem ser usados de forma semelhante na linguagem C++. Aliadas às
funcionalidades tradicionais do "C" podemos criar operações diferentes para os operadores. Esta funcionalidade é
conhecida como sobrecarga de operadores e será descrita em capítulo posterior.
Como C++ interpreta os operadores
Para dar uma base de entendimento para a sobrecarga de operadores iremos introduzir o modo como o compilador
C++ entende os operadores. Este modo de interpretar os operadores é implementado para dar suporte aos recursos de
POO da linguagem. O entendimento do modo de funcionamento do mecanismo de compilação pode diminuir as
dúvidas que surgem no estudo de operadores em C++.
É importante entender que a linguagem deve servir de base para a criação de entidades de dados autônomas e
operáveis. Logo, o compilador deve ser generalista ao enxergar operações com tipos primitivos e tipos criados pelo
programador (classes). Por estes fatores, o compilador utiliza-se de uma interface funcional para implementação dos
recursos de operadores.
Os operadores são tratados como funções, de forma a possibilitar a alteração do seu comportamento em
determinados casos. Os operandos são tratados como argumentos de funções, enquanto que o resultado da operação
é tratado como retorno da função do operador. Esta interface faz com que possamos programar o comportamento das
Operadores 35
operações e alterá-las quando nos seja conveniente.
Entendendo o operador
Basicamente, temos dois tipos de implementação para operadores, o tipo global e o tipo membro de classe. Os dois
tipos são usados regularmente nas implementações mais comuns. Analisaremos o tipo global, uma vez que ainda não
temos uma noção de classes suficiente para abordar o tipo membro de classe.
Digamos que temos uma estrutura ponto, como definida abaixo:
 struct Ponto
 { int x;
 int y;
 };
Uma vez que tenhamos definido um ponto, nada mais natural que queiramos somar, subtrair, enfim operar, pontos
diferentes de acordo com nossas necessidades. Para isso podemos criar operadores para fazer isso, da seguinte forma:
•• Observamos a quantidade de parâmetros, o retorno e a forma de chamar o operador que queiramos definir e
criamos uma função que execute a operação desejada;
• Inserimos o código da referida função dentro de uma chamada de operador, usando a palavra reservada operator
seguida do operador que desejamos definir:
 Ponto operator+ ( Ponto a, Ponto b )
 { Ponto soma; 
 soma.x = a.x + b.x;
 soma.y = a.y + b.y;
 return soma;
 }
E assim, o operador é entendido como uma função, sendo a sobrecarga um processo de definição da operação a ser
executada. Recebe esse nome porque todo operador já existe e a definição de uma nova funcionalidade apenas
adiciona (sobrecarrega) as habilidades anteriores do operador. Embora isto seja comum, é bom lembrar que
operações de tipos primitivos não poderão ser modificadas, restando apenas a funcionalidade de criar operadores
para nossos tipos (classes).
Os argumentos
Agora vejamos como os argumentos são vistos pelo compilador durante a chamada ao operador. Essa sintaxe, muitas
vezes, confunde iniciantes, mas é bastante intuitiva. Veja:
c = a + b;
Consideremos que a,b,c são pontos. Em termos gerais, qualquer operador binário (com dois argumentos) definido em
escopo global, receberá a e b como primeiro e segundo argumento da função que define o operador.
Podemos ver a chamada da seguinte forma:
 c = operator+( a, b );
Operadores 36
Operadores aritméticos
Operadores aritméticos são utilizados para efetuar operações matemáticas entre dados. São 5 operadores aritméticos
em C++:
#include <iostream>
using namespace std;
int main() {
int soma = 5 + 5; // o operador '+' realiza somas.
double subtracao = 5 - 5; // o operador '-' efetua subtração.
float multiplicacao = 5.1 * 0.5; // o operador '*' efetua 
multiplicação.
char divisao = 100 / 2; // o operador '/' efetua divisão.
int modulo = 51 % 5; // retorna o resto da divisão inteira.
cout << "Resultados: " << soma << ", " << subtracao << ", " << multiplicacao << ", "
 << divisao << ", " << modulo << endl;
}
A saída desse programa gera no console o seguinte:
<source lang=cpp>
Resultados: 10, 0, 2.55, 2, 1.
O quarto resultado é '2' pois 50 é o código decimal deste caracter.
Tipo de retorno
Você pode realizar operações aritméticas, obviamente, entre números. Como dito no tópico anterior, você também
pode realizar operações aritméticas com os tipos char e wchar_t.
O retorno da operação será também um número (real, inteiro ou até mesmo um caracter, conforme os tipos dos
operandos).
Divisão inteira e divisão real
Existe, para a linguagem, diferença entre uma divisão entre números inteiros e entre números reais (ponto flutuante).
Se você fizer a divisão entre os inteiros 3 e 2, o resultado não será 1.5, será 1. Já se fizer a divisão entre os números
reais (em ponto flutuante) dos deles, então sim obterá 1.5.
O motivo é que há 2 tipos de divisão: a inteira e a decimal.
Divisão inteira e o operador módulo
A divisão inteira retorna o quociente da divisão sem a parte fracionária. Isso ocorre porque a linguagem efetua a
divisão enquanto o resto for maior que o divisor (logo, a divisão nunca apresentará parte fracionária).
Para obter o resto da divisão, você pode usar o operador módulo (%). Esse operador retorna, em vez do quociente, o
resto da divisão inteira. É por isso que no nosso exemplo 51 % 5 resultou em 1, pois 5x10 + 1 = 51, onde 5 é o
divisor, 10 é o quociente, 1 é o resto e 51 o dividendo.
Operadores 37
Divisão real
A divisão real é aquela efetuada entre tipos ponto flutuante ou entre ponto flutuante e inteiros/caracteres. Isso
efetuará a divisão até que o resto seja zero, ou quando o resto repetir-se indefinidamente (no caso de dízimas
periódicas como, por exemplo, 10/3).
Se quisermos que

Continue navegando