You are on page 1of 150

PDF gerado usando o pacote de ferramentas em cdigo aberto mwlib. Veja http://code.pediapress.com/ para mais informaes.

PDF generated at: Fri, 26 Sep 2014 03:17:25 UTC


Programar em C++
Contedo
Pginas
Objetivo 1
Por que C++? 1
Diferenas entre C e C++ 2
Introduo 3
Al, Mundo! 6
Variveis e constantes 12
Ponteiros 18
Vetores 20
Estruturas 29
Operadores 34
Deciso e controle de fluxo 37
Estruturas de repetio 42
Funes 49
Referncias de dados 51
Entrada e sada de dados 56
Entrada e sada de dados 2 65
Manipulando strings 80
Classes 88
Encapsulamento 103
Herana 106
Polimorfismo 119
Friend 124
Classes internas 126
Sobrecarga de operadores 127
Alocao dinmica de memria 129
Excees 136
Namespace 137
Templates 137
Containers 139
Compilao 139
Lista de Palavras Reservadas do C++ 141
Lista de Sequncias de Escape 142
Tabela ASCII 142
C++11 144
Referncias
Fontes e Editores da Pgina 145
Fontes, Licenas e Editores da Imagem 146
Licenas das pginas
Licena 147
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 nvel para os diversos ambientes existentes, desde
aplicaes para GNU/Linux ou Windows at programas para microcontroladores, alm de fornecer a base para os
estudos avanados de C++.
Por ser um livro especfico sobre a linguagem C++, altamente recomendvel que o leitor tenha conhecimentos
prvios sobre a linguagem C.
Espera-se que este livro aborde:
Aspectos tericos
Aspectos prticos
Os erros comuns
Para tanto cada tpico dever ter uma explicao terica, citar os erros mais comuns e exerccios.
Por que C++?
Imagine que voc deve fazer um programa para fazer a mquina de um pequeno relgio de pulso funcionar, ento
voc pensa:
Bom, isso pode ser feito com Assembly...
Porm, pensando melhor, voc decide mudar de linguagem quando voc pondera.
O problema maior que se eu tiver que mudar o processador do relgio, 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 fcil de entender o cdigo,
reaproveitar em outras coisas e ainda vai ser mais fcil de expandir para outros modelos de relgio.
E assim o que podemos perceber como C++ poderosa, flexvel e abrangente. Ela pode ser usada para programar
qualquer tipo de hardware, desde os mais simples at os mais complexos. Alm disso, C++ uma linguagem que
gera programas em cdigo de mquina, que funcionam com ou sem a participao de sistemas operacionais no
dispositivo.
Alguns profissionais afirmam que C++ a linguagem mais poderosa que existe, veja algumas caractersticas dela:
um superconjunto da linguagem C, e contm vrios melhoramentos;
Deu origem a grandes linguagens como Java e D;
a porta para a programao orientada a objetos;
C++ pode virtualmente ser efetivamente aplicado a qualquer tarefa de programao;
H vrios compiladores para diversas plataformas tornando a linguagem uma opo para programas
multiplataforma.
A linguagem C++ utilizada em projetos como:
Compiladores;
Editores;
Ferramentas de programao;
Jogos;
Programas de redes.
At ao momento foram realizadas 3 grandes revises 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 verso suportada por todos os compiladores C++ famosos incluindo Microsofts Visual C++, Borlands
C++ Builder e GCC. Esta foi revista em 2003.
C++ considerada uma linguagem que est entre linguagem de alto nvel (em ingls, high level language) e
linguagem de baixo nvel (em ingls, low level language). Dito de outra forma, uma linguagem que est prxima
da linguagem humana (linguagem de alto nvel), mas ao mesmo tempo permite estar prximo da maneira como o
computador processa, prximo do Assembly (uma linguagem de baixo nvel).
Diferenas entre C e C++
Quem sabe programar em C++, capaz de programar C, devido semelhana entre as linguagens e o fato do C++
ser uma extenso do C. Contudo o C no completamente um subconjunto do C++. Grande parte de cdigo C pode
ser perfeitamente compilado em C++, mas existem algumas pequenas diferenas sintticas e semnticas entre as
linguagens que tornam alguns trechos de cdigo C vlidos em cdigo C++ invlido, ou cdigos que exibem
comportamentos diferentes em cada linguagem.
Algumas diferenas bsicas:
O C permite a converso implcita entre o tipo de dado void* para ponteiros para outros tipos, algo que o C++ no
permite.
O C permite que constantes de caracteres sejam inseridas em chamadas de funes com parmetros tipo char*,
em C++ preciso declarar o parmetro como const char *;
Alm destas pequenas diferenas, C++ tem um conjunto de caractersticas que a torna fundamentalmente diferente
de "C". Esse conjunto, torna possvel programar em C++ de um modo totalmente diferente do modo de programar da
linguagem "C". O que traz a diferena o modo da orientao na montagem do cdigo.
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 comeam a programar usando um compilador C++, pois esta
linguagem permite programar nos dois modos. Essa uma das caractersticas que a torna mais flexvel.
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 caractersticas, o C++ permite programar em modo misto, ou seja, escrevendo partes do
cdigo orientadas a procedimentos e outras orientadas a objetos.
As diferenas entre os dois modos de programar sero esclarecidas nos captulos subsequentes. Por hora nos basta
deixar claro que os dois modos so 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, no
permitem.
Esta pgina um esboo de informtica. Ampliando-a voc ajudar a melhorar o Wikilivros.
Introduo
3
Introduo
Pensando no cdigo
Considerando o conjunto de operaes e eventos que nosso programa deve executar temos diversas maneiras de criar
o cdigo, porm o mais difcil criar um cdigo eficiente, rpido e compacto. Na verdade, diversos fatores podem
interferir nestes aspectos da programao, entre eles, a escolha do compilador, o mtodo de estruturar o cdigo, a
orientao do mesmo, etc... Em termos gerais, um cdigo torna-se mais prximo do ideal a medida que suas partes
tornam-se mais simples de se analisar e quando todos os processos esto bem definidos e especializados. Quando
temos um cdigo que contm muito mais excees do que regras, este precisa de uma reestruturao.
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 avanados da
linguagem, as estruturas de deciso (por exemplo, if-else ou switch) podem ser simplificadas e a organizao
do cdigo pode ser bem mais globalizada e genrica, possibilitando a reutilizao do cdigo em diversas situaes
diferentes.
Vejamos como as funcionalidades da linguagem C++ podem ajudar a redefinir os meios de programao que
aprendemos com o bom e velho estilo C.
Dois modos de programar
Observando o modo de programar que as linguagens oferecem desde os primrdios da computao, podemos notar
vrios mtodos 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 sntese, refere-se a forma
de programar onde uma instruo segue a outra numa sequncia que inicia e termina em um fluxo parcialmente
"previsvel".
A programao estruturada ainda pode ser classificada em dois modos: um orientado a procedimentos e outro
orientado a objetos. Os dois podem ser confundidos por quem no tem muita experincia, mas o uso de um ou do
outro implica em caractersticas prprias para cada caso. Logo, preciso entender bem os conceitos antes de definir
se um cdigo procedural ou orientado a objetos.
O modelo sequenciado procedural bem simples de implementar, porm, aumenta a complexidade para tarefas mais
bem trabalhadas e sofisticadas. Isto ocorre devido a estrutura do modelo, que exige rotinas cada vez mais extensas.
No raramente possvel encontrar rotinas que, em alguns casos, tornam-se comparveis a programas completos,
usando como referncia o nmero de linhas de instrues. O uso deste modelo, muitas vezes dificulta a manuteno
e expanso do cdigo, caso isto no 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 orientao define o modo de abordar o problema para tentar solucion-lo:
O modelo de orientao a procedimentos se preocupa em fornecer meios para resolver o problema sem
contabilizar, a princpio, os dados que sero usados durante o processo.
O modelo de orientao a objetos se preocupa com os elementos que so necessrios para a soluo de um
problema. Sob este ngulo, os dados so os elementos principais na anlise do problema.
Este livro traz uma viso dos problemas sob a ptica da orientao a objetos, enquanto que o livro "Programar em C"
traz a anlise sob a ptica da orientao a procedimentos. Isto no quer dizer que devamos escolher a orientao a
objetos como o modo mandatrio de programao, mas que podemos contar com seus recursos sempre que esta
escolha facilite a resoluo do problema. Portanto, cabe sempre uma anlise para definir se o problema melhor
Introduo
4
tratado por uma abordagem orientada a objetos ou a procedimentos.
Um pouco sobre orientao a objetos
A programao orientada a objetos um paradigma de programao que visa organizao, produtividade e
sustentabilidade.
A apresentao dos conceitos de orientao a objetos bastante abrangente, o que implica na abordagem de diversos
aspectos, como modelagem, estudo de performance de modelos, aplicabilidade de tcnicas, estruturao de objetos,
otimizao, manuteno do cdigo, entre outros. Por este motivo, nosso objetivo aqui no apresentar a orientao 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 orientao a objetos se aplica na linguagem C++, porm os
conceitos aqui apresentados devem ser suficientes para a estruturao de programas de bom nvel.
A ideia principal por traz do modelo de programao orientado a objetos est em transformar entidades do mundo
real em identificadores dentro do programa (objetos), trabalhando-os como entidades da linguagem que possuem
caractersticas e operaes prprias. Esta abordagem transforma o programa em um meio de simulao de situaes
virtuais por meio de entidades de cdigo que tem comportamento predefinido. Esta abstrao uma aliada do
programador por permitir idealizar sistemas mais sofisticados de uma maneira bastante intuitiva.
Todas as linguagens orientadas a objetos contm os princpios de:
Encapsulamento
um mecanismo para esconder os detalhes envolvidos no processamento de uma ao. Por exemplo, quando
usamos um telefone, no 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.
Herana
Como o nome sugere, isso permite que uma classe herde de outra suas caractersticas, podendo tambm
introduzir suas prprias ou alterar as caractersticas herdadas. O uso de herana acaba poupando trabalho e
melhorando a organizao do cdigo.
Paradigmas da Programao:
Desde o incio da programao, j passamos pelos seguintes paradigmas:
No estruturada - exemplos: COBOL, FORTRAN, BASIC (anos 50-60)
Procedimental ou Procedural - exemplos: C, Pascal (anos 70)
Modular - exemplo: Modula II (anos 80)
Abstrao de tipos de dados - exemplo: Ada (anos 80)
Programao Orientada a Objetos - exemplos: C++, Java, Delphi (Object Pascal) entre outras. (dcadas
80-90-2000)
Introduo
5
Objetos
Objeto , genericamente, uma entidade de armazenamento e manipulao de dados. O mesmo deve ser criado para
processar os dados que armazena e recebe, sendo sensvel a entradas do programa principal para fornecer as sadas
esperadas pelo mesmo. Por estes motivos o objeto deve ser pensado como uma entidade de dados autnoma,
encarregada de processar todos os dados que mantm.
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 so 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 caractersticas dadas a um grupo de "indivduos", ou seja, grupo
de objetos. Por este motivo, classe a definio de tipo de objeto.
Em C++ as classes de objetos so criadas atravs da palavra chave class. Esta nomenclatura usada por muitas
outras linguagens de programao mais caracteristicamente restritas a orientao a objetos. Estes aspectos facilitam
um pouco o aprendizado por programadores j familiarizados com estas linguagens quando iniciam a programao
em C++.
O processo de criao de um objeto segue a sequncia:
Definir os dados e procedimentos que a classe deve conter;
Criar a classe de objetos;
Declarar (instanciar) o objeto.
A definio de uma classe de objetos deve ser feita de forma a tornar, preferencialmente, todos os dados protegidos
de interferncias de cdigos externos ao objeto. Por este motivo um objeto deve ser uma parte do cdigo 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
prpria".
Al, Mundo!
6
Al, Mundo!
Ol mundo!
comum, no aprendizado de uma linguagem de programao, que seu primeiro programa faa com que o
computador exiba "Ol mundo!". Na linguagem C++ este primeiro programa j introduz muitos conceitos sobre a
linguagem. Veja o cdigo do nosso primeiro programa:
#include <iostream>
using namespace std;
int main ()
{
cout << "Ol mundo!";
return 0;
}
Assim como para comear a dirigir no necessrio saber toda a mecnica do carro, para programar no precisamos
logo de incio nos prender a todos os detalhes.
No programa acima, vamos dar ateno apenas ao contedo que se encontra entre as chaves:
{
cout << "Ol mundo!";
return 0;
}
cout << "Ol mundo!";
A palavra cout vem de Console OUT (sada do console), onde geralmente temos a sada 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 sequncia de caracteres ser levada ao cout.
return 0;
Este comando termina o programa, o estudaremos melhor no captulo sobre funes e retornos.
ATENO:
Caso seu sistema operacional seja o Microsoft Windows, voc deve adicionar imediatamente antes de return 0;
a seguinte linha:
system ("pause");
A funo system() executa um comando do Windows. como se o prprio usurio 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 necessrio adicionar esta linha, caso contrrio o
computador escreveria "Ol mundo!" e fecharia o programa antes que pudssemos ler qualquer coisa. Uma forma
elegante de lidar com estas peculiaridades do Windows usar predefinies, de forma que o programa seja portvel
para qualquer sistema operacional:
#if defined(_MSC_VER)
// estas linhas sero executadas apenas quando o programa
// for compilado por alguma verso 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 acessvel, mesmo quando o usurio est usando a interface
grfica. Por isso, para esses sistemas um comando para solicitar pausa ao sistema no necessrio.
Entrada de dados e comentrios no cdigo
Comentrio um recurso muito til em programao. 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 comentrios
so usados para explicar trechos de cdigo, adicionar clusulas e qualquer texto em geral.
Vamos agora para um programa mais completo com entrada de dados e comentrios dentro do cdigo:
// Este um comentrio de uma linha
/*
Este
um comentrio
de vrias
linhas
*/
#include <iostream>
using namespace std;
int main ()
{
int x;
cout << "Digite um nmero: ";
cin >> x;
cout << "\nVoc digitou o nmero: " << x << endl;
return 0;
}
Comentrios no programa
Observemos esta linha:
// Este um comentrio 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 binrio existem trs fases
principais: O preprocessamento, a compilao e a fase de ligao (link). O preprocessador um programa invocado
pelo compilador para remover comentrios e substituir certas partes do programa conforme a necessidade do cdigo
criado pelo programador.
O preprocessador faz algumas alteraes no texto fonte, que basicamente consistem em eliminar pedaos de cdigo
e/ou substitu-los por outros (copy-paste). Enfim, o mesmo altera o cdigo fonte contendo comandos iniciados com
# e outros comandos especficos, por outro cdigo sem comandos de preprocessamento, puramente em linguagem
C++.
Al, Mundo!
8
Ao analisar o cdigo, o preprocessador encontra a sequncia // e vai eliminar o texto que est a seguir at ao fim
da linha.
Mais uma forma de adicionar comentrios:
/*
Este
um comentrio
de vrias
linhas
*/
A linguagem C++ permite tambm fazer comentrios por mais do que uma linha. Chama-se comentrio por bloco e
o que faz eliminar tudo o que encontrar entre a sequncia inicial /* e o final */.
A vantagem de termos esta possibilidade poder comentar o nosso cdigo. Existem algumas regras de boa conduta
para comentrios que foram criadas por pessoas que j tm muito tempo nisto:
Uma criar logo no topo um comentrio a dizer o que o nosso programa, e o que faz numa forma geral;
Outra fazer comentrios a cada funo que aparece no cdigo a explicar;
Outra comentar uma linha mais obscura, mais difcil de entender, que no bvia;
A outra no comentar tudo. O comentar deve ser para sobressair.
Esta ltima regra pode ser esquecida quando o programa didtico, neste caso pode-se usar o programa como texto
comentado.
Incluindo cabealhos
#include <iostream>
O smbolo # uma chamada de ateno ao compilador a dizer que aquela linha para o preprocessador, depois
temos o "include" (que basicamente diz para incluir cdigo). Incluir o qu?
Deve incluir o ficheiro/arquivo iostream. (in+out+stream, "fluxo de entrada e sada", padro) (na maioria das
vezes, como entrada padro temos o teclado e como sada temos o monitor) (este ficheiro/arquivo contm
declaraes das funes e definies que o nosso cdigo fonte ir necessitar)
Este cdigo que ser includo chamado de cabealho devido a uma caracterstica evidente, o fato de ser cdigo de
declarao inicial do programa, que deve estar no topo do arquivo/ficheiro.
Existem outros arquivos (ficheiros cabealho), o iostream para fluxos de entrada e sada, mas temos muitos
mais para matemtica, manipulao de tempo, tratamento de caracteres, etc...
Na maioria das vezes, os arquivos de cabealho fazem parte de uma biblioteca. Podemos ver na parte dos anexos,
algumas bibliotecas que existem juntamente com as funes de cada uma. Ns prprios podemos criar uma
biblioteca com cdigo e nosso prprio cabealho. E at podemos comprar bibliotecas existentes comercialmente,
atravs de empresas especializadas em desenvolvimento, que tambm tero seus arquivos/ficheiros de cabealhos.
Mas, o que so bibliotecas? So arquivos com um conjunto de cdigos que algum fez antes. As que enunciamos
antes so as "standard", so aquelas que tm as funcionalidades bsicas, pertencentes aos padres 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 stio/diretrio usual (que onde o compilador usa como padro para os "includes"). Se
tivssemos o ficheiro/arquivo iostream envolvido em "" significaria que o preprocessador deveria procur-lo
dentro de uma lista de diretrios de incluso, "includes", iniciando pelo diretrio atual.
Al, Mundo!
9
As bibliotecas so compostas por 2 partes: um ndice de todas as funes e definies e declaraes, o cabealho, e
depois a definio de todas as funes existentes no ndice, arquivos de cdigo.
As diretivas de preprocessamento no terminam com o ponto e vrgula como nas instrues.
Namespace
using namespace std;
Observando esta linha, alguns tradicionais programadores em linguagem C, tm uma novidade: namespaces so
espaos de nomes dentro do cdigo, eles funcionam, entre outras coisas, como um meio de evitar duplicao de
nomes dentro de um projeto extenso, que geralmente contam com inmeros 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 sada padro, 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 incio deste tpico.
O "namespace" permite que as variveis sejam localizadas em certas regies do cdigo. Declarar o "namespace std"
permite que todos os objetos e funes da biblioteca "standard input-output" possam ser usados sem qualquer
qualificaes especficas, desta maneira, no mais necessrio o uso de "std::".
Este um conceito avanado que podemos explorar mais, vamos deix-lo para depois.
Funo "main"
int main(){}
Como na linguagem C, a funo principal de entrada do programa a partir do sistema operacional a funo main.
Por isso mesmo ela obrigatria em qualquer programa. Se no existisse uma "main function", no haveria entrada
para que o sistema iniciasse o programa.
Todas as funes so declaradas e usadas com o operador ( ), assim que o compilador reconhece que estas so
funes. A ideia de ter funes permitir o encapsulamento de uma ideia ou operao, dar um nome a isso e depois
chamar essa operao de vrias partes do programa simplesmente usando o seu nome. As funes declaradas como
membros de uma classe de objetos podem ser chamadas de mtodos.
Do ponto de vista funcional, um cdigo dentro de uma funo executa operaes em outra parte do programa, que
no aquela de onde foi chamada, por este motivo as mesmas contam com um mecanismo de passagem de dados, ao
declarar uma funo indicamos quais os dados que entram e o que ela deve fornecer a quem lhe chamou. Pode-se
dizer que, tal qual uma funo matemtica, a funo em C/C++ poder ser substituda, depois de sua execuo, pelo
valor que ela retorna, este valor ser especificado antes do nome da funo na declarao da mesma, conforme
vemos no incio deste tpico.
O int significa que a funo 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 representao para nmero real.
Vejamos um exemplo:
Quando criamos uma funo soma, obviamente s para ilustrao pois isso no necessrio, 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 varivel chamada valor, para isto
faremos:
valor = soma(2, 3);
Primeiro analisamos qual o resultado e depois substitumos a funo pelo valor que ela retorna:
valor = 5;
Simples, no?
; - Final de sequncia de instrues
O ponto e vrgula funciona como ponto final, separa as instrues e contextos. Repare que apenas as funes, ou
melhor, as definies de funes e as diretivas de preprocessamento que no tm o ";"
importante notar que o cdigo poderia ser todo escrito quase numa linha tipo:
int main (){int a; cout << "Hello world! Digite um nmero:\n"; cin >> a;cout <<
"Voc digitou o nmero: " << a<<"\n";return 0;}
realmente o ";" que faz a terminao das instrues.
Ao encontrar as chaves "{}", o compilador reconhece como um delimitador de bloco, ou "body", corpo. O corpo de
uma funo ou bloco de cdigo comea com "{" e termina com "}", como temos as instrues agrupadas, j no h
necessidade de colocar o ";" no final para indicar onde o fim do bloco.
No nosso exemplo existem 2 instrues no corpo da funo. As instrues so executadas por ordem: do topo at ao
fim a menos que existam funes que alterem o fluxo da leitura ou que existam cdigos de controle de execuo
"execution control codes", que alteram o caminho de execuo.
Entrada e sada (cin/cout)
cout << "Hello world! Digite um nmero:\n";
(c+out) Podemos utilizar este objeto porque pusemos o header e o namespace std. As informaes sero
direcionadas atravs do iostream, um subsistema de entrada e sada da biblioteca padro. O que este objeto nos
permite enviar o que temos entre aspas para a sada (out), que o monitor neste caso.
Quem j conhece a linguagem C, certamente est familiarizado com os streams da biblioteca padro, 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 abstrao do elemento de sada
padro observada na presena de um objeto que representa a sada fsica 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 padro, neste caso a sua funo foi substituda
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 funes imprimir strings no "standard
output" (que normalmente o/a ecr/tela).
Da mesma forma que podemos formatar o texto enviado a sada padro na linguagem C, tambm podemos faz-lo
com os objetos do C++, por exemplo, se acrescentssemos "<< hex <<" entre uma varivel e a sada:
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 memria que foi chamada de "a".
Da mesma forma que o cout existe para sada de dados, temos outro objeto para entrada atravs 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 esto vindo do cin para a varivel "a".
cout << "Voc digitou o nmero: " << a << "\n";
Aqui voltamos a utilizar o objeto cout primeiro para imprimir no/na ecr/tela a frase "Voc digitou o nmero: ",
depois vai buscar o valor que est naquela rea de memria a que chamamos de "a" e por fim coloca o fim de linha
atravs 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 aps a finalizao da linha.
funo system("pause")
system ("pause");
A maioria dos compiladores quando esto executando em modo grfico fecha o console de sada assim que o
programa finaliza. Isto impede que possamos ver o que aconteceu, principalmente quando o programa contm
apenas umas poucas instrues.
A funo system(), faz parte do padro 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 incio deste captulo, este comando
destinado a sistemas da Microsoft

. Coloquei esta linha para que o programa no finalizasse sem que pudssemos
ver uma janela com o resultado, se no o fizesse a janela abriria e fecharia sem que pudssemos ver o aconteceu
durante a execuo 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 funo retorne o valor zero, como esta funo a principal do programa, por onde o sistema
operativo/operacional iniciou a execuo do mesmo, este retorno recebido pelo sistema, comum que valores
diferentes de zero sejam interpretados como erro do programa.
Esta instruo 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 no finalize como seria de
esperar, ele tem um crash (ou porque ficou com falta de memria.). O sistema operativo/operacional necessita de
lidar com estas terminaes anormais de uma forma diferente das normais. Por isso que o programa diz ao sistema
operativo/operacional que terminou normalmente.
Questo: porque que o sistema operativo necessita de saber que o programa terminou bem?
Variveis e constantes
12
Variveis e constantes
Constantes
Compatvel com a linguagem C, o C++ mantm as constantes bsicas e introduz algumas novas funcionalidades
possibilitadas pelo modificador const.
O uso do modificador const tem duas funes principais:
1. 1. Resguarda da inviolabilidade de valores apontados por ponteiros;
2. 2. Auxlio na compreenso das caractersticas de funes, durante a implementao.
Simblicas
Constantes simblicas podem ser criadas com as diretivas do preprocessador #define. Neste modo os valores, de
fato, no so interpretados imediatamente pelo compilador, antes so identificados e substituidos pelo
preprocessador no estgio anterior compilao. Por exemplo:
#define BUFFER_LENGTH 2048
...
...
...
char data[BUFFER_LENGTH];
Observe que o valor 2048 ser usado logo abaixo no cdigo, depois que o preprocessador substituir a constante
simblica BUFFER_LENGTH pelo valor que lhe foi atribudo.
Note que as constantes so escritas com todas as letras maisculas, isso no uma regra, mas ajuda a identificar o
que constante simblica dentro do programa, sendo adotado pela maioria dos desenvolvedores como uma boa
prtica de programao.
Neste caso, podemos definir valores simblicos 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 simblicos em formato de cdigo, o que permite criar programas com melhor legibilidade.
Para isso podemos colocar expresses com funcionalidades bem definidas substitudas por nomes que as
identifiquem. Por exemplo:
float a[3];
#define PRINT_VECTOR cout << a[0] << " , " << a[1] << " , " << a[2] << endl
...
...
Variveis e constantes
13
PRINT_VECTOR;
Desta forma, todas as vezes que quisermos mostrar o valor do vetor de trs 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 cdigo atravs de seu valor significativo. Por
exemplo, podemos definir nmeros:
256 //decimal
0400 //octal
0x100 //hexadecimal
Tambm 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
Enumeraes
Valores enumerados so muito recorrentes nos ambientes de programao, por isso podemos contar com a
declarao de enum em C++ tambm, 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;
Porm, observamos uma diferena: a palavra enum pode ser dispensada na declarao da varivel, enquanto que em
C obrigatrio,apesar desta pequena diferena a funcionalidade do recurso a mesma, ou seja, pode-se definir
variveis que assumem estritamente os valores presentes na declarao de enumerao.
Este recurso torna-se til na padronizao de valores a serem usados como entrada de funes, por exemplo. Pode
ser considerada como uma funcionalidade mnemnica, seu uso no altera o cdigo final caso modifiquemos o
programa para que use variveis inteiras ou strings de mesmo valor do enum.
A seguinte sintaxe:
seq x = 3;
No permitida, mesmo que o valor presente no enum seja avaliado como 3 pelo compilador em tempo de
compilao. Isso pode parecer confuso, mas lembre-se de que os valores sero atribuidos pelo compilador, logo isso
Variveis e constantes
14
evita que o mesmo programa seja compilado em ambientes diferentes e tenha comportamento diferente.
Variveis
As variveis no C++ podem ser usadas da mesma forma que na linguagem "C", porm algumas poucas diferenas
podem ser destacadas, principalmente aquelas que trazem linguagem C++ caractersticas prprias da orientao a
objetos.
Tipos
Como na linguagem "C", os tipos nativos do compilador em uso so referenciados por:
char
int
float
double
Que correspondem a nmeros com tamanho relativos, com os significados respectivos: caractere, inteiro, ponto
flutuante e ponto flutuante de dupla preciso. De qualquer forma a extenso dos mesmos depende da mquina que se
pretende programar. Considerando que nem sempre teremos que programar apenas computadores, poderemos ter
extenses bem distintas dependendo do hardware a ser programado, por exemplo, computadores domsticos
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 situao.
A linguagem C++ introduz o tipo bool, que representa o valor booleano, falso ou verdadeiro, o que no existe na
linguagem "C", porm seu tamanho na memria depende da capacidade de otimizao do compilador usado.
Tipicamente os compiladores para computadores usam uma varivel do tamanho de char para representar o valor, o
que poderia ser considerado um desperdcio, mas devido abundncia de memria no chega a ser inadequado.
Porm em sistemas pequenos h compiladores que armazenam o valor booleano em apenas um bit. Obviamente, se o
processador possuir recursos de manipulao de bits isso muito til e pode ser usado como um fator de melhoria da
qualidade do software desenvolvido. Em outros ambientes, onde a manipulao de bits traga prejuzo para o
desempenho usa-se a estratgia padro de desperdiar um pouco de espao em favor de uma agilidade maior nas
operaes. Portanto, embora as variaes de utilizao do espao sejam muitas, o compilador sempre far a mais
apropriada para cada ambiente de utilizao 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 esto diretamente ligados a caractersticas da POO (programao orientada a
objetos). Desta forma descreveremos apenas os tipos relevantes exclusivamente para a programao na linguagem
escopo do livro presente sem nos aprofundarmos na teoria por trs dos mesmos. A prtica 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
Variveis 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 funo, basicamente, estabelecer um vnculo entre declarao e
obrigatoriedade da coerncia no uso do smbolo declarado.
A princpio, quando declaramos uma constante com este modificador fazemos com que seja obrigatrio o uso do
smbolo de forma que o mesmo no possa ter seu valor alterado. Assim, se fizermos:
const int x = 4;
O inteiro x no 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. Porm podemos considerar esta funcionalidade como bvia e
trivial, ainda temos o uso do modificador de uma forma mais proveitosa, na passagem de parmetros para funes,
por exemplo:
void inhibitX(const int *x)
{
...
...
BASEADDRESS = z*((*x) - 23p*71);
...
...
}
Neste caso, a funo acima recebe um valor inteiro atravs de um ponteiro, que no obrigatoriamente precisa ser
constante no escopo fora da funo, porm dentro da mesma a varivel ser constante. Fazendo este simples
procedimento teremos como fazer com que um smbolo seja varivel fora da funo e constante dentro da mesma, de
forma que dentro do escopo da mesma s faamos leituras do seu valor. O artifcio cria duas consequncias
importantes: a primeira a melhor legibilidade do cdigo, visto que ao usarmos uma funo teremos certeza de que
os valores no sero alterados dentro da funo; a segunda que poderemos evitar erros inadvertidos de atribuio
de valores varivel quando da construo da funo.
volatile
Uma varivel "voltil", como a prpria expresso sugere, uma varivel que pode ser modificada sem 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
contedo da varivel em eventos fora da previsibilidade do tempo de compilao. Em outras palavras, o compilador
no pode prever com segurana se pode otimizar trechos de programa onde esta varivel se encontra.
A palavra reservada volatile destinada as situaes onde uma varivel pode ter seu valor alterado por fatores
diversos, e portanto, no pode ser otimizada. Usando-a o programador informa ao compilador que no deve interferir
na forma com que o programa foi escrito para acesso a esta varivel. Desta forma impede que erros inseridos por
otimizao estejam presentes na verso final do executvel.
O uso desta palavra implica em mudana no comportamento do compilador durante a interpretao do cdigo. As
classes de objetos do tipo volteis s podero ser acessadas por rotinas que declarem aceitar como entrada dados
volteis, da mesma forma que apenas objetos volteis podem acessar variveis volteis. Esta "amarrao" faz com
que o uso de tais variveis se torne mais seguro.
Podemos declarar variveis volteis da seguinte forma:
volatile int x;
Variveis e constantes
16
Enquanto que para funes que acessam tais variveis teremos consequncias visveis na montagem do cdigo, por
exemplo, se tivermos o seguinte trecho de programa:
int x = 1265;
void main_loop()
{
while( x == 1265)
{
// fazer alguma coisa
}
}
Poderemos ter uma otimizao 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 no pode ser considerado
verdadeiro, pois o programa pode estar esperando que uma das tarefas modifique o estado da varivel para
prosseguir seu curso, a otimizao acima ser um desastre, uma vez que a funo acima jamais ser encerrada.
Para evitar isso fazemos:
volatile int x = 1265;
void main_loop()
{
while( x == 1265)
{
// fazer alguma coisa
}
}
E o compilador no poder mais avaliar que o valor de x pode ser otimizado para o valor corrente, pois informamos
na declarao que o valor da varivel pode ser alterado sem seu conhecimento. Desta forma o mesmo no alterar o
algortmo e far o teste da varivel dentro do while.
Variveis e constantes
17
Nomeando tipos
A linguagem "C" possui recursos de nomeao de tipos simples e compostos atravs das palavras chaves typedef e
struct. Adicionada a estas o C++ acrescenta a palavra chave class. Vejamos como devemos definir um novo tipo
atravs 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 avanado de programar usando o C++. Com este identificador declaramos objetos, da mesma forma que
declaramos estruturas.
Uma classe pode ser definida em um cabealho "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 presena de uma funo dentro da declarao acima. Ento poderamos
perguntar: Por que colocar uma funo dentro de um tipo? A resposta simples: Para manipular os dados dentro do
tipo! No apenas por esta caracterstica, mas por vrias outras que aboradaremos nos captulos seguintes, o tipo class
extremamente flexvel e poderoso.
importante ressaltar que em C++ a declarao do identificador: enum, struct, class, etc... dispensado quando se
declara uma varivel ou objeto para o referido tipo. Desta forma podemos ter tambm as seguintes declaraes como
vlidas, alm do uso padro 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;
Variveis e constantes
18
...
...
y.getData();
}
Como podemos ver na funo acima se a varivel x for declarada para uma estrutura data o uso da palavra struct
no obrigatrio, assim como tambm no o para outros tipos de dados compostos.
Ponteiros
Ponteiros
Em linguagem "C", podemos definir variveis ponteiro, ou seja, variveis que armazenam o endereo de outras
variveis. 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++ tambm permite o uso de
ponteiros, o que a distingue de muitas outras linguagens orientadas a objeto. Embora seja muito difundida a idia da
criao de linguagens que no suportem acesso a ponteiros, basicamente pressupondo que todos os programadores
so inexperientes, a falta deste recurso limita as capacidades de interao 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, porm implica em
necessidade de cautela na elaborao de programas que usam deste recurso. Certamente, nem todos os
programadores precisam ser considerados inaptos, a priori, atravs da supresso ou insero de complicadores de
recursos criados explicitamente para for-los a no usar dos recursos. Por isso, a linguagem C++ disponibiliza o
recurso para quem deseja utiliz-lo e tambm apresenta diversos outros recursos que so alternativas ao uso de
ponteiros quando eles no so imprescindveis.
O operador *
O operador *, chamado de apontador, funciona em C++ da mesma forma que em C. Considerando que tenhamos
uma varivel ponteiro p:
Em p armazena-se o endereo de memria que queiramos manipular. Na maioria das vezes obtemos o endereo
de outra varivel e colocamos em p;
Se p um ponteiro, *p o valor apontado por p, ou seja, o valor que est armazenado no endereo de memria
que queremos ler ou alterar.
Na declarao de variveis, uma varivel declarada com * um ponteiro.
Exemplo:
int *px;
Muitas vezes, iniciantes podem se sentir confusos porque quando declaramos um ponteiro usamos o * e quando
atribumos endereos a ele no usamos o *. A conceituao bsica a seguinte:
Declaramos o ponteiro com *, para que o compilador identifique que a varivel um ponteiro;
Usamos o ponteiro sem *, para acessar o endereo que ele aponta na memria;
Usamos o ponteiro com *, para acessar o valor do dado armazenado na posio de memria;
Ponteiros
19
O operador &
Na linguagem "C", o operador & tem duas funes bsicas, funciona como operador da funo lgica AND e como
operador de leitura de endereos. Para operaes com vetores, isso usado da seguinte forma:
int a = 12;
int *pa;
...
...
pa = &a;
...
...
*pa = 100;
Ou seja, declaramos a varivel a, depois declaramos um ponteiro pa, atravs do operador & obtemos o endereo de a
e atribumos o valor 100 varivel usando o ponteiro ao invs da varivel a. Desta forma alteramos o valor de a
indiretamente.
Um outro uso de & (que no tem similar em "C") pode ser visto mais adiante, em ../Referncias de dados/, mas, para
isto, necessrio estudar o que so ../Funes/.
O ponteiro "this"
Imagine que tenhamos criado um objeto qualquer de uma classe X, se quisermos ter acesso ao ponteiro que contm a
posio de memria onde est armazenado este objeto basta chamar o ponteiro "this". O ponteiro "this" uma das
caractersticas dos objetos em C++ e algumas outras linguagens que suportam orientao a objetos. Ele um
membro inerente a todos os objetos que instanciamos em programas escritos em C++.
Faremos uma breve explanao a respeito de objetos para esclarecer este tpico. Objeto so parecidos com
estruturas, uma diferena bsica que estes possuem "habilidades especficas" representadas por funes que esto
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 funes para cada um deles, uma que atribui o valor e
outra que l o valor de uma das mesmas. Detalhes das implicaes a respeito desse modo de operar os valores sero
dados nos captulos seguintes que tratam de objetos. Por ora vamos nos ater a um conceito fundamental importante
para a noo de ponteiros em C++, a identidade de um objeto.
Veja, temos uma estrutura de dados que est na memria, os dados esto l (variveis x e y), porm as funes no
estaro l, pois se tivssemos que copiar uma funo para cada estrutura que crissemos o programa tomaria um
tamanho monstruoso. O que se faz apenas guardar o endereo da estrutura em um ponteiro especial, o ponteiro
this. Assim, o compilador poder criar uma nica cpia de funo para todas as estruturas que criarmos e depois
quando a funo quiser manipular os dados de uma estrutura em particular, o far atravs 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 funes 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 funo.
Quando declaramos uma funo dentro de uma estrutura de dados esta rotina recebe um ponteiro com o endereo do
conjunto de dados que deve tratar toda vez que for invocada pelo programa. Assim, sempre acessar os dados atravs
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
Faamos uma pequena reviso de conceitos:
Vetores e matrizes so variveis compostas homogneas, ou seja, so agrupamentos de dados que
individualmente ocupam o mesmo tamanho na memria e so referenciados pelo mesmo nome, geralmente so
individualizadas usando-se ndices.
Vetores distinguem-se das matrizes apenas pela caracterstica de ter dimenso (1 x n) ou (n x 1), essencialmente
vetores so matrizes linha ou matrizes coluna.
Em linguagem "C" vetores e matrizes so usados abundantemente para compor estruturas de dados necessrias para
composio 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. Alm deste recurso, o "C" tambm define meio de criao de
matrizes tipo (n x m), provendo, desta forma os recursos necessrios para criao destes conjuntos de dados.
A linguagem "C++" suporta os mesmos recursos e permite a criao de matrizes de objetos. Uma vez que um objeto
essencialmente um tipo de dado criado pelo programador, todas as caractersticas bsicas legadas aos "tipos" em
geral so observados nos tipos criados (classes de objetos).
Vetores
21
Vetores
Os vetores em C++ seguem a mesma notao da linguagem "C", via de regra declara-se o tipo seguido de um
asterisco. Para acessar o valor apontado pela varivel usa-se um asterisco de forma semelhante, como pode ser visto
no trecho de cdigo abaixo:
int *x;
int a = 3;
x = &a;
cout <<" O valor do contedo da posio 0x"; // O valor da posio 0x23A0209112
cout << hex << x << "de memria " << *x << endl; // de memria 3
Matrizes
Podemos imaginar que uma matriz um conjunto de vetores que ocupam uma determinada rea de memria
referenciada por um nome comum. Matrizes de tipos primitivos so conseguidas atravs de associaes 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 memria disponvel para que a matriz no ultrapasse esse limite fsico,
muitas vezes delimitada pelo hardware ou pelo sistema operacional. Lembremos que, um objeto precisa do espao
Vetores
22
equivalente a soma de suas variveis internas para ser alocado na memria.
Declarando arranjo
Os arrays permitem fazer o seguinte:
int a1, a2, a3,.a100; equivalente a ter int a[100];
Ou seja permite declarar muitas variveis de uma forma bem simples, poupa escrita e bastante compreensvel.
O nmero que est dentro de brackets [] o size declarator. Ele que vai permitir ao computador dizer quantas
variveis a serem geradas e logo quanta memria dever ser reservada. A memria reservada para as variveis
vo ser todas seguidas, um int a seguir ao outro
H uma forma para no dizer o valor deste size declarator, mas isso apenas acontece antes da compilao, ou seja
o compilador que vai fazer esse preenchimento por ns, visualizando o nosso cdigo e contanto os membros que
colocmos. Isto um automatismo dos compiladores recentes. chama-se a isto iniciao implcita que vamos ver
nesta seco.
As variveis geradas pelos arrays vo ser todos do mesmo tipo.
Reparem que o valor do size declarator um nmero. literal, ele no vai mudar quando o programa estiver a
correr. Por isso quando no soubermos o nmero 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];
return 0;
}
Isto vai dar um erro de compilao, porque o array est a espera de uma constante e no uma varivel. H uma
maneira de contornar isto que atravs da memria dinmica que vamos dar mais tarde, num capitulo prprio, pois
isto vai envolver muitos conceitos.
Constantes
Reparem que h uma diferena entre literais e constantes, apesar de em ambos os casos o valor no alterado
durante a execuo do programa, a constant um nome que representa o valor, o literal o valor.
Declarar constantes
exatamente como declarar uma varivel com duas diferenas:
1. 1. A declarao comea com a palavra const. Isto vai dizer ao compilador que uma constante e no uma varivel
2. 2. Teremos de atribuir logo o valor na declarao, ou seja, fazer a iniciao
Exemplo:
const int numTests = 3;
Portanto se tentarmos colocar um outro valor ao numTest, isso vai dar um erro de compilao
Vetores
23
Array index
a[100] composto por a[0], a[1], a[99] ( De a[0], a[1], a[99] existe 100 posies)
Pergunta: Porque que o ndex comea em zero e no um? Ou seja temos as 100 posies que pedimos mas o ndex
comea no zero e no no 1. A razo disto tem a ver com offset que refere ao valor adicionado para o endereo base
para produzir a segunda address. Bem no entendi bem! Eu explico de novo: O endereo (address) do primeiro
elemento do array, o mesmo do que o endereo base do prprio array. ah espera a, o que esto a dizer que o
endereo do array igual ao do primeiro elemento do array. Assim o valor que teria de ser adicionado, ao endereo
base do array, para conseguirmos o endereo do primeiro elemento seria zero. Agora sim, percebi!
Erro: Um erro comum esquecer que o index comea no zero, e portanto quando se querem referir ao ltimo
elemento, esquecem-se que tm de subtrair uma unidade. O que advm desse esquecimento que podem estar a
alterar memria pertencente a uma varivel, instruo,..de um outro programa. Ou seja vai existir violao de
dados.
Se o array for declarado globalmente em vez de ser localmente, ento cada elemento inicializado ao valor defaut
que zero.
Iniciao
Iniciao, se bem se recordam atribuir um valor a uma varivel ao mesmo tempo que declaramos a varivel.
Podemos fazer a iniciao 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 atribuio do que elementos do array?
int a[3] = { 74, 87, 91, 45 };
Isto vai dar um erro de compilao too many initializers
Pergunta: O que que acontece se tivermos menos valores do que os elementos
int a[3] = { 74 };
No acontece nada simplesmente no temos valores para a[1] e a[2]. Porm em alguns compiladores os elementos
no 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 no inicializarmos um dos elementos, os restantes elementos tero de ser no
inicializados pois caso contrrio teremos um erro de compilao
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 ns, conta os elementos e preenche o nmero de elementos
Vetores
24
Caracter array
char name[ ] = {'J', 'e', 'f', 'f', '\0' };
char name[ ] = "Jeff";
Ambas as inicializaes so permitidas. Porm tomar ateno ultima iniciao! Quando colocmos as aspas duplas
o compilador acrescenta o "\0" na array que cria! No tem []!! Esta at costuma ser a preferida pelos programadores,
ao estilo de strings (Na verdade as strings so arrays de char mas vamos falar disso num capitulo prprio)
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 no tivssemos este carcter apareceriam estranhos caracteres a seguir
ao "jeff", chamados "caracteres-lixo". (porqu?) Isto no significa que o ltimo elemento deva ser sempre o null
carcter
Arrays de vrias dimenses
Podemos ter duas dimenses
tipo_da_varivel nome_da_varivel [altura][largura];
como tambm poderamos ter infinitas
tipo_da_varivel nome_da_varivel [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 memria teramos as coisas assim. ou seja os elementos so 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 espao par 6 ints ou antes um espao com o tamanho de 6 ints? Como ns sabemos que os
arrays os elementos tm endereos de memoria consecutivos, por isso, no podem ser pedidos 6 ints, pois se fosse
esse o caso, poderia acontecer que eles no 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;
return 0;
}
Podemos atribuir o valor 1 a 1, mas para poupar escrita de programao melhor utilizar as funes 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;
}
return 0;
}
Ou melhor ainda podemos usar uma constante, para tornar o nosso cdigo mais abstracto.
#include <iostream>
using namespace std;
const int MAX = 3;
int main ()
Vetores
26
{
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;
}
return 0;
}
Lembram-se da histria de termos o endereo do array igual ao endereo 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 no um elemento particular do array
return 0;
}
Pois bem vemos que quando mandamos imprimir o array, ele d um endereo. Pois o valor do nome do array o
endereo do array.
Arrays como statements de funes
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++)
{
cout << "Test score #" << i + 1 << ": " << testScore[i] << endl;
}
return 0;
Vetores
27
}
Vamos torn-lo mais modular, escrevendo uma funo para atribuir valores ao array e outa funo 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);
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 funes
// arrays as parameters
#include <iostream>
using namespace std;
void printarray (int array[], int length) /*funo com 2 argumentos,um deles um array */
{
for (int n=0; n<length; n++)
cout << array[n] << " ";
cout << "\n";
}
int main ()
{
int a[] = {5, 10, 15};
printarray (a,3); //passo array como argumento
return 0;
Vetores
28
}
Este exemplo por acaso est muito curioso
Pergunta: mas agora deveramos perguntar se neste caso tnhamos uma passagem por valor ou referncia.
Quando um array passado para uma funo, a funo recebe no a cpia do array mas invs disso o endereo,
address do primeiro elemento do array, que igual ao valor do array (base).
Assim todas as modificaes que se efectuarem na funo que foi chamada iro 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;
}
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 reviso
Conceito
Da linguagem "C" tambm temos o conceito de estrutura, do qual faremos uma pequena reviso 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 heterogneos.
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 so armazenados de forma a
facilitar a identificao 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 so blocos bsicos de informao e so manipulados de maneira primitiva. Basicamente o compilador
instrui a montagem de um cdigo que manipula-as de forma a copiar, referenciar e obter posio na memria. Todas
as outras formas de tratar os dados devem ser providas pelo cdigo do programa.
Implementao
Para criar um tipo de dados composto heterogneo, basicamente, cria-se uma lista de tipos e nomes de variveis
separadas por ponto e vrgula. Podemos imaginar esta lista como um bloco de cdigo, em linguagem C, onde esto
presentes apenas as declaraes de variveis. 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 varivel composta pode ser omitido na declarao da estrutura e depois definido onde for mais
apropriado, geralmente, dentro de algum bloco de cdigo onde venha a ser usado. Podemos ver logo abaixo, o
exemplo de uma declarao 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 variveis internas de uma estrutura feito atravs do operador ponto ".", porm, quando usamos
ponteiros para guardar o endereo de uma estrutura usamos o operador seta "->". Vejamos um pequeno trecho de
cdigo:
Estrutura st;
Estrutura *pst;

st.Inteiro = 200;
pst = &st;

pst->PontoFlutuante = 23.976;
Estruturas em C++
As estruturas em C++ funcionam de modo anlogo ao apresentado em linguagem "C". A diferena, a princpio,
notvel entre elas nas duas linguagens que em "C++" o especificador struct no 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 caracterstica importante das estruturas em C++: Nesta linguagem as estruturas so
tratadas como tipos primitivos de objetos. Elas tm caractersticas semelhantes s classes, que veremos nos captulos
subsequentes.
As estruturas em C++ tambm podem conter funes alm de dados. Este fato vem da ideia de modelo de objeto que
as estruturas mantm nesta linguagem. Objetos devem ter propriedades (variveis) e mtodos (funes membro), por
isso temos a possibilidade de criar funes dentro do corpo das estruturas, com a finalidade de lidar com os dados
que elas mantm.
Estruturas
31
Construtores
Os construtores so funes que so criadas automaticamente sempre que tentamos criar um objeto. Eles funcionam
da mesma maneira que construtores de classe. A esses que so criados automaticamente so os chamados de defaut.
Se escrevermos o cdigo:
#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 instncia p1 ie com a linha Person p1;
Como as variveis membro no foram iniciadas, o valor de name est vazio e o na varivel height est um valor
qualquer que lixo!
Constructor sem argumentos
Podemos ter um construtor sem argumentos que ao contrrio do defaut constructor designa valores defaut s
variveis 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 exceo.
O construtor no retorna qualquer valor, sem exceo
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 variveis. Agora no estamos no caso de ter p1.name=??? Por mais instncias
que criemos eles vo ter sempre valores padro.
Constructor com argumentos
Termos um constructor sem argumentos um melhoramento face ao defaut constructor pois agora temos valores
defaut para as variveis membro. Porm seria melhor se consegussemos inicializar as variveis 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 tm de estar na ordem esperada
Separar o construtor prototype da implementao
#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 parmetros, apenas
necessrio dizer o tipo dos parmetros o nome no necessrio)
};

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 funo main(): declarmos 2 variveis uma int e outra string. Pedimos para a pessoa escrever o nome
e colocmos o valor na varivel string, depois pedimos a altura e colocmos na varivel int. Depois chammos o
construtor com dois argumentos e passamos as variveis anteriores como argumentos. Por fim mandmos
imprimir os valores das variveis 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 parmetros
Operadores
Os operadores realizam, como o nome sugere, operaes entre dois tipos de dados. Existem muitos operadores, mas
citaremos aqui os fundamentais e, conforme as necessidades dos tpicos posteriores, citaremos todos os demais.
Compatibilidade
Os operadores padres da linguagem "C" podem ser usados de forma semelhante na linguagem C++. Aliadas s
funcionalidades tradicionais do "C" podemos criar operaes diferentes para os operadores. Esta funcionalidade
conhecida como sobrecarga de operadores e ser descrita em captulo 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 compilao pode diminuir as
dvidas que surgem no estudo de operadores em C++.
importante entender que a linguagem deve servir de base para a criao de entidades de dados autnomas e
operveis. Logo, o compilador deve ser generalista ao enxergar operaes com tipos primitivos e tipos criados pelo
programador (classes). Por estes fatores, o compilador utiliza-se de uma interface funcional para implementao dos
recursos de operadores.
Os operadores so tratados como funes, de forma a possibilitar a alterao do seu comportamento em
determinados casos. Os operandos so tratados como argumentos de funes, enquanto que o resultado da operao
tratado como retorno da funo do operador. Esta interface faz com que possamos programar o comportamento das
Operadores
35
operaes e alter-las quando nos seja conveniente.
Entendendo o operador
Basicamente, temos dois tipos de implementao para operadores, o tipo global e o tipo membro de classe. Os dois
tipos so usados regularmente nas implementaes mais comuns. Analisaremos o tipo global, uma vez que ainda no
temos uma noo 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 parmetros, o retorno e a forma de chamar o operador que queiramos definir e
criamos uma funo que execute a operao desejada;
Inserimos o cdigo da referida funo 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 funo, sendo a sobrecarga um processo de definio da operao a ser
executada. Recebe esse nome porque todo operador j existe e a definio de uma nova funcionalidade apenas
adiciona (sobrecarrega) as habilidades anteriores do operador. Embora isto seja comum, bom lembrar que
operaes de tipos primitivos no podero ser modificadas, restando apenas a funcionalidade de criar operadores
para nossos tipos (classes).
Os argumentos
Agora vejamos como os argumentos so 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 so pontos. Em termos gerais, qualquer operador binrio (com dois argumentos) definido em
escopo global, receber a e b como primeiro e segundo argumento da funo que define o operador.
Podemos ver a chamada da seguinte forma:
c = operator+( a, b );
Operadores
36
Operadores aritmticos
Operadores aritmticos so utilizados para efetuar operaes matemticas entre dados. So 5 operadores aritmticos
em C++:
#include <iostream>
using namespace std;
int main() {
int soma = 5 + 5; // o operador '+' realiza somas.
double subtracao = 5 - 5; // o operador '-' efetua subtrao.
float multiplicacao = 5.1 * 0.5; // o operador '*' efetua
multiplicao.
char divisao = 100 / 2; // o operador '/' efetua diviso.
int modulo = 51 % 5; // retorna o resto da diviso inteira.
cout << "Resultados: " << soma << ", " << subtracao << ", " << multiplicacao << ", "
<< divisao << ", " << modulo << endl;
}
A sada desse programa gera no console o seguinte:
<source lang=cpp>
Resultados: 10, 0, 2.55, 2, 1.
O quarto resultado '2' pois 50 o cdigo decimal deste caracter.
Tipo de retorno
Voc pode realizar operaes aritmticas, obviamente, entre nmeros. Como dito no tpico anterior, voc tambm
pode realizar operaes aritmticas com os tipos char e wchar_t.
O retorno da operao ser tambm um nmero (real, inteiro ou at mesmo um caracter, conforme os tipos dos
operandos).
Diviso inteira e diviso real
Existe, para a linguagem, diferena entre uma diviso entre nmeros inteiros e entre nmeros reais (ponto flutuante).
Se voc fizer a diviso entre os inteiros 3 e 2, o resultado no ser 1.5, ser 1. J se fizer a diviso entre os nmeros
reais (em ponto flutuante) dos deles, ento sim obter 1.5.
O motivo que h 2 tipos de diviso: a inteira e a decimal.
Diviso inteira e o operador mdulo
A diviso inteira retorna o quociente da diviso sem a parte fracionria. Isso ocorre porque a linguagem efetua a
diviso enquanto o resto for maior que o divisor (logo, a diviso nunca apresentar parte fracionria).
Para obter o resto da diviso, voc pode usar o operador mdulo (%). Esse operador retorna, em vez do quociente, o
resto da diviso 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
Diviso real
A diviso real aquela efetuada entre tipos ponto flutuante ou entre ponto flutuante e inteiros/caracteres. Isso
efetuar a diviso at que o resto seja zero, ou quando o resto repetir-se indefinidamente (no caso de dzimas
peridicas como, por exemplo, 10/3).
Se quisermos que a diviso entre inteiros retorne a diviso real, deveremos efetuar uma converso explcita,
conforme o exemplo:
int num = 3;
int num2 = 2;
cout << "Resultado: " << (float) num/num2 << endl;
// o resultado foi convertido para ponto flutuante explicitamente.
Deciso e controle de fluxo
Controle de fluxo em C++
Aqui vamos criar funes que nos permitam alterar a leitura de execuo do cdigo. Ou seja, j dissemos que a
leitura de execuo do cdigo de cima para baixo (l a primeira linha de cdigo executa, l a 2 linha ---
executa,..e por a adiante)
O que agora vamos fazer e criar mecanismos para alterar esse leitura sequencial e permitir:
Execuo de cdigo de acordo com a condio
Repetio de execuo de cdigo sujeito a condio
Saltar linhas de cdigo
Deciso em C++
Em C++ os mtodos de tomada de deciso presentes na linguagem C esto disponveis para as tarefas mais
corriqueiras que o programa deve executar. Alm desta forma de controle de decises, C++ prov certas
funcionalidades relacionadas a objetos que modificam a forma como o cdigo estruturado e, por consequncia,
decidem como o programa deve se comportar em determinadas situaes. Examinemos os mtodos bsicos e
analisemos de forma simples as estruturas de deciso presentes no modelo de programao orientado a objetos, para
entender como isso poder nos ajudar a tornar o cdigo mais bem construdo.
De modo geral, a maioria das linguagens de programao existentes utiliza-se das estruturas if-else ou
switch-case.
Deciso e controle de fluxo
38
if-else
if
Se voc quer que o software execute um determinado comando somente em certas situaes, utilize if para
determinar isto. O programa vai, ento, executar a primeira linha de cdigo aps o if, se a declarao entre
parnteses for verdadeira. Exemplo:
#include <iostream>
using namespace std;
int main(void) {
int variavel;
cout << "Escreva um numero: ";
cin >> variavel;
if(variavel == 5)
cout << "A varivel igual a 5";
return 0;
}
Pode-se usar valores booleanos:
bool variavel;
if(variavel) //if ser executado se booleano for verdadeiro, como no
lhe foi atribudo valor, falso
cout << "varivel verdadeira!";
Ou, se booleano tiver que ser falso para ocorrer a execuo:
if(!variavel) // O ! faz com que s haja execuo da prxima linha se
varivel for falsa
cout << "varivel falsa!";
Mas se voc quiser que o computador execute vrias linhas aps o if se este for verdadeiro? Basta usar chaves:
if(variavel) {
cout << "A varivel verdadeira...\n";
cout << "E continua executando" <<
"at que seja fechado o if" <<
" com o }";
}
else
tambm possvel usar o bloco else para o computador executar vrias linhas de cdigo caso uma condio tenha
o valor booleano falso. Por exemplo:
if(temperatura < 20) {
cout << "Est frio";
} else {
cout << "Est calor";
}
Assumindo que a varivel temperatura tem tipo inteiro (int), se esta contiver um valor, por exemplo, 20, ser
apresentada na tela a mensagem "Est calor", uma vez que 20 < 20 uma expresso contradio, logo tem o valor
Deciso e controle de fluxo
39
booleano falso.
Podemos ainda encadear vrios else, e obter ainda mais possibilidades:
if(deposito < 20) {
cout << "Depsito de gasleo inferior a 20%";
} else if(deposito < 50) {
cout << "Tem menos de metade do depsito";
} else {
cout << "Ainda tem meio depsito ou mais";
}
Desta forma, conseguimos distinguir o nvel de depsito de gasleo de um carro em 3 nveis diferentes. Para
distinguir por mais nveis, bastaria acrescentar mais } else if(...condio...) { para distinguir os
diferentes patamares.
De notar que, cada caso avaliado individualmente, por ordem. Isto , primeiro seria verificado se o depsito tem
menos de 20% de gasleo; apenas se esta condio for falsa que o computador avalia a segunda condio, para
verificar se o depsito tem menos de 50% de gasleo, e por ainda adiante.
switch
O switch muito parecido com o if-else. Apenas a sintaxe e construo diferente
#include <iostream>
using namespace std;
int main(void)
{
char grade;
cout << "Enter your grade (A to F): ";
cin >> grade;
switch (grade)
{
case 'A':
cout << "Your average must be between 90 - 100"<< endl;
break;
case 'B':
cout << "Your average must be between 80 - 89"<< endl;
break;
case 'C':
cout << "Your average must be between 70 - 79"<< endl;
break;
case 'D':
cout << "Your average must be between 60 - 69"<< endl;
break;
default:
cout << "Your average must be below 60" << endl;
}
return 0;
}
Deciso e controle de fluxo
40
Cada um dos casos tem de ser uma constante (no pode alterar durante a vida do programa), neste exemplo A, B,

O defaut serve para a condio de todas as avaliaes dos casos anteriores der falsa. ( tipo o else)
O break serve para terminar o switch, caso contrrio se num dado case fosse verdadeiro, iria executar todos os
statementes mesmo de outros cases at terminar o switch.
Aqui para cada caso no necessitamos de {} se tivermos mais do que 2 statements.
o if-else mais forte do que o switch por que permite fazer coisas como:
if (apples == oranges)
do this;
else if (sales >= 5000)
do that;
Para alm do ponto j dito de os casos serem obrigatoriamente constantes, no switch
Tambm posso utilizar operadores lgicos no switch
switch (age >= 18 && citizen == true)
{
case true:
cout << "You are eligible to vote";
break;
case false:
cout << "You are not eligible to vote";
}
Operador condicional "?"
A sintaxe :
[Relational expression] ? [statement if true] : [statement if false]
Ou seja, este operador testa a expresso relacional e se o resultado for verdadeiro executa logo a 1 afirmao caso
contrrio executa a segunda.
ou seja isto no mais do que um if-else.
H quem goste de usar este operador porque poupa escrita, mas acho que no vale a pena!
#include <iostream>
using namespace std;
int main(void)
{
int num;
cout << "Enter a whole number: ";
cin >> num;
cout << "The number is " << (num % 2 == 0 ? "even" : "odd") << endl;
return 0;
}
Notar que o operador condicional exige 3 operandos.
vamos fazer uns exerccios:
7==5 ? 4 : 3 // returns 3, since 7 is not equal to 5.
7==5+2 ? 4 : 3 // returns 4, since 7 is equal to 5+2.
Deciso e controle de fluxo
41
5>3 ? a : b // returns the value of a, since 5 is greater than 3.
a>b ? a : b // returns whichever is greater, a or b.
O Comando goto
O goto realiza um salto para um local especificado. Este local determinado por um rtulo. Portanto pode ser em
qualquer parte do programa.
nome_do_rtulo:
....
goto nome_do_rtulo;
....
// goto loop example
#include <iostream>
using namespace std;
int main ()
{
int n=10;
loop:
cout << n << ", ";
n--;
if (n>0)
goto loop;
cout << "FIRE!";
return 0;
}
Repare no rtulo.
Nota: Evite o uso de goto quando for possvel usar estruturas principais, porque pode tornar o cdigo ilegvel. Esse
comando deve ser usado em ltimo caso, como sair de loops aninhados.
Terminando o programa
Esta funo definida com a biblioteca cstdlib (c+std+lib) O propsito da funo terminar com o programa com
um especfico cdigo de sada O prottipo :
int exit (int exitcode);
Esta funo usada por alguns sistemas operativos e podem ser usadas para chamar programas. Por conveno o
cdigo 0 se sada significa que o programa terminou normalmente, como previsto, se vier com outro nmero
significa que houve um erro e algo de inesperado sucedeu.
Estruturas de repetio
42
Estruturas de repetio
Laos (loops em ingls), ou estruturas de repetio, so comandos existentes nas linguagens de programao
destinados a executar uma ou mais instrues quantas vezes forem necessrias. Cada ciclo de um loop chamado de
iterao. Podemos ter tambm loops dentro de outro loop.
While
O while, "enquanto" em ingls, um lao que ordena o computador a executar determinadas instrues enquanto
uma condio for verdadeira. Isso faz com que um comando seja executado uma vez a cada verificao da condio.
De modo geral o comando sempre deve ser elaborado de forma que se leve a condio de execuo a ser falsa em
algum momento, de forma a interromper o lao para que o resto do programa entre em execuo.
Sintaxe
while (condio)
comando;
Onde condio a condio de execuo do lao while.
O cdigo abaixo mostra o uso do lao while para imprimir na tela do nmero 1 ao nmero 10. Perceba o uso de uma
varivel inteira intitulada contador. Esta varivel utilizada para armazenar um valor a ser impresso bem como
participar da condio de execuo do lao. Assim que a varivel atingir o valor 11 o programa segue para o
comando logo aps o lao.
#include <iostream>
using namespace std;
int main()
{
int contador; // Declara a varivel contador.
contador=1; // contador recebe o valor 1.
while (contador<=10) // Enquanto contador for menor ou igual a 10.
{
cout << contador << endl; // Imprime contador.
contador++; // Incrementa contador em uma unidade.
}
return 0;
}
Estruturas de repetio
43
Do-While
O lao do-while um while invertido, onde voc coloca as instrues a serem repetidas antes da verificao da
condio de execuo. Isso significa que os comandos do lao sero executados ao menos uma vez.
Sintaxe
do {
comando;
} while (condio);
Onde condio a condio de execuo do lao do-while. Os comandos pertencentes ao lao somente deixaro de
se repetir quando a condio for falsa.
O algoritmo abaixo mostra como seria o algoritmo exemplo usado na seo do lao while convertido para o uso do
lao do-while.
#include <iostream>
using namespace std;
int main()
{
int contador; // Declara a varivel contador.
contador=1; // contador recebe o valor 1.
do {
cout << contador << endl; // Imprime contador.
contador++; // Incrementa contador em uma unidade.
} while (contador<=10); // Enquanto contador for menor ou igual a 10.
return 0;
}
For
Como o uso de uma varivel como contador nos laos algo frequente, foi criado um outro lao que traz em sua
estrutura campos para abrigar os comandos de atribuio de valor inicial e incremento/decremento do contador. O
nome deste lao for, "para" em ingls.
Sintaxe
for ([iniciao]; [condio]; [incremento])
comando;
Onde:
iniciao: campo destinado para qualquer comando que deve ser executado, uma nica vez, logo no incio do
lao.
condio: campo destinado para a condio de parada. Esta condio verificada logo no incio do lao,
imediatamente aps a concluso do parmetro1 e a cada passo quando o <comando> executado.
incremento: campo destinado para qualquer comando que deve ser executado todas as vezes em que o lao
finalizar seu ltimo comando, em todas as suas repeties.
O algoritmo abaixo mostra o uso do lao for manipulando a varivel inteira contador de maneira imprimir uma
contagem de 1 at 10. Esse uso do lao for o mais comum pois possibilita uma repetio de comandos de nmero
Estruturas de repetio
44
fixo, dez no algoritmo em questo.
#include <iostream>
using namespace std;
int main()
{
int contador; // Declara a varivel
contador.
for (contador=1; contador<=10; contador++) // Inicia o lao.
cout << contador << endl; // Imprime contador.
return 0;
}
importante deixar claro que nenhum dos trs parmetros utilizados no lao for obrigatrio. Caso no haja
necessidade de utilizar um ou mais deles, basta deixar seu espao em branco. Como exemplo temos o algoritmo a
seguir, que demonstra um lao infinito usando for:
#include <iostream>
using namespace std;
int main()
{
for (;;)
cout << "Eu sou um lao infinito." << endl;
return 0;
}
A ausncia do 2 parmetro significa loop infinito:
for (int num =1; ; num++)
{
cout << num << " ";
}
Isto vai colocar um valor a mais no num indefinidamente.
Ausncia do 3 parmetro:
for (int num=1; num <= 10; )
{
cout << num << " ";
num++;
}
Estruturas de repetio
45
Dicas
Bloco de Comandos
Em muitos casos, os laos devem repetir dois ou mais comandos. Para isso, necessitamos criar um bloco de
comandos contendo todas as instrues a serem repetidas. A criao de um bloco de comandos simples, basta
colocar todos os comandos entre chaves { }. Os algoritmos de exemplo dos laos while e do-while fazem uso de um
bloco de comandos.
Caso o lao no encontre a abertura de um bloco logo em seguida, ele assumir que o comando imediatamente
abaixo o nico que deve ser repetido.
Exemplo 1:
while (condio)
comando1; // Este comando faz parte do lao.
comando2; // Este comando no faz parte do lao.
Exemplo 2:
while (condio)
{
comando1; // Este comando faz parte do lao.
comando2; // Este comando faz parte do lao.
}
O Comando break
O que o break faz quebrar a execuo para fora do bloco de cdigo onde ela est presente
#include <iostream>
using namespace std;
int main(void)
{
int num;
char choice;
bool quit = false;
while (true)
{
cout << "Enter a positive number: ";
cin >> num;
if (num > 0)
break;
else
{
cout << "Number must be positive; try again (Y/N): ";
cin >> choice;
if (choice != 'Y')
{
quit = true;
break;
}
Estruturas de repetio
46
}
}
if (quit == false)
cout << "The number you entered is " << num << " ";
else
cout << "You did not enter a positive number";
return 0;
}
O break faz com que a execuo do programa continue na primeira linha seguinte ao loop ou bloco
O Comando continue
Esta instruo bem parecida com o break, mas algo diferente. Pois em vez de mandar a execuo para fora do
bloco manda-a para a avaliao do loop. Ou seja faz saltar uma determinada iterao do loop, enquanto o break faz
acabar o loop
#include <iostream>
using namespace std;
int main(void)
{
int num, counter = 0, total = 0;
cout << "How many items do you want to buy: ";
cin >> num;
while (counter++ < num)
{
if (counter % 13 == 0)
continue;
total += 3;
}
cout << "Total for " << num << " items is $" << total;
return 0;
}
Neste exemplo quando o conter for mltiplo de 13, a instruo seguinte saltada total+=3
Incrementar/decrementar
Aqui vamos voltar a um tpico anterior que foi abordado nos operadores Temos
a=a+1 equivalente a ter a+=1 e ainda a ter a++
Mas isto tudo s no caso do incremento ser 1.
Podemos ter ++a ou ainda a++. Eles so parecidos mas diferentes, a questo do prefixo e ps-fixo. A diferena
que
O prefixo, faz o incremento ainda durante a instruo
O ps-fixo faz o incremento quando se passa para a instruo seguinte.
#include <iostream>
using namespace std;
int main(void)
{
Estruturas de repetio
47
int num = 2;
cout << num << \n;
cout << ++num << \n;
cout << num++ <<\n;
cout << num << \n;
return 0;
}
Portanto
int num = 5;
cout << (++num == 5);
Exerccios
Crie um programa que d o fatorial de um nmero:
#include <iostream>
using namespace std;
int main(void)
{
int num, counter, total = 1;
cout << "Enter a number: ";
cin >> num;
cout << "The factorial of " << num << " is ";
for (int counter = 1; counter <= num; counter++)
total *= counter;
cout << total;
return 0;
}
Crie um programa para o utilizador adivinhar um nmero de 0 a 3. D 3 hipteses para adivinhar. No caso de acertar
antes de chegar ao fim das 3 hipteses termine.
#include <iostream>
using namespace std;
int main(void)
{
int num, counter, secret = 3;
cout << "Guess a number between 1 and 10\n";
cout << "You have 3 tries\n";
for (int counter = 1; counter <= 3; counter++)
{
cout << "Enter the number now: ";
cin >> num;
if (num == secret)
{
cout << "You guessed the secret number!";
break;
}
}
Estruturas de repetio
48
cout << "Program over";
return 0;
}
Criao de menu.
#include <iostream>
using namespace std;
int main ()
{
int i;
do
{
cout << "\n\nEscolha a fruta pelo numero:\n\n";
cout << "\t(1)...Mamao\n";
cout << "\t(2)...Abacaxi\n";
cout << "\t(3)...Laranja\n\n";
cin >> i;
} while ((i<1)||(i>3));
switch (i)
{
case 1:
cout << ("\t\tVoce escolheu Mamao.\n");
break;
case 2:
cout <<"\t\tVoce escolheu Abacaxi.\n";
break;
case 3:
cout << ("\t\tVoce escolheu Laranja.\n");
break;
}
return(0);
}
Funes
49
Funes
Funo, do latim functio, onis, representa na computao, um pequeno algoritmo com uma funo simples e bem
definida. como se cada funo fosse um micro programa, ou um tijolo na construo do programa principal. O uso
de funes facilita muito o desenvolvimento, pois, divide o problema principal em pequenos problemas mais
simples. Essa tcnica se chama, Dividir para conquistar.
A experincia mostra que o uso de funes facilita e acelera a criao e manuteno de sistemas.
Todo programa em C++ tem pelo menos uma funo, o main. Veja o exemplo do programa em C++:
#include <iostream> //Biblioteca com funes de entrada e sada de dados
using namespace std;
int main (void) //Funo principal do programa
{
cout << "Ol mundo!"; //cout tambm uma funo, e precisa ser importada da biblioteca iostream

//Esta funo main retorna um valor int, ou inteiro, por isso faz a
operao de retornar 0
return 0;
}
Do exemplo Ol mundo, vemos que toda funo em C++ tem um nome. O nome de uma funo junto com o tipo de
dados que retorna chamado assinatura da funo.
int main (void) //Assinatura da funo main
Essa assinatura informa que a funo de nome main retorna na sua execuo um valor do tipo int, ou inteiro, e recebe
void como parmetro. Receber void significa que a funo no recebe parmetro, se a funo retorna void, significa
que no retorna nada. Algumas funes no precisam retornar nenhum valor para funcionar, apenas realizar alguma
ao.
Sobrecarga de funes
Em C++ duas funes podem ter o mesmo nome se:
Tiverem um n diferente de parmetros e/ou
Se os parmetros forem de tipos diferentes (ints floats,..)
A funo no pode ser overloaded apenas com diferentes tipo de retorno de funo (ie, uma funo retornar ints e a
outra retornar floats) ento os parmetros que interessam.
#include <iostream>
using namespace std;
void ConvertFToC(double f, double &c);
void ConvertFToC(float f, float &c);
void ConvertFToC(int f, int &c);
int main()
{
double df, dc;
float ff, fc;
Funes
50
int i_f,i_c; //if is a reserved word
df = 75.0;
ff = 75.0;
i_f = 75;
// The compiler resolves the correct
// version of ConvertFToC based on
// the arguments in each call
cout << "Calling ""double"" version" << endl;
ConvertFToC(df,dc);
cout << df << " == " << dc << endl << endl;
cout << "Calling ""float"" version" << endl;
ConvertFToC(ff,fc);
cout << ff << " == " << fc << endl << endl;
cout << "Calling ""int"" version" << endl;
ConvertFToC(i_f,i_c);
cout << i_f << " == " << i_c << endl << endl;
system ("pause");
}
void ConvertFToC(double f, double &c)
{
cout << "In ""double"" version" << endl;
c = (f - 32.0) * 5. / 9.;
}
void ConvertFToC(float f, float &c)
{
cout << "In ""float"" version" << endl;
c = (f - 32.0) * 5. / 9.;
}
void ConvertFToC(int f, int &c)
{
cout << "In ""int"" version" << endl;
c = (f - 32) * 5. / 9.;
}
O que que acontece se tivermos um n diferente de argumentos entre a chamada e a definio?
A soluo aqui proposta quando no sabemos a quantidade de parmetros que a funo vai ser chamada ou mesmo
a tipologia desses argumentos, o que se sugere fazer vrias definies para a funo e dar a todas elas o mesmos
nome, que o compilador vai saber escolher a definio correcta atravs do n e tipologia de argumentos.
Entretanto, por boa prtica, as funes no devem ser sobrecarregadas se fizerem operaes distintas.
Funes
51
Parmetros default (padro)
Pode acontecer que tenhamos que declara varia vezes o mesmo valor como parmetro de uma funo. Para
simplificar a chamada a funes que variam pouco podemos definir uma parmetro default.
#include <stdio.h>
#include <stdlib.h>
/*-----------------------------Cabealho--------------------------------*/
/*Definimos uma funao*/
void function(int a,int b, int c = 100 )
{
printf("Meu Primeiro argumento :%d\n",a );
printf("Meu Segundo argumento :%d\n",b );
printf("Meu terceiro argumento :%d\n",c );
getchar();
}
int main (void)
{
function( 10, 30);
/* Agora use a funo assim e veja o que acontece */
// function( 10,30,999);
}
Os parmetros por default devem ser os ltimos da lista, ou seja, mais direita. O parmetro padro deve ser
especificado no prottipo e no na declarao da funo.
Referncias de dados
Variveis de referncia
Em C++ podemos criar variveis que podem ser uma alternativa para os ponteiros em algumas situaes. A
vantagem de no usar diretamente o endereo (valor de ponteiro) em situaes onde no precisamos lidar
diretamente com valores de memria torna a programao mais segura e simplificada. Podemos deixar as operaes
com ponteiros apenas para quando for estritamente necessrio.
Variveis de referncia podem ser criadas para dar um nome diferente para as variveis que j existem no programa,
ou para passar a varivel para dentro do corpo de uma funo. Observemos, inicialmente, um caso simples:
int a = 10;
int &b = a;
b = 20;
Neste trecho de programa, criamos uma varivel de referncia b para a varivel a, o que significa que criamos outro
nome para a varivel a. De fato, b a prpria varivel a com outro nome, apenas isso. Desta forma, podemos alterar
o valor de a usando b.
Referncias de dados
52
Passagem de parmetros
Na linguagem "C", durante a chamada de uma funo, os argumentos (parmetros) tm seus valores copiados para a
rea de processamento da funo. Depois que os mesmos foram usados dentro do bloco de processamento da funo,
eles so descartados. A funo retorna o processamento para o bloco que a chamou trazendo apenas o valor de
retorno. A nica maneira de fazer com que a funo modifique o valor de alguma varivel definida no bloco de
programa que a chamou pass-la por um ponteiro com o seu endereo.
Vejamos o fragmento de cdigo seguinte:
int f( int x )
{
x--;
return x;
}
int main()
{
int a = 10;
int b;
b = f(a);
...
...
Em "C", a menos que o programador seja bem malicioso e faa manipulaes de memria arriscadas, a funo f
jamais alterar o valor do seu argumento x.
Diferentemente da linguagem "C", a chamada a uma funo em C++ pode alterar o valor de uma varivel definida
antes da chamada da funo, mesmo sem esta varivel ser explicitamente passada como um ponteiro. Este modo
chamado de passagem por referncia. Em termos mais gerais, significa a passagem da varivel propriamente dita,
para o corpo interno da funo com outro nome, aquele definido na lista de parmetros da funo.
Em C++, uma funo pode ser chamada na forma acima e alterar o valor das suas variveis. Para isso basta
declar-la como:
int function(int & x)
{
x--;
return x;
}
Temos em C++ o operador & que se comporta diferentemente de C, tendo uma funo a mais, a de criar variveis de
referncia:
&x quando usado no cdigo retorna o pointero para o endereo de x;
&x quando usado na declarao de varivel, cria uma referncia;
&x quando usado como parmetro na declarao de uma funo faz com que suas chamadas transfira o
argumento/parmetro passando-o de forma similar a passagem de seu pointero. (Passagem por referncia).
Em termos semnticos, ao passar a varivel para uma funo onde o parmetro uma referncia, o endereo da
varivel atribudo ao endereo do parmetro. Desta forma, o parmetro a mesma varivel passada, no trecho de
cdigo onde a funo foi invocada, assumindo um nome diferente dentro da funo.
Vejamos um exemplo usando a funo anterior:
Referncias de dados
53
int m = 4;
function(m);
cout << m << endl;
O cdigo anterior imprime na sada padro o valor 3. Acompanhando o fluxo de execuo verificamos o seguinte:
Depois que a varivel m includa na chamada da funo o seu nome muda para x e o programa passa a ser
executado dentro da funo, onde a varivel decrementada. Portanto, quando a execuo retorna para o corpo
principal a varivel estar decrementada.
Exemplo: alterando o valor da varivel usando referncia
#include <iostream>
using namespace std;
int main()
{
int val = 1;
int &ref = val;
cout << "val is " << val << endl;
cout << "ref is " << ref << endl;
cout << "Setting val to 2" << endl;
val = 2;
cout << "val is " << val << endl;
cout << "ref is " << ref << endl;
cout << "Setting ref to 3" << endl;
ref = 3;
cout << "val is " << val << endl;
cout << "ref is " << ref << endl;
system ("pause");
return 0;
}
Como se viu conseguimos alterar o valor de val alterando o valor de ref.
Existe apenas umas restries para o seu uso:
Teremos de inicializar e no momento da declarao teremos de atribuir de imediato o valor (se no fizermos isso
gerar um erro de compilao)
As referncia no podem ser reatribudas, ou seja no exemplo anterior tinha
int &ref = val; se mais tarde no cdigo tentar-se fazer int &ref=m; (sendo m uma varivel j declarada e iniciada por
hiptese) o que acontece que a 2 instruo completamente ignorada e ficamos sempre com a primeira.
A vantagem real das referncias que quando elas so usadas para passar valores para as funes elas providenciam
uma maneira de retornar valores das funes.
Vejamos o exemplo
#include <iostream>
using namespace std;
int main()
{
int val1 = 10;
int val2 = 20;
Referncias de dados
54
int &ref = val1;
cout << "val1 is " << val1 << endl;
cout << "val2 is " << val2 << endl;
cout << "ref is " << ref << endl;
ref = val2; //What does this do?
cout << endl << "ref = val2" << endl;
cout << "val1 is " << val1 << endl;
cout << "val2 is " << val2 << endl;
cout << "ref is " << ref << endl;
val2 = 30;
cout << endl << "Setting val2 = 30" << endl;
cout << "val1 is " << val1 << endl;
cout << "val2 is " << val2 << endl;
cout << "ref is " << ref << endl;
system ("pause");
return 0;
}
Exemplo: Swap
O exemplo abaixo mostra uma forma muito comum de usar referncias. A instruo "swap", que tem por objetivo
trocar os valores de duas variveis, mais naturalmente chamada como Swap(a, b) do que Swap(&a, &b); assim,
mais simples declarar a funo usando referncia:
#include <iostream>
using namespace std;
void Swap (int &i,int &j)
{
int t=i;
i=j;
j=t;
}
int main ()
{
int a,b;
a=5;
b=10;
cout<<a<<"\t"<<b;
Swap (a,b);
cout<<a<<"\t"<<b;
system ("pause");
return 0;
}
Referncias de dados
55
Comparao entre passagem por referncia e ponteiros
Para exercitar vamos criar um novo problema: Criar um funo que duplique qualquer valor colocado pelo
utilizador:
1 PROGRAMA-via referncia 2 PROGRAMA via ponteiros - endereos
#include <iostream>
using namespace std;
void doubleIt(int&);//prototype com endereo de variavel
int main ()
{
int num;
cout << "Enter number: ";
cin >> num;
doubleIt(num); //chamo funo, passando parametro num
cout << "The number doubled in main is " << num << endl;
system ("pause");
return 0;
}
void doubleIt (int& x)
{
cout << "The number to be doubled is " << x << endl;
x *= 2;
cout << "The number doubled in doubleIt is " << x << endl;
}
#include <iostream>
using namespace std;
void doubleIt(int*); //parametro por endereo
int main ()
{
int num;
cout << "Enter number: ";
cin >> num;
doubleIt(&num);//passei parametro como endereo
cout << "The number doubled in main is " << num << endl;
system (pause);
return 0;
}
void doubleIt (int* x)
{
cout << "The number to be doubled is " << *x << endl;
*x *= 2;
cout << "The number doubled in doubleIt is " << *x << endl;
}
Ou seja nestes dois cdigos temos uma passagem por referncia e outro por endereo. Com diferenas:
Na chamada da funo (dentro do main() )
doubleIt(num); // by reference
doubleIt(&num); // by address
No prototype da funo (confirmar o ponto e virgula)
void doubleIt(int&); // by reference
void doubleIt(int*); // by address
Na function header
void doubleIt (int& x) // by reference
void doubleIt (int* x) // by address
dentro do body function (dentro da prpria funo)
x
*x
Podemos pensar que passando por referncia parece ser muito mais simples do que passado por address.
Na verdade existem certas funes da biblioteca que s permitem a passagem por address.
Entrada e sada de dados
56
Entrada e sada de dados
Entrada e sada
Aqui vamos dar incio ao estudo de recursos que possibilitaro inserir dados e fazer reporte da falta deles.
No C++ a entrada e sada podem ser feitas atravs da biblioteca iostream. Para podermos us-la deveremos colocar a
linha de cdigo: #include <iostream>
A estrutura de comunicao com o meio externo em modo texto composta por um conjunto de objetos. Estas, em
conjunto com operadores e funes de formatao possibilitam uma forma de comunicao mais intuitiva. Devido
abstrao de elementos do mundo real por recursos da orientao a objetos, a forma de entender o cdigo torna-se
mais natural.
Na biblioteca iosteam, temos os seguintes objetos:
cin - Este objeto fornece entrada de dados "bufferizada" atravs do "standard input device", o dispositivo de
entrada padro;
cout - Este objeto fornece sada de dados "bufferizada" atravs do "standard output device", o dispositivo de sada
padro;
cerr - Este objeto fornece sada de dados no "bufferizada" para o standard error device, o dispositivo de erro
padro, que inicialmente definido para a tela.
clog - Este objeto fornece sada "bufferizada" atravs do "standard error device", o dispositivo de erro padro que
inicialmente definido para a tela.
O foco de orientao a objetos que a biblioteca iostream confere aos dispositivos de entrada e sada uma das
caractersticas da linguagem C++. Ele est presente na maneira na qual o cdigo foi idealizado e est formatado,
modificando a maneira como as partes do sistema de entrada/sada interagem. Desta forma, as operaes de interao
entre o usurio e o software tornam-se mais intuitivas para o programador.
O sistema de entrada e sada um exemplo deste modelo de programao, onde cada entidade fsica ou lgica de
entrada e sada representada por objetos cujas operaes podem ser acessadas diretamente nos programas.
Buffer
Para entendermos um pouco mais sobre Buffer, se faz necessrio recordar um pouco sobre o funcionamento da
memria e suas operaes relacionadas a Buffer.
Bufferizao um meio de sincronizao entre dispositivos de velocidades diferentes, tais quais memria e
dispositivos de armazenamento mecnicos, como discos magnticos. Para evitar que as operaes do dispositivo
mais lento interfiram no desempenho do programa pode-se fazer com que os dados sejam colocados em uma
memria mais rpida e depois sejam enviadas ao dispositivo mais lento a medida que ele tenha disponibilidade para
receb-los, desta forma temos os seguintes modos de escrita em dispositivos de sada:
unbuffered significa que qualquer mensagem ou dados sero escritos imediatamente. o caso da escrita no
dispositivo cerr;
buffered - significa que os dados sero mantidos num buffer de memria at que o dispositivo de destino solicite,
ou que um comando de descarregamento seja executado, ou quando o buffer estiver cheio. O problema que se o
programa interrompido antes do buffer ser escrito esses dados so perdidos.
Entrada e sada de dados
57
cout
cout << "hello"; // mostra a palavra hello no ecr(monitor)
cout << 120; // mostra o nmero 120 no ecr(monitor)
cout << hello; // mostra o contedo do pedao de memoria a que chamamos de "hello" no ecr(monitor)
cout << "hello, tenho " << age<< " anos de idade"; /* mostra a primeira string depois
vai buscar o
contedo da varivel
age de
depois a string anos de idade
*/
cout << "Primeira frase. ";
cout << "Segunda frase.\n" << "Terceira frase."; /* imprime:
Primeira frase.
Segunda frase.
Terceira frase.
*/
O cout (c+out) usado em conjugao com o operador de insero <<permite enviar dados para o "stream out" que
por definio o ecr (monitor).
Ento podemos enviar as constantes, as variveis, a conjugao das duas se nos apetecer, separadas pelo operador de
insero.
Temos ainda diversos recursos de formatao atravs de "escapes sequences" que detalharemos no tpico logo a
seguir, o recurso usado aqui concatena as vrias frases na mesma linha. Temos de dizer explicitamente "quebra de
linha", atravs do "\n", que faz com que a sequncia logo aps, seja escrita na prxima linha.
Uma caracterstica muito importante do C++, presente nas instrues logo acima, o polimorfismo notvel na
operao de apresentao dos dados na sada; Note que os tipos de dados que so passados para o cout so diversos,
ou seja, no importa qual o tipo de dado que ser entregue ao cout, de alguma maneira ele sempre formatar de uma
maneira legvel no monitor. Nos captulos mais adiante veremos como fazer com que tipos de dados diferentes sejam
tratados pelo mesmo objeto.
Escape Sequences
H um conjunto de caracteres, ns chamamos de string. Mas no exemplo anterior quando usamos o "\n", ns antes
dissemos que o cout com o operador << iria colocar no monitor todos os caracteres que estivessem entre aspas.
Acontece que existem estas strings especiais chamadas de "escape sequences" - que de alguma forma alteram o
sentido das strings. Existem muitas destas sequncias. As mais conhecidas so estas:
Escape Sequences (as mais comuns)
\n nova linha muda o cursor para uma linha abaixo
\r retorno
\t tabulador muda o cursor para o prximo ponto de tabulao
\v tabulador vertical
\b deleo reversa
\f alimentador de pgina
\a alerta (bipe) faz o computador emitir um sinal sonoro
\' aspas simples (') imprime aspas simples
\" aspas duplas (") imprime aspas duplas
\? sinal de interrogao (?)
Entrada e sada de dados
58
\\ barra oposta (contrabarra) (\)
cin
O objeto cin obtm informao do "standard input" (que usualmente o teclado). Este objeto est tal como o cout
declarado no cabealho da biblioteca <iostream>
A sintaxe mais comum da instruo para obter dados do cin :
cin >> [variable name];
Aqui temos o operador de extrao ">>" que diz que tudo o que o teclado escrever, coloque esses dados na varivel
que me segue. Este operador consegue at traduzir o conceito de dados de fora para dentro.
#include <iostream>
using namespace std;
int main(void)
{
int testScore;
cin >> testScore;
cout << "Your test score is " << testScore << "\n";
#ifdef WIN32
system ("pause"); /* Necessrio apenas para sistemas Microsoft, em
modo grfico.
Em UNIX, variantes e similares use um terminal
de texto e
esta funo no ser necessria. */
#endif
return 0;
}
H mais um pormenor. O computador est espera de um "Return" ("ENTER", ou "New Line", ou Espao em
Branco ) para finalizar a entrada de dados na varivel, at l o cursor aparece a piscar.
Bem, na verdade, este ponto muito importante, por que Vejamos mais a baixo a questo de termos 2 entradas.
Pergunta: declaramos uma varivel int testScore e se colocarmos um valor que no seja um int? Isto no a mesma
situao do captulo anterior porque antes o programa ainda no tinha compilado, e agora temos entrada de dados
quando o programa j est compilado e a correr/rodar.
Assim se no exemplo anterior colocarmos o nome Jeff, que uma string, e o programa est a espera de um int, o
que acontece que o cin no vai colocar "jeff" na varivel (ele ignora a entrada). E quando o cout chamado ele vai
colocar o valor que est na varivel.
Ento porque que me apareceu o nmero 858993460 quando corri/rodei o programa? que na memria fsica do
computador existem dados da rea onde a varivel est alocada fisicamente, e quando declarei o testScore o
compilador apenas reserva aquela memria mas no apaga o que l est.
Pergunta: O que que acontece quando inserimos um nmero maior do que o limite do tipo quando o programa
executar? o caso de "overflow" - estouro de memria, mas quando o programa corre/roda.
Entrada e sada de dados
59
Aqui j no temos a questo de dar a volta ao intervalo permitido, aqui temos o caso em que vai ser colocado um
nmero estranho. Isto no est perfeitamente explicado.
Chama-se prompt quando dito ao utilizador o que deve fazer, o que no deixar como no exemplo anterior o cursor
a piscar sem o utilizador saber o que fazer. Alm de que temos o problema de overflow em execuo, portanto bom
que o utilizador cumpra os requerimentos.
De uma maneira muito conveniente, os dados recebidos pelo cin so tratados de forma a tornar o processo
polimrfico, da mesma forma que no caso de cout, assim temos como receber os dados da maneira que precisamos,
ou seja, quando declaramos uma varivel int e a usamos para receber um dado do cin, o mesmo convertido na
entrada para inteiro, quando usamos uma varivel de outro tipo, a entrada convertida para o tipo da varivel.
Lendo um caractere
Ler um caractere at simples, basta utilizar o objeto cin e ser guardado o valor digitado na varivel.
char nivel;
cout << "Entre um nvel: ";
cin >> nivel;
Porm teremos de pressionar a tecla ENTER depois de digitar o caractere. Isto leva a vrias questes.
O problema pressione uma tecla para continuar...
#include <iostream>
using namespace std;
int main(void)
{
char ch;
do {
cout << "Pressione S ou s para sair, qualquer outra tecla para continuar: ";
cin >> ch;
if (ch != 'S' && ch != 's')
cout << "Deseja continuar?"<<endl;
else
cout << "Saindo..."<<endl;
} while (ch != 'S' && ch != 's');
#ifdef WIN32
system ("pause");
#endif
return 0;
}
O programa funciona bem se pressionarmos S ou s para sairmos;
O programa funciona bem se pressionarmos qualquer outra tecla com caractere imprimvel;
Mas se pressionarmos a tecla ENTER, nada acontece, o cin continua espera de entrada. A razo o operador de
extrao ">>" ignora os espaos em branco e os caracteres "nova linha" resultantes do pressionamento da tecla
enter.
Entrada e sada de dados
60
A funo cin.get()
J tivemos oportunidade para discutir a funo getline (funo membro) do objeto cin.
cin.getline(name,80);
Aqui vamos utilizar uma outra funo, a cin.get().
Esta funo pode ser chamada, tal como a getline(), atravs de 3 argumentos, onde o primeiro o array de caracteres,
mas tambm o pode ser sem argumentos ou ainda apenas um argumento.
No caso de no conter argumentos apenas ir ler um caractere, em vez de uma cadeia de caracteres.
No caso de ter um argumento, ela aceita qualquer tecla incluindo o enter. (o que no se passa com o cin e o operador
de extrao). Aqui um exemplo
#include <iostream>
using namespace std;

int main(void)
{
char ch;
do {
cout << "Pressione S ou s para sair, \nqualquer outra tecla para continuar: ";
cin.get(ch);
if (ch != 'S' && ch != 's')
cout << "Deseja continuar?"<<endl;
else
cout << "Saindo..."<<endl;
} while (ch != 'S' && ch != 's');
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Porm se pressionarmos uma tecla de caractere imprimvel, no conseguiremos inserir o prximo prompt, parece que
houve um salto. Estranho!
Para explicar a razo deste novo problema necessitamos de explicar o conceito de buffer.
O "input buffer" uma rea de memria que guarda os caracteres de entrada, por exemplo do telado, at que essa
entrada seja atribuda pelo cin e o operador de extrao >>, ou por funes como get() ou getline() do objeto cin.
Quando o loop comea, o "input buffer" est vazio.
Se digitarmos apenas o enter, sendo este o primeiro e nico caractere no "imput buffer", ele removido do input
buffer e atribudo varivel ch, ento o "input buffer" est vazio na prxima iterao do loop;
Se digitarmos x e enter. Temos 2 caracteres. A funo get() retira o primeiro caractere do "input buffer" e atribui
varivel ch, mas nisto o caractere nova linha permanece no "input buffer". Isto faz com que na prxima iterao
do loop, no haja a oportunidade para entrar com dados.
Entrada e sada de dados
61
Ou seja, na segunda iterao, retirado o caractere nova linha que ficou da 1 iterao - e colocado na varivel
ch. Agora o "input buffer" est vazio.
cin.ignore()
Uma soluo limpar o caractere nova linha do "input buffer" antes da chamada da funo getline(). E fazemos isso
usando a funo ignore() do objeto cin.
Esta funo membro tal com a get() e a getline() so sobrecarregadas, podem ser chamadas sem argumentos, com um
ou dois argumentos.
Utilizar a funo ignore() sem argumentos, permite que o prximo caractere no "input buffer" seja lido e depois
descartado,- e isto exatamente aquilo que queramos.
A funo com 1 ou 2 argumentos usada para cadeias de caracteres.
Com um argumento, o argumento o nmero mximo de caracteres a ser removido do "input buffer". Exemplo:
cin.ignore(80); // Remove at 80caracteres do input buffer
Com dois argumentos, o segundo argumento o delimitador, um caractere que se encontrado, antes do nmero de
caracteres especificado no primeiro paramento, faz com que a remoo pare. Exemplo:
cin.ignore (80, '\n'); // Remove 80 caracteres se at l no encontrar
o nova linha.
Reescrevendo o cdigo anterior utilizando o cin.ignore()
#include <iostream>
using namespace std;
int main(void)
{
char ch;
do {
cout << "Pressione S ou s para sair,\n qualquer outra tecla para continuar: ";
cin.get(ch);
cin.ignore();
if (ch != 'S' && ch != 's')
cout << "Deseja continuar?"<<endl;
else
cout << "Saindo..."<<endl;
} while (ch != 'S' && ch != 's');
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Ora este programa funciona muito bem, MAS
Entrada e sada de dados
62
Se pressionarmos a tecla Enter para continuar, teremos de fazer isso duas vezes, pois a primeira vez ignorada. A
razo: que no existe nada no "input buffer" quando a funo ignore chamada, por isso que a tecla enter
necessita de ser pressionada 2 vezes, colocando um caractere nova linha a mais no "buffer" para a funo ignore()
remover.
Se tentarmos modificar isto atravs do if?
#include <iostream>
using namespace std;
int main(void)
{
char ch;
do {
cout << "Pressionar S ou s para sair,\n qualquer outra tecla para continuar: ";
cin.get(ch);
if (ch != '\n')
cin.ignore();
if (ch != 'S' && ch != 's')
cout << "Deseja continuar?"<<endl;
else
cout << "Saindo..."<<endl;
} while (ch != 'S' && ch != 's');
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Agora sim temos todos os problemas resolvidos e isto agora funciona!!
cin, cin.get(), cin.getline()
O problema anterior do caractere nova linha permanece quando usamos o cin, o get() e o getline() juntos num
programa, uma vez que o enter usado para terminar a entrada.
#include <iostream>
using namespace std;
int main(void)
{ char name[80];
int courseNum;
cout << "Informe o nmero do curso: ";
cin >> courseNum;
cout << "Informe seu nome: ";
cin.getline(name, 80);
Entrada e sada de dados
63
cout << "O nmero do curso : " << courseNum << endl;
cout << "Seu nome : " << name << endl;
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Aqui, neste exemplo, ns no tivemos a oportunidade de colocar o nome. Quando digitamos o nmero e depois
pressionamos a tecla enter, o cin coloca o nmero no courseNUm mas o caractere nova linha permanece no "input
buffer", que fica para o enter name, pois o getline l espaos em branco.
A soluo pode ser:
#include <iostream>
using namespace std;
int main(void)
{
char name[80];
int courseNum;
cout << "Informe o nmero do curso: ";
cin >> courseNum;
cin.ignore();
cout << "Informe seu nome: ";
cin.getline(name, 80);
cout << "O nmero do curso : " << courseNum << endl;
cout << "Seu nome : " << name << endl;
#ifdef WIN32
system ("pause");
#endif
return 0;
}
A partir destes exemplos podemos criar umas regras:
1. Colocar sempre a funo ignore() depois do cin e do >>;
Razo: O "cin>>" deixa sempre o nova linha no "input buffer". Assim devemos elimin-lo com a funo
ignore().
2. 2. No colocar a funo ignore(), no caso de ser sem parmetros, depois do getline();
Razo:O getline() remove o caractere nova linha que termina a entrada do "input buffer", portanto no
necessrio o ignore().
3. 3. Verificar se temos o caractere nova linha no "input buffer" depois de utilizar o get(), se tivermos deveremos
utilizar o ignore().
Entrada e sada de dados
64
Razo: A funo get() com um argumento deixa o caractere nova linha no "input buffer" se pressionarmos
um caractere e o enter. mas no deixar, se apenas pressionarmos o enter. portanto necessrio confirmar.
Entrada de valores para variveis mltiplas
Podemos fazer com que o programa receba vrios valores ao mesmo tempo
cin >> [first variable] >> [second variable] >> [third variable];
Neste caso o utilizador separa os dados por espaos (o enter tambm d) e como anteriormente o utilizador fecha
utilizando o enter
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
int peso, altura;
string nome;
cout << "escreva o seu nome, peso e altura \n separe os valores por espaos\n";
cin >> nome >> peso >> altura;
cout << "o seu nome :" << nome << "\n";
cout << "o seu peso :" << peso << "\n";
cout << "a sua altura : " << altura<< "\n";
#ifdef WIN32
system ("pause"); /* Necessrio apenas para sistemas Microsoft, em
modo grfico.
Em UNIX, variantes e similares use um terminal
de texto e
esta funo no ser necessria. */
#endif
return 0;
}
Note-se que no exemplo anterior poderamos colocar as 3 variveis, mesmo no caso de elas serem de tipos
diferentes. Temos de ter ateno na ordem de entrada.
Pergunta: se escrevssemos duas palavras para o nome, apenas a primeira que apareceria a 2 palavra que estava
separada da primeira para um espao seria colocada na varivel peso.
Entrada e sada de dados 2
65
Entrada e sada de dados 2
Entrada/Sada em ficheiros (arquivos)
Nota introdutria: Este capitulo geralmente colocado uns captulos mais para o fim, mas acho por bem que se
torne as coisas mais interativas, o que possvel introduzindo agora operaes em arquivos, d muito mais
entusiasmo. Encontramos aqui conceitos avanados mas podero ser deixados para depois se o leitor no quiser
observar o tema neste momento.
Gravar (Salvar) os dados para um ficheiro(arquivo)
Os dados que mantemos nos programas esto guardados na memria RAM, que limpa quando o programa ou
computador para de funcionar. Isso implicaria que perderamos toda a informao! Porm existe uma maneira para
tornar os dados persistentes que gravar os dados num ficheiro (arquivo) no "hard drive" (disco rgido) ou no outro
meio persistente. Nas formas mais diretas de escrita podemos passar os dados em formato binrio para o
ficheiro(arquivo). Outros meios avanados para guardar dados podem envolver bases de dados relacionais ou XML.
O que um ficheiro(arquivo)?
Um arquivo uma coleo de dados que esto localizados numa memria persistente tipo hard drive, cd-rom, etc.
Para identificarmos o arquivo podemos atribuir-lhe um nome (filename). Os "filenames" tm usualmente uma
extenso, que determina o tipo de arquivo em sistemas operacionais semelhantes aos da Microsoft

, mas que podem


ser dispensados em sistemas operacionais que guardam as caractersticas dos arquivos no meio de armazenamento,
tais quais sistemas UNIX

e seus similares GNU/Linux, FreeBSD, etc... A extenso representada por 3 ou 4 letras
que seguem aps o nome do arquivo e um ponto ".". Por exemplo: "joao.doc" ou "joao.odt". Isto diz-me que temos
um ficheiro(arquivo) que se chama "joao", e que tem a extenso .doc que refere usualmente a documentos do WORD
no primeiro caso e com extenso ".odt" do OpenOffice no segundo. Outros tipos de extenses podem ser ".xls" para
documentos EXCEL, ".ods" para planilhas do OpenOffice. ou ainda ".cpp" para ficheiros(arquivos) de cdigos de
c++.
Ficheiros(Arquivos) binrios e tipo texto
Existem na verdade dois tipos de ficheiros(arquivos): os do tipo texto e os do tipo binrio.
Os arquivos tipo texto apenas armazenam texto obedecendo uma codificao de caracteres, a mais comum a
ASCII, isto implica no uso do cdigo para armazenamento, ou seja, pode ser que a codificao seja interpretada
antes de ser efetivada no meio de armazenamento.
Os arquivos binrios podem guardar mais informao, como imagens, base de dados, programasPor exemplo,
editores de texto com formatao, como o OpenOffice e o Word, guardam os seus arquivos em formatos binrios,
porque eles possuem alm do texto, informao acerca da formatao do texto, para as tabelas, as listas
numeradas, tipo de fonte, etc... da aparecerem os caracteres de formatao tipo 6, L, h5
Os arquivos binrios podero ser mais bem explorados em um tpico avanado, vamos trabalhar inicialmente com
arquivos tipo texto, que poderemos operar de maneira mais simplificada.
Entrada e sada de dados 2
66
biblioteca padro fstream
At agora temos usado a biblioteca iostream (i de input + o de output + stream), que suporta, entre vrias
funcionalidades, o objeto cin para ler da "standard input" (que usualmente o teclado) e o objeto cout para "standard
output" (que usualmente o monitor)
Ora, agora queremos ler e escrever para ficheiros(arquivos) e isso requer a biblioteca fstream (f de file + stream).
Esta biblioteca define 3 novos tipos de classe:
ofstream (apenas para sada "out to a file". serve para criar, manipular ficheiros (arquivos) e escrever, no serve
para ler).
ifstream (apenas para entrada "in from a file" . serve para ler ficheiros (arquivos), receber dados dos mesmos,
no serve para criar nem escrever).
fstream (este conjuga os dois tipos anteriores, "input and output to file". cria ficheiros (arquivos), escreve e l
informao dos mesmos.
Abrir um ficheiro(arquivo)
Um ficheiro(arquivo) deve ser aberto pelo programa para que o mesmo possa ser manipulado, a abertura do arquivo
implica, entre outras coisas, em atribuir um identificador que nos permita ter acesso aos seus dados. necessrio
criar uma linha de comunicao entre o arquivo e o objeto stream.
Podemos recorrer a dois mtodos para abrir um ficheiro (arquivo):
1. 1. Usando um construtor;
2. 2. Usando a funo membro chamada de "open".
Usando o Construtor
O construtor uma funo que automaticamente chamada quando tentamos criar uma instncia de um objeto.
fstream afile; // criado uma instncia do fstream chamada
de afile
Os construtores de objetos podem ser sobrecarregados, ou seja, para a mesma classe podemos ter um construtor sem
argumentos, com um argumento, dois argumentos, etc. No exemplo anterior criamos um sem argumentos. Os
construtores no retornam valores, geralmente o compilador reporta erro quando se declara funes que retornam
valor e estas tm o mesmo nome da classe, pois este nome reservado para os construtores. Vamos dar um exemplo
com dois argumento:
ofstream outfile ("joao.doc", ios::out);
Chama o construtor com dois argumentos, criando uma instncia de ofstream e abrindo o ficheiro(arquivo)
"joao.doc" para operaes de sada.
Usando a funo membro "open"
Esta funo tem como primeiro argumento o nome e localizao do ficheiro/(arquivo) a ser aberto, o segundo
argumento especifica o modo de abertura.
Sobre a questo da localizao existem 2 tipos, o "path" relativo e o "path" absoluto. Para este ltimo indicamos o
caminho todo: "c:\\....\\joao.doc" em sistemas Microsoft

ou "/home/joao/joao.odt" para sistemas UNIX

e
similares. O "path" relativo dispensa essa descrio se o ficheiro/(arquivo) estiver (na mesma directoria)/(no mesmo
diretrio) que o programa.
Sobre a questo do modo de abertura temos as seguintes modalidades:
Entrada e sada de dados 2
67
Modo do
abertura
sinalizador
(Flag)
Descrio
ios::app "Append
mode"
Todos os dados do arquivo so preservados e qualquer sada escrita a partir do fim do arquivo.
ios::ate Se o arquivo j existe,o programa vai diretamente ao seu fim.O modo de escrita ento feito de forma
aleatria.Usado normalmente com arquivos do modo binrio(binary mode).
ios::binary "Binary
mode"
Informaes so escritas na forma binria e no na forma textual(text mode).
ios::in "Input mode" Leitura de informaes de arquivo(no ir criar um arquivo novo)
ios::out "Output
mode"
Informaes sero escritas no arquivo.
ios::trunc Se o arquivo j existe,suas informaes sero truncadas, outra forma de se dizer: deletadas e reescritas.
Os sinalizadores (flags) so nmeros em potncias da base binria, portanto podemos ter vrios flags ao mesmo
tempo se usarmos o operador unrio para a operao "OU", como no exemplo abaixo:
ofstream outfile; //crio o objeto outfile
outfile.open("students.dat", ios::binary | ios::app); /*chamo a funo
membro open do objeto,
com o 1
parmetro que o nome do arquivo
e o 2 o modo
de abertura. */
Observe que estamos abrindo o arquivo "students.dat" em modo binrio e ao mesmo tempo com o modo "append",
isto significa que abriremos o arquivo e poderemos preservar o seu contedo anterior inserindo os novos dados no
fim do arquivo.
Comparando os dois mtodos (pela funo membro e pelo construtor)
O primeiro mtodo similar a ter
int age;
age=39;
O segundo mtodo similar a
int age=39;
A escolha do melhor mtodo em cada situao depende do contexto em que estamos criando o cdigo, geralmente
quando j temos o objeto criado e ele est fechado podemos abrir um novo arquivo com ele e depois fech-lo
novamente, isto nos sugere que usemos a funo open quando o objeto deve abrir arquivos diferentes em cada trecho
de cdigo, embora que possam surgir outras funcionalidades, dependendo de como o projeto foi idealizado.
Entrada e sada de dados 2
68
Abrir um arquivo para leitura
A histria aqui a mesma s tem uma diferena: que no caso de leitura, no ser criado nenhum ficheiro (arquivo)
caso ele no exista.
ifstream arq; //cria objeto "arq"
arq.open (joo.doc); //chama funo membro open ao objeto
"arq", com o
//parmetro do nome do ficheiro
Poderamos fazer o mesmo com o construtor:
ifstream arq (joo.doc);
Ou ainda
fstream bloco;
bloco.open("joao.doc", ios::in)
ou ainda
fstream b(joao.doc, ios::in)
H mais uma nota a fazer, se quisermos ler e escrever, no podemos usar o ofstream e o ifstream ao mesmo tempo,
teremos de usar o fstream. Teremos de fazer:
fstream a (joo.doc, ios::in | ios::out);
Neste caso, o comportamento padro preservar o contedo do ficheiro (arquivo) ou cri-lo caso ele no exista.
Verificar se o ficheiro (arquivo) foi aberto.
Vamos verificar o que acontece quando tentamos abrir um arquivo que no existe, a primeira verso do nosso
exemplo observa o comportamento bsico do fstream:
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
ifstream arq; //crio objeto "arq" da classe
ifstream - leitura
arq.open("joao.doc"); //chamo funo membro open
cout << "(arq) = " << arq << endl; //imprime o objeto
cout << "(arq.fail()) = " << arq.fail() << endl; //chamo funo membro fail
#ifdef WIN32
system ("pause");
#endif
return 0;
Entrada e sada de dados 2
69
}
No caso do ficheiro (arquivo) joao.docno existir:
(arq) = 00000000
(arq.fail()) = 1
No caso do ficheiro (arquivo) joao.docexistir no mesmo diretrio que o programa:
(a) = 0012FE40
(a.fail()) = 0
Repare que o resultado a impresso do endereo, do objeto a de ifstream. d um ponteiro!!
Agora, vajamos um exemplo mais completo:
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
ifstream arq; //crio objeto "arq" da classe
ifstream - leitura
string str;
arq.open("joao.doc"); //chamo funo membro open
if (arq.is_open() && arq.good())
{
arq >> str;
cout << "contedo: \n " << str << endl; //imprime o contedo do arquivo
arq.close();
}
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Observe que aqui verificamos se o arquivo foi aberto com a funo membro is_open() que retorna verdadeiro "true"
caso o arquivo foi aberto, depois verificamos se o arquivo foi aberto satisfatoriamente atravs da funo membro
good(), que tambm retorna verdadeiro se o arquivo pode ser usado.
Entrada e sada de dados 2
70
Fechar um ficheiro (arquivo)
Devemos fechar depois de ler e/ou escrever. Mas por que, se o objeto do ficheiro ir ser fechado assim que o
programa acabar? Porque estamos a utilizar recursos com um ficheiro (arquivo) aberto, porque alguns sistemas
operativos (operacionais) limitam o n de ficheiros (arquivos) abertos, e estando este aberto impede que outros se
possam abrir e por fim porque se no fecharmos, outros programas no podero abri-lo at que o fechemos. Este
comportamento faz parte de um esquema de controle de acesso usado pelo sistema para assegurar que os arquivos
no sero usados por processos diferentes ao mesmo tempo.
ofstream outfile;
outfile.open("students.dat");
// ....
outfile.close();
Vamos criar um exemplo mais real. Queremos criar um programa que escreva informao inserida pelo utilizador
num ficheiro por ns escolhido
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
char data[80]; //criamos um array de 80 caracteres
ofstream outfile; //criamos objeto da classe ofstream
outfile.open("joao.doc"); //chamamos a funo membro da classe
para o objeto criado.
// Esta funo membro cria o arquivo
"joao.doc"
if (outfile.is_open() && outfile.good()) //verificamos se est tudo
bem
{ cout << "digite o seu nome: "; //imprime no ecr (monitor) a frase
cin.getline(data, 80); //chama funo membro getline
do objeto cin para
//ler o que foi escrito pelo
usurio
outfile << data << endl; //coloca o array no objeto criado.
outfile.close(); //fechamos o objeto.
}
#ifdef WIN32
system ("pause");
#endif
return 0;
Entrada e sada de dados 2
71
}
Podemos ir ver o novo ficheiro/arquivo com o nome joao.doc e tem l escrito aquilo que digitamos.
Agora vamos tentar ler o que escrevemos no documento criado.
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
char data[80];
ifstream infile;
infile.open("joao.doc");
if (infile.is_open() && infile.good()) //verificamos se est tudo bem
{ infile >> data; //colocamos os dados abertos no array
cout << data << endl;
infile.close();
}
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Repare que se tivssemos escrito duas palavras, apenas uma era apresentada (ela pra no primeiro whitespace), para
isso necessitaramos de repetir:
#include <fstream>
#include <iostream>
using namespace std;
int main ()
{
char data[80];
ifstream infile;
infile.open("joao.doc");
if (infile.is_open() && infile.good()) //verificamos se est tudo bem
{ infile >> data; //colocamos os dados abertos no array
cout << data << endl;
infile >> data; //colocamos os dados abertos no array
cout << data << endl;
infile.close();
}
#ifdef WIN32
system ("pause");
#endif
Entrada e sada de dados 2
72
return 0;
}
Agora j obtemos 2 palavras e so apresentadas em linhas diferentes. Mas temos de arranjar um mtodo para no
estar a repetir constantemente, podemos fazer isso com
infile.getline(data, 80);
Ento ficamos com:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string data;
ofstream outfile;
outfile.open("joao.doc");
if (outfile.is_open() && outfile.good()) //verificamos se est tudo
bem
{
cout << "Writing to the file" << endl;
cout << "===================" << endl;
cout << "Enter class name: ";
getline(cin, data);
outfile << data << endl;
cout << "Enter number of students: ";
cin >> data;
cin.ignore(); //esta funo membro para limpar o
caractere
//newline do inputbuffer depois de usar
o objeto
//cin com o operador de extrao >>
outfile << data<< endl;
outfile.close();
}

ifstream infile;
infile.open("joao.doc ");
if (infile.is_open() && infile.good()) //verificamos se est tudo
bem
{ cout << "Reading from the file" << endl;
cout << "=====================" << endl;
getline(infile, data);
cout << data << endl;
Entrada e sada de dados 2
73
getline(infile, data);
cout << data << endl;
infile.close();
}
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Looping pelo ficheiro (arquivo).
E se no soubermos quantas linhas tem o arquivo? O objeto ifstream tem uma funo membro que a eof()
(e-end+o-of+f-file). Esta funo no tem parmetros e retorna "true" se o fim do arquivo for alcanado e "false" caso
contrrio. No entanto, esta funo eof() no de confiana com os ficheiros (arquivos) texto como o para os
binrios ( que nos ficheiros (arquivos) binrios no existem espaos em branco).
A melhor alternativa usar a funo membro fail().
ifstream infile;
infile.open("joao.doc");
if (infile.is_open() && infile.good())
{ infile >> data;
while(!infile.fail())
{ infile >> data;
cout << data;
}
infile.close();
}
Refazendo tudo
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string data;
ofstream outfile;
outfile.open("joao.doc");
if (outfile.is_open() && outfile.good())
Entrada e sada de dados 2
74
{
cout << "Escrevendo no arquivo" << endl;
cout << "===================" << endl;
cout << "Informe o nome da classe: ";
getline(cin, data);
outfile << data<< endl;
cout << "informe o nmero de estudantes: ";
cin >> data;
cin.ignore();
outfile << data<< endl;
outfile.close();
}
ifstream infile;
infile.open("joao.doc");
if (infile.is_open() && infile.good())
{
cout << "Lendo do arquivo" << endl;
cout << "=====================" << endl;
getline(infile, data);
while(!infile.fail())
{
cout << data << endl;
getline(infile, data);
}
infile.close();
}
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Agora vamos fazer o nosso programa mais modular:
1. . writeFile para abrir um arquivo para escrita usando o ofstream e
2. 2. . readFile - ler do ficheiro (arquivo) usando o ifstream
3. 3. . Cada funo ir verificar se o ficheiro (arquivo) foi aberto com sucesso
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
Entrada e sada de dados 2
75
bool writeFile (ofstream&, char*);
bool readFile (ifstream&, char*);
int main ()
{
string data;
bool status;
ofstream outfile;
status = writeFile(outfile, "students.dat");
if (!status)
{
cout << "Arquivo no pode ser aberto para escrita.\n";
cout << "Programa terminando...\n";
return 0;
}
else
{
cout << "Escrevendo no arquivo" << endl;
cout << "===================" << endl;
cout << "Informe o nome da classe: ";
getline(cin, data);
outfile << data<< endl;
cout << "Informe o nmero de estudantes: ";
cin >> data;
cin.ignore();
outfile << data<< endl;
outfile.close();
}

ifstream infile;
status = readFile(infile, "students.dat");
if (!status)
{
cout << "O arquivo no pode ser aberto para leitura.\n";
cout << "Programa terminando...\n";
return 0;
}
else
{
cout << "Lendo do arquivo" << endl;
cout << "=====================" << endl;
getline(infile, data);
while(!infile.fail())
{
cout << data << endl;
Entrada e sada de dados 2
76
getline(infile, data);
}
infile.close();
}
#ifdef WIN32
system ("pause");
#endif
return 0;
}
bool writeFile (ofstream& file, char* strFile)
{
file.open(strFile);
return !(file.fail()||!file.is_open()||!file.good());
}
bool readFile (ifstream& ifile, char* strFile)
{
ifile.open(strFile);
return !(ifile.fail()||!ifile.is_open()||!ifile.good());
}
Manipuladores
Os objetos das classes "stream" podem ser configurados para fornecer e reportar os dados de maneira pr-formatada.
Da mesma maneira que temos a formatao quando usamos funes de formatao, como printf() e scanf(), na
linguagem C, podemos usar os manipuladores na linguagem C++ para informar os objetos streams em que formato
desejamos receber os dados deles ou fornecer para eles.
Abaixo temos uma srie de manipuladores teis:
Manipulator Uso
boolalpha Faz com que variveis tipo bool sejam reportadas como "true" ou "false".
noboolalhpa (padro) Faz com que variveis tipo bool sejam reportadas omo 0 ou 1.
dec (padro) Determina que variveis tipo inteiras (int) sejam reportadas na base 10.
hex Determina que variveis tipo inteiras (int) sejam reportadas em hexadecimal.
oct Determina que variveis tipo inteiras (int) sejam reportadas em octal.
left Faz com que textos sejam justificados a esquerda no campo de sada.
right Faz com que textos sejam justificados a direita no campo de sada.
internal Faz com que o sinal de um nmero seja justificado a esquerda e o nmero seja justificado a direita.
noshowbase (padro) Desativa a exibio do prefixo que indica a base do nmero.
showbase Ativa a exibio do prefixo que indica a base do nmero.
noshowpoint (padro) Mostra o ponto decimal apenas se uma parte fracionria existe.
showpoint Mostra o ponto decimal sempre.
Entrada e sada de dados 2
77
noshowpos (padro) Nenhum sinal "+" prefixado em nmeros positivos.
showpos Mostra um sinal "+" prefixado em nmeros positivos.
skipws (padro) Faz com que espaos em branco, tabulaes, novas linhas "\n" sejam descartados pelo operador de entrada >>.
noskipws Faz com que espaos em branco, tabulaes, novas linhas "\n" no sejam descartados pelo operador de entrada >>
fixed (padro) Faz com que nmeros com ponto flutuante sejam mostrados em notao fixa.
Scientific Faz com que nmeros com ponto flutuante sejam mostrados em notao cientfica.
nouppercase (padro) 0x mostrado para nmeros em hexadecimal e para notao cientfica.
uppercase 0X mostrado para nmeros em hexadecimal e para notao cientfica.
Ajustando a largura da entrada/sada
setw(w) - Ajusta a largura da sada e entrada para w; precisa ser includo.
width(w) - Uma funo membro das classes iostream.
Preenchimento de espaos em branco
setfill(ch) - Preenche os espaos em branco em campos de sada com ch; precisa ser includo.
fill(ch) - Uma funo membro das classes iostream.
Ajustando a preciso
setprecision(n) - Ajusta a preciso de casas decimais em nmeros com ponto flutuante, para n dgitos. Este ajuste
apenas visual, de forma que o manipulador no afeta o modo de clculo do nmero pelo programa.
Exemplificando o uso de manipuladores:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
int intValue = 15;

cout << "Nmero inteiro" << endl;
cout << "Padro: " << intValue << endl;
cout << "Octal: " << oct << intValue << endl;
cout << "Hexadecimal: " << hex << intValue << endl;
cout << "Ativando showbase " << showbase << endl;
cout << "Decimal: " << dec << intValue << endl;
cout << "Octal: " << oct << intValue << endl;
cout << "Hexadecimal: " << hex << intValue << endl;
cout << "Desativando showbase " << noshowbase << endl;
cout << endl;

double doubleVal = 12.345678;

cout << "Nmeros com ponto flutuante" << endl;
Entrada e sada de dados 2
78
cout << "Padro: " << doubleVal << endl;
cout << setprecision(10);
cout << "Preciso de 10: " << doubleVal << endl;
cout << scientific << "Notao cientfica: " << doubleVal << endl;
cout << uppercase;
cout << "Caixa alta: " << doubleVal << endl;
cout << endl;

bool theBool = true;

cout << "Booleano" << endl;
cout << "Padro: " << theBool << endl;
cout << boolalpha << "BoolAlpha ativo: " << theBool << endl;
cout << endl;

string myName = "John";

cout << "Strings" << endl;
cout << "Padro: " << myName << endl;
cout << setw(35) << right << "Com setw(35) e \"right\": " << myName << endl;
cout.width(20);
cout << "Com width(20): " << myName << endl;
cout << endl;
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Exerccios
1. 1. Quero colocar num documento, uma lista das combinaes possveis entre a,b,c e d. com a respectiva ordenao e
quantidade;
2. 2. . Quero que seja a pessoa a escolher o nome do ficheiro (arquivo) e escrever tambm a localizao;
3. 3. . Quero que seja depois tansformado num sistema modular;
4. 4. . Encontrar uma maneira para contar o n de espaos em branco, o n de caracteres "." que quisermos de um dado
documento.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int blank_count = 0;
Entrada e sada de dados 2
79
int char_count = 0;
int sentence_count = 0;
char ch;
ifstream object("jo.txt");
if (! object)
{
cout << "Erro abrindo arquivo." << endl;
return -1;
}
while (object.get(ch))
{
switch (ch)
{
case ' ':
blank_count++;
break;
case '\n':
case '\t':
break;
case '.':
sentence_count++;
break;
default:
char_count++;
break;
}
}
cout << "Existem " << blank_count << " espaos em branco;" << endl;
cout << "Existem " << char_count << " caracteres;" << endl;
cout << "Existem " << sentence_count << " sentenas." << endl;
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Manipulando strings
80
Manipulando strings
"Char strings" e Strings
Os caracteres so entendidos como sendo nmeros que geralmente tm oito bits, esses nmeros so traduzidos na
tabela ASCII de 128 caracteres, como existem inmeras regies no mundo com caractersticas lingusticas prprias,
a tabela ASCII estendida por um bloco de caracteres acima dos 128 mais baixos que varia de acordo com as
necessidades de cada lngua. A parte superior da tabela ASCII conhecida como parte estendida e referenciada por
pginas de cdigos para cada propsito lingustico, isso quer dizer que podemos ter os mesmos nmeros significando
caracteres diferentes para cada regio do mundo.
No estilo da linguagem C quando queremos representar um conjunto de caracteres colocamos todos eles em uma
matriz sequenciada na memria:
Endereo relativo 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A
Dado U m a f r a s e .
Por exemplo, para declarar um espao na memria que contenha 20 caracteres fazemos:
char dados[20];
Este o estilo de strings usado pela linguagem C pura. Para manipular este tipo de string preciso ter certo cuidado,
pois a matriz sempre tem um tamanho definido e caso faamos um acesso a um endereo fora da matriz invadiremos
outras reas de memria que no temos como definir o que so, e portanto poderemos fazer o programa parar de
funcionar, em muitos sistemas pode tambm haver danos aos outros programas e at mesmo ao prprio sistema
operacional, porm em sistemas operacionais mais sofisticados como o GNU/Linux, que possuem gerenciamento de
memria com proteo de memria, apenas o programa que causou a falha ir parar de funcionar.
Para manipular este tipo de string a biblioteca padro da linguagem C dispe de diversas funes, para mais detalhes
consulte o livro Programar em C.
No estilo C++, como era de se esperar, as strings so objetos, eles podem ser criados facilmente atravs da biblioteca
padro referenciada pelo arquivo de cabealho <string>. As strings so objetos com recursos que permitem
manipular os seus caracteres com as funcionalidades das funes da linguagem C e mais algumas caractersticas
prprias possibilitadas pela orientao a objetos.
// listandoCodigoASCII.cpp
#include<iostream>
using std::cout;
using std::cin;
using std::endl;
#include<string>
using std::string;
using std::getline;
int main(){
string anyWord;
Manipulando strings
81
cout << "Digite uma palavra: ";
getline(cin, anyWord);
for ( int i = 0; i < anyWord.length(); i++)
cout << anyWord[i] << " - " << (int)anyWord[i] << endl;
cout << endl;
return 0;
} //end main
Funes de caracteres teis.
As seguintes funes esto no cabealho da biblioteca <cctype>
toupper() (to+upper) retorna a maiscula de uma letra. uma funo de um argumento o caractere. no caso do
argumento no ser uma letra, a funo retorna o mesmo caractere que argumento.
tolower() (to+lower) o mesmo comportamento que toupper(), porm com o resultado em minscula.
#include <iostream>
#include <cctype>
using namespace std;
int main(void)
{
char ch;
do {
cout << "Pressionar S ou s para sair, \nqualquer outra tecla para continuar: ";
cin.get(ch);
ch = toupper(ch);
if (ch != '\n')
cin.ignore();
if (ch != 'S')
cout << "Deseja continuar?\n";
else
cout << "Saindo...";
} while (ch != 'S');
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Funes que verificam o caractere. Estas funes recebem apenas um argumento, o caractere e retornam um valor
booleano.
Manipulando strings
82
Funo Descrio
isalpha Retorna verdadeiro se o argumento uma letra do alfabeto; falso em caso contrrio.
isalnum Retorna verdadeiro se o argumento uma letra do alfabeto ou um dgito; falso em caso contrrio.
isdigit Retorna verdadeiro se o argumento um dgito; falso em caso contrrio.
islower Retorna verdadeiro se o argumento uma letra minscula, falso em caso contrrio.
isprint Retorna verdadeiro se o argumento um caractere imprimvel (inclundo espaos); falso em caso contrrio.
ispunct Retorna verdadeiro se o argumento um sinal de pontuao (caracteres imprimveis que no sejam letras, dgitos ou espao); falso em
caso contrrio.
isupper Retorna verdadeiro se o argumento uma letra maiscula; falso em caso contrrio.
isspace Retorna verdadeiro se o argumento um espao, tabulao ou nova linha; falso em caso contrrio.
Strings em C++
As cadeias de caracteres da linguagem C podem formatar um novo tipo de dados, porm criar tipos de dados mais
sofisticados no possvel nesta linguagem, as strings em C++ so objetos da classe string, o que isso traz de novo
para o tratamento de textos em programas? A primeira coisa a notar quando criamos strings em C++ a maneira de
cri-las, a classe disponibiliza uma srie de construtores:
1 string ( );
2 string ( const string& st );
3 string ( const string& st, size_t position, size_t n = npositions );
4 string ( const char * ps, size_t n );
5 string ( const char * ps );
6 string ( size_t n, char ch );
Isto torna possvel, basicamente, criar string de seis maneiras diferentes:
1. 1. Podemos definir um objeto string vazio, para futuramente usarmos de acordo com a necessidade;
2. 2. Podemos criar um objeto string com uma cpia de outro;
3. 3. Podemos criar um objeto string com uma cpia de uma poro de outra string;
4. 4. Podemos criar um objeto string com uma cpia de uma parte de uma "char string";
5. 5. Podemos criar um objeto string com uma cpia de uma "char string";
6. 6. Podemos criar um objeto string preenchida com uma quantidade definida de um determinado caractere;
Quando manipulamos strings, podemos faz-lo com operadores, como por exemplo "+", "+=", "<<", etc... Isto torna
o cdigo um pouco mais intuitivo, vejamos os operadores:
1 operator=
2 operator[]
3 operator+=
4 operator+
5 operator<<
6 operator>>
Que representam as operaes:
1. 1. Atribuir o valor de uma string para outra;
2. 2. Acessar caracteres individualmente;
3. 3. Adicionar uma string no final de outra;
4. 4. Concatenar strings;
Manipulando strings
83
5. 5. Enviar uma string a um output stream;
6. 6. Receber uma string do input stream.
Apenas com estas poucas informaes j possvel operar strings com bastante flexibilidade e de uma maneira
muito intuitiva, vejamos alguns exemplos:
string a = "Alice e Beto gostam de ",
b("chocolate."),
c = string("doce de leite."),
d = "pipoca.",
e(c);
cout << a + b << endl;
cout << a + c << endl;
cout << a + d << endl;
cout << a + e << endl;
Estas operaes resultam em:
Alice e Beto gostam de chocolate.
Alice e Beto gostam de doce de leite.
Alice e Beto gostam de pipoca.
Alice e Beto gostam de doce de leite.
Exemplos de como manipular strings em C++
erase A funo membro erase elimina parte de uma string. Os parmetros passados para a funo so a posio
inicial e o nmero de caracteres a ser excludo. Veja um exemplo de uso abaixo:
#include<iostream>
using std::cout;
using std::endl;
using std::cin;
#include<string>
using std::string;
using std::getline;
int main(){
string myText;
cout << "Digite um texto qualquer" << endl;
getline( cin, myText );
myText.erase(7, 3);
cout << myText << endl;
return 0;
}
Manipulando strings
84
Comparando formas de operar strings em C e C++
Em C, temos diversas funes que so usadas para manipular strings, para mais detalhes veja o livro Programar em
C, aqui faremos uma comparao dos modos de operar strings em C e C++, algumas particularidades da linguagem
C++ permitem uma operao mais intuitiva das strings e algumas novas formas de trat-las. Vejamos como
manipular estes dados to comuns em qualquer programa.
Funes uteis para o uso de strings
strlen() (str=string + len=length)- aceita um argumento que pode ser um array (uma cadeia) de caracteres, um
ponteiro (que aponta para um array de caracteres) ou uma string literal. retorna um nmero inteiro que representa o
nmero de caracteres, no incluindo o caractere "null":
int len;
len = strlen("Jeff") // a extenso 4
char* stinkydog = "Dante";
len = strlen(stinkydog); // a extenso 5
char name[80] = "Devvie";
len = strlen(name); // a extenso 6
No c++ temos duas funes similares na classe string que so o lenght() e size(). Estas funes no tem argumentos
pois reportam as informaes sobre o objeto a quem pertencem, ambas retornam um inteiro que representa o
tamanho das strings:
string s = "Jeff Kent";
cout << s.length(); // mostra: 9
cout << s.size(); // tambm mostra: 9
Copiando strings
Se tentssemos copiar strings desta maneira
char* target = "Jeff Kent";
char src[80] = "Micaela";
target = src;
O que acontecia que era a cpia do endereo de src para o ponteiro e no os caracteres que esto dentro da matriz.
No entanto existe a funo strcpy (estilo C) ela aceita dois argumentos,
O primeiro para onde vai ser copiada e passado o ponteiro desse array (no pode ser uma string literal).
O segundo a frase a ser copiada e pode ser um array, um ponteiro ou um string literal
char* target = "Jeff Kent";
char src[80] = "Micaela";
strcpy(target, src);
Note que esta operao muito arriscada visto que, quando criamos target, a quantidade de caracteres que foi
reservada para a string era de 9 caracteres mais o caractere nulo no final, se fizermos uma cpia de uma string com
mais de 9 caracteres para este endereo, representado por target, ele fatalmente causar uma violao de endereo.
Porm em C++ podemos atribuir o valor de uma varivel para outra da classe string da forma:
string target = "Jeff Kent";
string src = "Micaela";
target = src;
Manipulando strings
85
Agora, reflitamos no que significa estas operaes: Em primeiro lugar "string" no um tipo primitivo de dado,
uma classe, portanto um tipo de dado mais "inteligente", uma das caractersticas dos objetos string que eles so
redimensionveis, ou seja, quando atribumos a uma string um dado maior que seu espao interno de armazenamento
ela aumenta o seu espao interno para comportar o novo dado. Outra caracterstica que a operao "=" para a string
uma operao de atribuio de contedo, de forma que a string copia a outra quando usamos este operador e no
apenas o ponteiro que referncia o endereo da string.
Unir strings
strcat() (string+concatenate) une duas frases. Recebe 2 argumentos, a frase primria o ponteiro para esse
array.
char target[80] = "Jeff";
char* source= " Kent";
strcat(target, source);
cout << target; // Mostra "Jeff Kent"
Deve-se observar que strcat , potencialmente, uma das rotinas mais perigosas do C, por um motivo bem simples: a
string de destino deve ser pre-dimensionada, e deve ter espao suficiente para receber a string de origem. Um
pequeno programa como:
char target[13] = "Regras do C!";
char* source = " Mas pode dar resultados imprevisiveis";
strcat(target, source);
Escrever bytes em regies da memria que no foram previamente alocadas para a string. Em c++, este problema
resolvido pelo uso de objetos string.
Ao estilo de c++ podemos fazer.
string target = "Regras do C++!\n";
string source = " Geralmente no do resultados imprevisiveis.\n";
target += source;
cout << target; // Mostra: Regras do C++!
// Geralmente no do resultados
imprevisiveis.
Isto porque a classe string prev o uso do operador "+=" de concatenao e nele est embutido um cdigo de
verificao de espao e realocao do mesmo para string, caso seja necessrio.
comparar frases
se fizessemos
char str1[80] = "Devvie Kent";
char str2[80] = "Devvie Kent";
if (str1 == str2)
cout << "The two C-strings are equal";
else
cout << "The two C-strings are not equal";
o que acontecia que estariamos a comparar os endereos e no os valores
temos a funo strcmp (string+compare) (tem 2 arguentos. retornar 0 se forem iguais)
Manipulando strings
86
char str1[80] = "Devvie Kent";
char str2[80] = "Devvie Kent";
if (!strcmp(str1, str2))
cout << "The two C-strings are equal";
else
cout << "The two C-strings are not equal";
esta comparao pode ser resultar em negativo e positivo e isso tem a ver com o jogo de caracteres na tabela ascII.
aqui vai um resumo
Resultados de comparaes entre strings
Primeira
string (str1)
Segunda
string (str2)
strcmp(str1,
str2)
Razo
Jeff jeff negativo j tem valor ASCII maior que J
aZZZ Zaaa positivo a tem valor ASCII maior que Z
chess check positivo Os primeiros trs caracteres so os mesmos, mas a quarta letra da primeira string-C, s, tem
maior valor ASCII que a quarta letra da segunda string-C, c.
Jeff Jeffrey negativo Os quatro primeiros caracteres so os mesmos, mas o quinto caractere da segunda string-C, r,
tem valor ASCII maior que o caractere nulo na quinta posio da primeira string-C.
Em C++ podemos comparar duas strings atravs da funo membro da classe string: compare(), existem os seguintes
formatos (assinaturas) para a funo:
1 int compare ( const string& str2 ) const;
2 int compare ( const char* szc ) const;
3 int compare ( size_t pos1, size_t n1, const string& str2 ) const;
4 int compare ( size_t pos1, size_t n1, const char* szc) const;
5 int compare ( size_t pos1, size_t n1, const string& str2, size_t
pos2, size_t n2 ) const;
6 int compare ( size_t pos1, size_t n1, const char* szc, size_t n2)
const;
A funo permite os seguintes modos de operao, respectivamente:
1. 1. Comparar uma "string" de entrada (str2) com o contedo do objeto a qual ela pertence;
2. 2. Comparar uma "C-string" apontada por um ponteiro com o contedo do objeto a qual ela pertence;
3. 3. Comparar uma seo comeando em (pos1) do objeto, a qual contm (n1) caracteres, com a "string" de entrada
(str2);
4. 4. Comparar uma "C-string" apontada por um ponteiro (szc), com uma seo comeando em (pos1), a qual contm
(n1) caracteres do contedo do objeto a qual ela pertence;
5. 5. Comparar uma seo do objeto, iniciada em (pos1) com (n1) caracteres, com uma seo de (str2), iniciada em
(pos2) com (n2) caracteres;
6. 6. Comparar uma "C-string" apontada por um ponteiro (szc) de extenso (n2), com uma seo comeando em
(pos1), a qual contm (n1) caracteres do contedo do objeto a qual ela pertence.
O resultado similar ao da funo strcmp() em "C", retornando uma referncia de valor de acordo com o cdigo
ASCII.
Se estiver comparando duas strings uma outra opo, ainda mais natural, utilizar os operadores de comparao < e
==.
Manipulando strings
87
using namespace std;
string str1 = "check";
string str2 = "chess";
if (str1 == str2)
cout << "As palavras so iguais." << endl;
else if (str1 < str2)
cout << "A palavra " << str1 << " vem antes de " << str2 << endl;
else
cout << "A palavra " << str1 << " vem depois de " << str2 << endl;
Convertendo C-string e nmero
No ficheiro (arquivo) cabealho da biblioteca cstdlib (c+std+lib) temos vrias funes de converso de nmeros em
tipo numrico.
atoi (acrnimo para "ASCII to integer") recebe um argumento c-string) e retorna o inteiro que a c-string
representa. No verifica se o argumento pode ser convertido:
int num = atoi("7654");
Programa exemplo:
#include <iostream>
#include <cstdlib> // necessrio para atoi
#include <cstring>
using namespace std;
int main(void)
{
char input[80];
int num;
cout << "Enter an integer: ";
cin >> input;
for (int x = 0; x < strlen(input); x++)
{
if (x == 0)
{
if (!isdigit(input[x]) && input[x] != '-')
return 1;
}
else
{
if (!isdigit(input[x]))
return 2;
}
}
num = atoi(input);
cout << num;
Manipulando strings
88
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Neste exemplo temos a vantagem de o usurio inserir um dgito para o array de caracteres em vez de um inteiro, para
evitar um "run-time error" ou "garbage data" que aconteceria se a entrada fosse no numrica. Depois o array
verificado para ver se representa um nmero. Se o numero for negativo tem o caractere "".
Em C++ usamos objetos da classe stringstream (biblioteca sstream.h) para armazenar temporariamente os caracteres,
depois usamos o operador ">>" para converter os caracteres em nmero, bastando para isto criar a varivel no
formato que desejamos receber o nmero. Mais uma vez temos o uso do poliformismo para resoluo de um
problema comum de programao, a operao do ">>" diferente para cada tipo de dado, selecionada
automaticamente pelo compilador de acordo com o tipo de dado da varivel destino.
string name = "123";
stringstream sst;
int i;
sst << name << endl;
sst >> i;
Os passos acima armazenam o valor 123 na varivel "i", todo processo de converso feito pelo operador ">>".
Classes
Esta pgina precisa ser reciclada (discuta).
Ao melhor-la, voc estar ajudando o Wikilivros.
Classes
Existem duas categorias de tipos de dados usuais em C++, so classificados como tipos bsicos e tipos definidos
pelo programador.
Assim como na linguagem C, podemos definir dados compostos por associaes dos tipos bsicos, estes tipos so
chamados de estruturas (structs). C++ traz uma nova representao de dados, muito semelhante na forma s
estruturas, porm diferentes na forma conceitual: a palavra chave class, que usada para criar uma classe de objetos
mais rica que as structs. Ao declararmos um identificador, tal qual fazemos ao declarar uma varivel e no lugar do
tipo especifiquemos uma classe criaremos um objeto.
Antes de prosseguirmos, vejamos um pouco sobre o conceito por trs do uso de objetos. Um objeto entendido
como uma entidade de dados dentro da memria que, basicamente, deve ser responsvel por seu contedo, ou seja,
um objeto deve ser capaz de gerenciar seu contedo autonomamente, ou prover meios de outras entidades de cdigo
faz-lo de forma segura.
Classes
89
Origem (atributos)
Observemos, por exemplo, o cdigo abaixo:
struct MyData
{ int n;
char data[10];
float nReal;
};
Esta declarao, bem conhecida de quem j est familiarizado com a linguagem C, cria um tipo de dado composto
heterogneo, que neste exemplo chamamos de MyData, o que acontece aqui que os dados esto agrupados dentro
desta estrutura, isto promove a possibilidade de manipul-los em conjunto. Um dos problemas com esta estrutura a
presena de uma matriz de caracteres chamada "data", observe que a mesma tem um tamanho definido de 10
caracteres, imagine que em algum momento da execuo do programa tentamos colocar um caractere na posio 11,
ou qualquer posio fora da matriz, neste caso estamos colocando o referido dado em endereos invlidos para a
operao que pretendemos realizar, ou seja, no h controle nenhum que assegure que o cdigo no far um acesso
fora da rea que pertena a matriz. Um acesso de memria a qualquer elemento da matriz acima da posio 9, far
com que invadamos dados na rea onde a varivel nReal est definida.
Funes membro (Mtodos)
Agora suponha que tenhamos como definir um modo para entrar e outro para ler dados da matriz:
struct MyData
{ int n;
char data[10];
float nReal;
bool write_data(int pos, char c)
{ if (pos >= 0 && pos < 10)
{ data[pos]=c;
return true;
}
return false;
}
char read_data(int pos)
{ if (pos >= 0 && pos < 10)
{ return data[pos];
}
return '\0';
}
};
Agora temos assegurados mtodos de incluso e acesso a dados da matriz de caracteres, porm ainda existe um
pequeno problema: Quem quiser o antigo mtodo de acesso direto conseguir facilmente, pois os elementos da
estrutura esto acessveis publicamente por padro.
Classes
90
Conceituao
O problema da visibilidade pblica dos dados em uma estrutura pode ser resolvido com um dos conceitos de objetos,
o encapsulamento. Encapsular os dados, significa reservar o acesso a funes que estejam dentro de um grupo
restrito, especializado para tais operaes de manipulao destes dados. Uma das vantagens deste procedimento
que o cdigo adquire um formato mais organizado, onde os processos tornam-se claramente distintos, caso tenhamos
que analisar o cdigo, cada procedimento estar restrito a partes definidas para cada operao.
Declarando classes
As estruturas so bem parecidas com as classes, com uma pequena diferena, peguemos o caso da passagem de
estruturas como argumentos de funes:
#include <iostream>
#include <string>
using namespace std;
class Person
{
string name;
int height;
};
void setValues(Person&);
void getValues(const Person&);
int main ()
{
Person p1;
setValues(p1);
cout << "Informando dados sobre a pessoa:\n";
cout << "================================\n";
getValues(p1);
return 0;
}
void setValues(Person& pers)
{
cout << "Informe o nome da pessoa: ";
getline(cin, pers.name);
cout << "Informe a altura em milmetros: ";
cin >> pers.height;
cin.ignore();
}
void getValues(const Person& pers)
{
cout << "Nome da pessoa: " << pers.name << endl;
Classes
91
cout << "A altura da pessoa em milmetros : " << pers.height << endl;
}
Mudamos o identificador de struct para class
Mas se tentarmos compilar o programa isto vai causar erros de compilao, porque agora temos variveis membro
que so privadas por padro, estas no so vistas por funes fora da classe.
Dentro de uma classe podemos definir diversos modos de visibilidade de variveis e funes.
As modalidades podem ser:
private (s podem ser acessados por membros da mesma classe)
public (pode ser acessadas fora do objeto, onde este estiver definido)
protected (deixemos esta para quando falarmos em classes derivadas, pois depende deste conceito).
Ora, como as funes getValues e setValues no so membros da classe Person, tal como o construtor Person, no
conseguem acessar as variveis "name" e "height".
Visualizamos melhor em forma de tabela:
Class Person private
string name
Int height
p1
A soluo criar funes publicas, para ler de e escrever para as variveis privadas:
#include <iostream>
#include <string>

using namespace std;
class Person
{
private:
string name;
int height;
public:
string getName() const;
void setName(string);
int getHeight() const;
void setHeight(int);
};
string Person::getName() const
{ return name; }
void Person::setName(string s)
{
if (s.length() == 0)
name = "No name assigned";
Classes
92
else
name = s;
}
int Person::getHeight() const
{ return height; }
void Person::setHeight(int h)
{
if (h < 0)
height = 0;
else
height = h;
}
void setValues(Person&);
void getValues(const Person&);
int main ()
{
Person p1;
setValues(p1);
cout << "Outputting person data\n";
cout << "======================\n";
getValues(p1);
return 0;
}
void setValues(Person& pers)
{
string str;
int h;
cout << "Enter person's name: ";
getline(cin,str);
pers.setName(str);
cout << "Enter height in milimeters: ";
cin >> h;
cin.ignore();
pers.setHeight(h);
}
void getValues(const Person& pers)
{
cout << "Person's name: " << pers.getName() << endl;
cout << "Person's height in milimeters is: " << pers.getHeight() << endl;
}
Classes
93
Mas perguntam: Por que que nos demos ao trabalho de recorrer a membros privados em vez de fazer todos
pblicos? Quando tnhamos uma estrutura no lugar de uma classe, no havia nada que impedisse a colocao de
valores invlidos, por isso poderamos ter valores vazios para a string e valores negativos para a varivel "height".
Agora que "Person" uma classe, as funes membro podem realizar a validao dos dados antes da atribuio de
valores nas variveis. Poderamos fazer com que a funo setName verificasse se a entrada na string seria vazia e
caso fosse, colocaria um valor padro como: sem nome. similarmente poderamos ter "setHeight" para verificar se
seriam colocados valores de entrada negativos e caso fossem, colocaria zero, ou no tomaria nenhuma ao.
Todas estas caractersticas demonstram o conceito de encapsulamento. A sua finalidade de tornar o cdigo mais
modularizado, restringindo o escopo de anlise a partes bem delimitadas dos programas. Devido a este conceito
podemos contar com cdigos mais fceis de analisar e fazer manuteno.
Instanciando objetos
Instanciao de objetos o processo de criar a estrutura lgica dos mesmos na memria. Isto ocorre quando
declaramos os objetos, pois neste momento todo o processo de construo dos mesmos efetivado. Assim, toda vez
que declaramos um objeto estamos instanciando-o, ou seja, estamos criando uma instncia da classe.
Podemos declarar os objetos logo aps definir a classe conforme podemos ver no 1 caso logo abaixo. Neste caso
teremos a varivel rect criada como um objeto conforme estabelecido pelo modelo definido pela palavra chave class.
Este tipo de declarao mais usual para objetos criados globalmente, pois a incluso desta declarao no cabealho
pode fazer com que vrios objetos sejam criados com o mesmo nome quando o cabealho invocado de vrios
arquivos. Portanto, mais prudente usar esta opo quando a declarao est no arquivo fonte e no no cabealho.
1 caso:
class CRectangle
{
int x, y;
public:
void set_values (int,int);
int area (void);
} rect;
No 2 caso, apresentado logo abaixo, podemos declarar objetos apenas quando precisarmos. Esta opo de declarar o
objeto depois a mais usada, pois na maioria das vezes temos o modelo dos objetos, a classe, declarada em um
arquivo de cabealho enquanto que os objetos sero criados no resto do cdigo fonte. Desta forma mais usual criar
as classes em cabealhos e depois declarar os objetos na parte do programa que for mais conveniente.
2 caso:
class CRectangle
{
int x, y;
public:
void set_values (int,int);
int area (void);
};
int main()
{
CRectangle rect;
Classes
94
}
Em ambos os casos temos
CRectangle Private public
int x
int y
void set_values (int,int);
int area (void);
rect
Podemos, ento, entender os objetos como blocos de dados que tm propriedades (variveis) e que podem fazer algo
(mtodos). Ento, criamos todas as funcionalidades que precisamos que a classe fornea aos programas, fazendo os
testes necessrios para assegurar sua consistncia e estabilidade. Sempre que precisemos utilizar os objetos s temos
que instanci-los (declar-los), e no precisamos nos preocupar como eles funcionam internamente, uma vez que os
desenhamos adequadamente.
Para entendermos melhor este conceito podemos fazer uma analogia. Consideremos um objeto resistncia: sabemos
que temos de us-lo e que ela deve ter certas caractersticas, ento teremos o seu valor em Ohms, sua potncia
mxima, tolerncia, entre outras, e teremos uma funo que nos dar a corrente que passa por ela quando lhe
aplicamos uma tenso eltrica. No precisamos saber de que que ela feita, ou como estas caractersticas internas a
faz funcionar, basta-nos receber os resultados.
Vejamos o exemplo:
Agora vamos mostrar que podemos ter funes membro apenas como prottipos e defini-las fora da classe. Para isso
usamos o operador de definio de escopo :: que permite definir o local do cdigo onde um identificador existe, no
formato: ESCOPO::funo ou ESCOPO::dado. De maneira geral, quando declaramos identificadores dentro da
classe podemos defini-los no escopo global referenciando estes pelo operador de escopo.
// classes example
#include <iostream>

using namespace std;
class CRectangle
{
int x, y;
public:
void set_values (int,int);
int area () {return (x*y);}
};
void CRectangle::set_values (int a, int b)
{
x = a;
y = b;
}
Classes
95
//repare no :: que pemite-nos definir a funo membro da classe
CRectangle fora da classe
int main ()
{
CRectangle rect; //definimos objeto de classe
rect.set_values (3,4); //objeto-membro
cout << "area: " << rect.area();
return 0;
}
// classes example
#include <iostream>

using namespace std;
class CRectangle
{
int x, y;
public:
void set_values (int a,int b)
{
x = a;
y = b;
}
int area () {return (x*y);}
};
int main ()
{
CRectangle rect; //definimos objeto de classe
rect.set_values (3,4); //objeto-membro
cout << "area: " << rect.area();
return 0;
}
area: 12
O exemplo anterior explora a caracterstica de toda figura geomtrica fechada, que possui uma rea interna. Observe
que este modo de definir a classe coloca o clculo da rea dentro da definio da mesma. Este modo faz com que o
cdigo seja apenas um modelo, a funo de clculo da rea no ser criada se no for usada durante o escrita do resto
do programa.
Vejamos outro exemplo:
class Dog
{
public:
void setAge(int age);
Classes
96
int getAge();
void setWeight(int weight);
int getWeight();
void speak();
private:
int age;
int weight;
};
void Dog::setAge(int age)
{
this->age = age;
}
int Dog::getAge()
{
return age;
}
void Dog::setWeight(int weight)
{
this->weight = weight;
}
int Dog::getWeight()
{
return weight;
}
void Dog::speak()
{
cout << "BARK!!" << endl;
}
Acima podemos ver um modo de declarar as funes apenas como prottipos, que ficam dentro da declarao da
classe. Nesse contexto as funes so definidas fora da classe, usando-se o operador "::" para ligar a funo classe.
Neste caso teremos as funes definidas e construdas no cdigo das mesmas, enquanto que o modelo da classe
poder permanecer em um arquivo cabealho, o que possibilita inclu-lo em qualquer arquivo de cdigos fontes do
programa.
Definio de classes
Usa-se a palavra "class" para criar uma classe, seguindo-se depois o nome que se queira dar-lhe e finalmente a
definio da mesma entre chaves.
A definio contm:
os dados ( propriedades );
os mtodos (as funes membro)
Vamos acompanhar com um exemplo: Vamos fazer o desenho de uma classe chamada Image, que ser usada para
guardar e manipular uma imagem.
Primeiro perguntamos o que necessrio para guardar uma imagem, depois que tipo de manipulaes necessitamos.
A imagem possui 400 pixels de largura e 300 pixels altura. Cada pixel tem as propriedades de cor e imagem. A cor
composta por: vermelho, azul e verde, numa escala de 0 a . Portanto vamos necessitar de membros para guardar
Classes
97
estas informaes
Agora planejemos os mtodos. Vamos, primeiramente, assumir que temos a restrio de <= 400 pixeis, e estes
valores sero feitos pelo construtor na criao do objeto. Ns no precisamos dos mtodos para estipular a altura e
largura, mas vamos precisar para obter e ler os valores. Esta estratgia tambm nos ajudar a manter os valores de
um determinado pixel e a sua localizao.
A primeira verso ento seria:
class Image {
public:
int getWidth();
int getHeight();
void setX(int x);
int getX();
void setY(int y);
int getY();
void setRed(double red);
double getRed();
void setBlue(double blue);
double getBlue();
void setGreen(double green);
double getGreen();
private:
int _width;
int _height;
int _x;
int _y;
double _red[400][400];
double _blue[400][400];
double _green[400][400];
boolean isWithinSize(int s);
double clipIntensity(double brightness);
};
Especificadores de acesso
Temos as palavras reservadas private e public so os chamados especificadores de acesso.
private Especifica uma faixa de variveis ou funes que podem ser acessadas exclusivamente por membros
da classe, de forma que nenhum outro cdigo fora da mesma possa acess-las;
public Especifica uma faixa de variveis ou funes que podem ser acessadas por qualquer cdigo no
programa, sendo que para as funes internas da classe no necessrio especificar o objeto enquanto que para
as outras partes do programa necessrio especificar o objeto a qual estas pertencem.
Esta caracterstica de limitar o acesso e manipulao dos membros de uma classe chama-se Encapsulamento. A boa
prtica no desenho de classes deve sempre forar o encapsulamento. raramente necessrio ou desejvel ter acesso
livre e pblico aos dados internos de uma classe.
O encapsulamento visa, primariamente duas metas:
1. Eliminar a necessidade de conhecimento da estrutura interna por quem deseja us-la. Por exemplo, se os objetos
precisam manter um conjunto de 4 bytes, isto pode ser conseguido usando-se duas variveis short int, uma int,
Classes
98
um vetor com 4 characteres, ou a variao de qualquer um dos anteriores sem sinal, mas estes detalhes no
precisam estar expostos.
2. 2. Se a representao interna dos dados for modificada, desde que os tipos de retorno e de parmetros das funes
pblicas mantenham-se inalteradas, no necessitemos de alterar cdigo que utilizem objetos da classe.
Ou seja, o encapsulamento simplifica a programao escondendo as particulariadades da classe e elimina o
retrabalho do cdigo por alteraes da mesma. Geralmente as funes (mtodos) privadas, so auxiliares a outras
funes da classe.
Se nenhum especificador de acesso for usado, todos os membros e metodos so declarados como privados por
padro.
H dois mtodos para definir as funes membro:
Eles podem ser definidos dentro da classe, o que apropriado para funes pequenas;
E funes grandes podem ser definidas fora da classe.
Neste caso tero de ser identificadas como pertencentes classe e para isso utilizamos o operador de resoluo de
escopo ::.
Construtores
Conceito
Os construtores "constructors" so funes membro (mtodos) especiais de uma classe. Permitem a inicializao das
variveis membro de um objeto. Ou melhor, permitem a construo e a inicializao de objetos das classes. Se no
os declararmos o compilador faz isso por ns. Os construtores tm sempre o mesmo nome que a classe.
Os objetos so construdos atravs destas funes especiais chamadas de construtores. At aqui no os declaramos,
eram criados automaticamente. Estas funes tem certas caractersticas que as fazem distintas das normais, que
permitem que as mesmas construam a estrutura lgica inicial do objeto. Desta forma estas funes so caractersticas
da orientao a objetos e servem para criao dos mesmos.
Construtores no podem ser chamados explicitamente como fazemos no caso de funes membro regulares. Eles so
apenas executados quando um novo objeto da classe criado. Portanto, existe apenas um evento capaz de executar
um construtor, a instanciao do objeto.
As principais caractersticas dos construtores so:
No tm qualquer valor de retorno;
No podem ser executados por chamada explcita no cdigo;
So executados logo depois que os tipos bsicos do objeto foram criados;
Inicializam os dados com os valores que o objeto precisa para comear a funcionar corretamente.
Declarao
Podemos criar construtores facilmente, atravs das caractersticas que os distinguem das funes membro
convencionais. Ou seja, definimos uma funo membro que possua o mesmo nome da classe, no tenha tipo de
retorno e a declaramos como pblica para que possa ser acessada por quem queira instanciar objetos. Vejamos como
definir um construtor:
class Caneta
{ string cor;
int volume;
///////////////
public:
Classes
99
Caneta( string c, int v );
};
Caneta::Caneta( string c, int v )
{ cor = c;
volume = v;
}
Construtores podem iniciar os membros da classe de uma forma simplificada. Este formato usado sempre que o
construtor tem dados bsicos que podem ser iniciados antes do resto da construo da estrutura do objeto. Podemos
iniciar os dados do objeto declarando-o desta forma:
class Caneta
{ string cor;
int volume;
///////////////
public:
Caneta( string c, int v ) : cor(c), volume(v)
{
}
};
Para faz-lo, como vemos no cdigo, basta listar as variveis membro em uma sequncia depois da declarao do
nome do construtor e de um sinal de dois pontos ":". Iniciamos uma lista de membros, com o valor a ser atribudo
entre parnteses depois de cada um, separando-os por vrgulas.
Destrutores
Conceito
Alm do construtor a linguagem C++, assim como outras linguagens orientadas a objeto, possuem outro tipo de
funo especialmente criada e gerenciada pela linguagem, os destrutores. Estas so destinadas a desmontar a
estrutura do objeto quando o mesmo est sendo encerrado. O destrutor ter o mesmo nome da classe, mas precedido
pelo sinal til ~e tambm no retorna valor.
O destrutor tem as seguintes caractersticas:
O destrutor chamado quando o objeto est sendo finalizado;
usado para liberar qualquer memria que tenha sido alocada;
Declarao
Faamos a classe Dog com o construtor e o destrutor.
class Dog
{
public:
Dog(); //Constructor
~Dog(); //Destructor
void setAge(int age);
int getAge();
void setWeight(int weight);
Classes
100
int getWeight();
void speak();
private:
int age;
int weight;
};
Dog::Dog()
{
age = 0;
weight = 0;
cout << "Dog Constructor Called" << endl;
}
Dog::~Dog()
{
cout << "Dog Destructor Called" << endl;
}
Repare que:
O construtor tem o mesmo nome que a classe;
O destrutor tem o mesmo nome que a classe com o prefixo de tilde~;
O construtor foi usado para inicializar as variveis membro, mas noutros exemplos poderia alocar memria, tomar
controle de recursos como dispositivos de sistema e executar inicializaes de cdigo;
O destrutor no exemplo no faz nenhuma ao real, para alm de fazer o eco informando que foi chamado.
"copy constructors"
Um "copy constructor" um construtor especial que toma como argumento a referncia de um objeto da mesma
classe e cria um novo objeto que a copia do objeto em referncia. Por padro, o compilador providencia um "copy
constructor" que faz a cpia membro por membro do objeto original, construindo um objeto idntico. Isto chamado
de "shallow copy" ou "member wise".
Em algumas situaes a cpia de um objeto no satisfatria, para ver isso vamos ver a classe employee, abaixo:
#include <iostream>
#include <string.h>

using namespace std;
class Employee
{
public:
Employee(char *name, int id);
~Employee();
char *getName(){return _name;}
private://Other Accessor methods
int _id;
char *_name;
Classes
101
};
Employee::Employee(char *name, int id)
{
_id = id;
_name = new char[strlen(name) + 1]; //Allocates an character
array object
strcpy(_name, name);
}
Employee::~Employee()
{
delete _name;
}
int main()
{
Employee programmer("John",22);
cout << programmer.getName() << endl;
return 0;
}
A funo strlen retorna o tamanho da string passada pelo constructor. Repare que o nome do employee agora
guardado num carcter array dinmico. o string lenght +1 para permitir o null terminator usado no estilo c.
A funo strcpy automaticamente adiciona o null terminator a string destino.
Note tambm que o destrutor liberta a memoria usada para guardar o employee name, para evitar memory leak.
Agora imagine que o john promovido:
int main()
{
Employee programmer("John",22);
cout << programmer.getName() << endl;
//Lots of code ....
Employee manager(&programmer);
//Creates a new Employee "manager",
//which is an exact copy of the
//Employee "programmer".
return 0;
}
Este programa contm um bug srio e morre com uma exceo quando executado. O problema que o construtor
que est sendo usado para criar um objeto manager" ,mas ele copia o endereo no ponteiro _name em "manager".
Nos temos 2 pointers ambos contendo o mesmo endereo. Imagine que agora um novo empregado contratado.
quando o nome for atualizado, no apenas iremos alterar o nome do empregado mas tambm do gerente. Finalmente,
quando os objetos deixarem de ser usados e o destrutor da classe fizer a liberao de espao na memria tentar
Classes
102
liberar duas vezes para o mesmo endereo, provocando um erro no sistema de alocao dinmica de memria, o que
forar o sistema operacional a eliminar o programa da memria.
Para resolver esse problema podemos definir um construtor de cpia ("copy constructor") na classe, substituindo a
implementao padro do compilador. Este recurso automaticamente identificado e faz com que o compilador no
crie a sua verso do construtor. Assim, definir um construtor de cpia prprio a maneira mais eficiente quando
nossos objetos detm caractersticas que os fazem diferentes do padro.
Para criar o construtor basta defin-lo na classe:
class Employee
{
public:
Employee( const Employee & e);
Employee(char *name, int id);
~Employee();
char *getName(){return _name;}
private://Other Accessor methods
int _id;
char *_name;
};
Employee::Employee( const Employee & e )
{
_id = e._id;
_name = new char[strlen(e._name) + 1]; //Allocates an
character array object
strcpy(_name, e._name);
}
Agora temos um construtor que pode fazer a cpia da forma correta. Neste novo construtor alocamos uma cadeia de
caracteres para copiar o contedo da original no objeto a ser copiado e copiamos o contedo para o novo objeto.
Assim, teremos objetos distintos, cada um com seu prprio contedo.
Encapsulamento
103
Encapsulamento
Conceito
Encapsulamento, em linguagens orientadas a objeto, a capacidade de ocultao de detalhes de implementao por
parte de entidades de manipulao de dados. Esta caracterstica visa prover um meio de manter cada classe
responsvel por operaes a elas atribudas sem interferncias externas. A vantagem dessa caracterstica de manter
os indivduos de cada classe com funes bem delimitadas e criar meios de criar mdulos onde cada classe faa bem
aquilo de que est encarregada, tendo total controle sobre tais operaes.
Atributos de restrio
Classes podem proteger sua estrutura de acessos de outras entidades de dados que no pertencem a seu corpo. Para
isto, em C++ temos atributos de acesso para blocos de dados ou funes membros de classes. Em algumas
linguagens os atributos so definidos para cada membro individualmente.
Os atributos de restrio de acesso em C++ so trs: private, public e protected. Cada atributo oferece um nvel de
ocultao para membros de classes. Eles so usados para assegurar que apenas grupos identificados de cdigo
tenham acesso a partes presselecionadas da classe.
Os nveis de proteo esto ligados ao parentesco do cdigo que pretende acesso com a classe em que os mesmos
esto definidos. Mais especificamente, classes que no so filhas da que pretendem acessar s podero ter acesso a
membros pblicos, classes filhas tero acesso a membros protegidos (protected) ou pblicos (public) e finalmente,
nenhum cdigo que no pertena a prpria classe poder acessar membros privados (private).
Classes derivadas (pequena introduo)
Precisamos dos conceitos bsicos de herana para entender alguns conceitos de encapsulamento. Para no criarmos
dependncias circulares entre os tpicos, ou seja, para no dependermos de conceitos de herana que tambm precisa
de tpicos de encapsulamento, faremos uma pequena introduo dos conceitos de classes derivadas antes de
prosseguirmos com o nosso estudo de encapsulamento.
Uma classe pode ser estendida a partir de outra, ou seja, podemos reaproveitar um cdigo j existente em uma
determinada classe que j temos e criar uma nova classe com tudo que j existia na primeira, mais o que definirmos
para a nova.
Vejamos um exemplo bsico:
class veculo
{
string cor;
string combustivel;
...
...
};
class carro : public veiculo
{
int nrodas;
...
...
int mover( int nkilometros );
Encapsulamento
104
};
A segunda classe declarada possui a extenso ": public veiculo" a mais, esta parte refere-se a uma declarao de
parentesco. De fato, ao declarar a classe desta forma estamos informando ao compilador que a classe veiculo me
da classe carro. Semanticamente, isto significa que a classe carro possui toda a estrutura da classe veiculo alm de
seus prprios membros.
Definindo acessos
Considerando o exemplo anterior, podemos observar que os atributos "cor", "combustivel", "nrodas" poderiam ser
alterados em qualquer ponto do programa se tivssemos usado a palavra struct, porm usando a palavra class algo
de diferente ocorre, pois no podemos ter acesso a estes atributos, a menos que estejamos acessando-os atravs de
funes definidas dentro das classes.
Em classes, o atributo private definido por padro, ou seja, os membros que no tenham definidos os seus
atributos de acesso explicitamente, sero definidos como privados. Este comportamento revela a necessidade de
resguardar os membros de uma classe atravs de atributos de restries. Em C++, ao definir membros em uma classe
antes da definio de qualquer atributo de restrio estamos definindo-os como privados (private).
Ainda levando em considerao o exemplo anterior, podemos definir atributos de restries para grupos de membros
e modificar o comportamento padro da classe. Se definirmos public, os dados estaro acessveis a qualquer parte do
programa, o que equivalente a coloca-los em uma estrutura com a palavra struct ao invs de dentro de uma classe.
Se definirmos protected temos uma situao peculiar, apenas funes membro da classe ou de suas "filhas" podero
acessar dados da classe me.
Vejamos o exemplo anterior com algumas alteraes:
class veiculo
{
string cor;
protected:
string combustivel;
...
...
public:
bool altCor( string c )
{ if ( c == "vermelho" )
{ cor = c;
return true;
}
if ( c == "azul" )
{ cor = c;
return true;
}
if ( c == "prata" )
{ cor = c;
return true;
Encapsulamento
105
}
return false;
}
};
class carro : public veiculo
{
int nrodas;
...
...
int mover( int nkilometros );
};
Neste exemplo definimos que o atributo cor no pode ser modificado, a no ser pela funo altCor(), onde
restringimos as cores a um conjunto que desejamos. Observe que ao tentar atribuir qualquer cor diferente de
"vermelho", "azul" e "prata", receberemos um retorno "false". Assim, temos a possibilidade de controlar o
comportamento do objeto criado atravs da restrio imposta.
O atributo "combustvel" ser manipulado livremente pela classe "veculo" e pela classe "carro", visto que o atributo
protected d visibilidade s classes derivadas de "veiculo". O mesmo mecanismo de controle visto no pargrafo
anterior poder ser implementado para acessos fora do escopo das duas classes, ou seja, para funes no escopo
global ou em outras classes.
Escopos globais
At aqui vimos os atributos de restrio sendo usados em classes para encapsular partes internas a elas, porm, existe
outro mecanismo de encapsulamento muito til em C++, os namespaces. Estes "espaos de nomes" so meios de
delimitar reas onde smbolos so usados, o que permite evitar que erros ocorram por coincidncia de nomes.
A sintaxe para criao de um namespace bem simples. Vejamos um exemplo de cdigo, para observarmos os
detalhes:
namespace MeuEspaco
{ void print()
{ cout << "Funo de imprimir no meu espaco" << endl;
}
}
namespace EspacoAlheio
{
void print()
{ cout << "Funo de imprimir no Espaco alheio" << endl;
}
}
Herana
106
Herana
Conceito
Herana um dos pontos chave de programao orientada a objetos (POO). Ela fornece meios de promover a
extensibilidade do cdigo, a reutilizao e uma maior coerncia lgica no modelo de implementao. Estas
caractersticas nos possibilitam diversas vantagens, principalmente quando o mantemos bibliotecas para uso futuro
de determinados recursos que usamos com muita frequncia.
Uma classe de objetos "veiculo", por exemplo, contm todas as caractersticas inerentes aos veculos, como:
combustvel, autonomia, velocidade mxima, etc. Agora podemos dizer que "carro" uma classe que tm as
caractersticas bsicas da classe "veculo" mais as suas caractersticas particulares. Analisando esse fato, podemos
concluir que poderamos apenas definir em "carro" suas caractersticas e usar "veculo" de alguma forma que
pudssemos lidar com as caractersticas bsicas. Este meio chama-se herana.
Agora podemos definir outros tipos de veculos como: moto, caminho, trator, helicptero, etc, sem ter que
reescrever a parte que est na classe "veculo". Para isso define-se a classe "veculo" com suas caractersticas e
depois cria-se classes especficas para cada veculo em particular, declarando-se o parentesco neste instante.
Outro exemplo: Imagine que j exista uma classe que defina o comportamento de um dado objeto da vida real, por
exemplo, animal. Uma vez que eu sei que o leo um animal, o que se deve fazer aproveitar a classe animal e fazer
com que a classe leo derive (herde) da classe animal as caractersticas e comportamentos que a mesma deve
apresentar, que so prprios dos indivduos classificados como animais.
Ou seja, herana acontece quando duas classes so prximas, tm caractersticas mtuas mas no so iguais e existe
uma especificao de uma delas. Portanto, em vez de escrever todo o cdigo novamente possvel poupar algum
tempo e dizer que uma classe herda da outra e depois basta escrever o cdigo para a especificao dos pontos
necessrios da classe derivada (classe que herdou).
Sintaxe
Para declarar uma classe derivada de outra j existente, procedemos de forma a declarar o parentesco e o grau de
visibilidade (acesso) que a classe derivada ter dos membros de sua classe base. Para isso seguimos o seguinte
cdigo sinttico:
class classe_derivada : [<acesso>] classe_base {
//corpo da classe derivada
}
Repare que temos o operador ":" ( dois pontos ) como elo entre as duas classes. Este operador promove o
"parentesco" entre as duas classes quando usado na declarao de uma classe derivada.
O termo [<acesso>] opcional, mas se estiver presente deve ser public, private ou protected. Ele define o grau de
visibilidade dos membros da classe base quando a classe derivada precisar acess-los.
Exemplo de implementao:
// Demonstra herana.
#include <iostream>
using namespace std;
class veiculo_rodoviario // Define uma classe base veculos.
{
int rodas;
int passageiros;
Herana
107
public:
void set_rodas(int num) { rodas = num; }
int get_rodas() { return rodas; }
void set_pass(int num) { passageiros = num; }
int get_pass() { return passageiros; }
};
class caminhao : public veiculo_rodoviario // Define um caminhao.
{
int carga;
public:
void set_carga(int size) { carga = size; }
int get_carga() { return carga; }
void mostrar();
};
enum tipo {car, van, vagao};
class automovel : public veiculo_rodoviario // Define um automovel.
{
enum tipo car_tipo;
public:
void set_tipo(tipo t) { car_tipo = t; }
enum tipo get_tipo() { return car_tipo; }
void mostrar();
};
void caminhao::mostrar()
{
cout << "rodas: " << get_rodas() << "\n";
cout << "passageiros: " << get_pass() << "\n";
cout << "carga (capacidade em litros): " << carga << "\n";
}
void automovel::mostrar()
{
cout << "rodas: " << get_rodas() << "\n";
cout << "passageiros: " << get_pass() << "\n";
cout << "tipo: ";
switch(get_tipo())
{
case van: cout << "van\n";
break;
case car: cout << "carro\n";
break;
case vagao: cout << "vagao\n";
}
}
int main()
{
caminhao t1, t2;
automovel c;
Herana
108
t1.set_rodas(18);
t1.set_pass(2);
t1.set_carga(3200);
t2.set_rodas(6);
t2.set_pass(3);
t2.set_carga(1200);
t1.mostrar();
cout << "\n";
t2.mostrar();
cout << "\n";
c.set_rodas(4);
c.set_pass(6);
c.set_tipo(van);
c.mostrar();
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Na implementao acima temos a classe base veiculo_rodoviario e duas classes derivadas :caminhao e automovel.
Podemos notar que as caractersticas comuns a todos os tipos de veculos, rodas e passageiros, esto na classe base,
enquanto as caractersticas exclusivas de cada tipo de veculo esto nas classes derivadas. Desta forma podemos
definir procedimentos especializados para cada classe, fazendo com que todas as eventuais modificaes feitas ao
longo da implementao na classe base sejam estendidas a todos os objetos criados a partir das classes derivadas no
programa.
Repare ainda um pormenor: tanto a classe "caminhao" quanto a automovel tm como funo membro o mtodo
mostrar(), mas uma no interfere com a outra. Isto ilustra um outro aspecto da orientao a objeto, o polimorfismo.
Este ser exposto em mais detalhe nos captulos subsequentes.
Controle de acesso classe base
Quando uma classe herda outra, os membros da classe base so incorporados como membros da classe derivada.
Devido separao das classes e do controle de acesso s variveis em cada classe, devemos pensar como as
restries de acesso so gerenciadas em classes diferentes, principalmente o acesso a membros da classe base a partir
das classes derivadas.
O acesso dos membros da classe base classe derivada determinado pelo especificador de acesso: public, private
e protected. Por "defaut" (padro) temos o private, ou seja, como temos a opo de no explicitar o especificador de
acesso, se este no estiver presente o compilador usar "private" durante a interpretao do cdigo.
Assim ficamos com as possveis combinaes
Herana
109
Classe base herdada como public:
Membros pblicos (public) da classe base:
como se copissemos os membros da classe base e os colocssemos como "public" na classe derivada. No
final, eles permanecem como pblicos.
Membros privados (private) da classe base:
Os membros esto presentes na classe, porm ocultos como privados. Desta forma as informaes esto
presentes, mas s podem ser acessadas atravs de funes publicas ou protegidas da classe base.
Membros protegidos (protected) da classe base:
Se tivermos membros protegidos (protected) na classe derivada, eles se comportam como se tivessem sido
copiados para a classe derivada como protegidos (protected).
Classe base herdada como private:
Membros pblicos (public) da classe base:
Os membros se comportam como se tivessem sido copiados como privados (private) na classe derivada.
Membros privados (private) da classe base:
Os membros esto presentes na classe, porm ocultos como privados. Desta forma as informaes esto
presentes, mas no podero ser acessadas, a no ser por funes da classe base que se utilizem delas.
Membros protegidos (protected) da classe base:
Os membros se comportam como se tivessem sido copiados como privados (private) na classe derivada.
Classe base herdada como Protected:
Membros pblicos (public) da clase base:
Se comportam como se tivssemos copiado-os como protegidos (protected) na classe derivada
Membros privados (private) da classe base:
Os membros esto presentes na classe, porm ocultos como privados. Desta forma as informaes esto
presentes, mas no podero ser acessadas, a no ser por funes da classe base que se utilizem delas.
Membros protegidos (protected) da classe base:
Se comportam como se estivssemos copiado-os como protegidos (protected) na classe derivada.
Em suma, estas regras podem ser sintetizadas em uma regra muito simples: Prevalece o atributo mais restritivo. Para
isto basta-nos listar os atributos por ordem de restries decrescente:
1. 1. private
2. 2. protected
3. 3. public
Assim, temos todas as combinaes definidas quando colocamos um atributo combinado com o outro, bastando para
isto escolher sempre o mais restritivo na combinao. Por exemplo: Quando temos uma varivel pblica na base e a
herana privada, a combinao resulta em uma varivel privada na classe derivada.
Aqui est um exemplo muito simples:
Herana
110
#include <iostream>
using namespace std;
class base
{
int i, j;
public:
void set(int a, int b) { i = a; j = b; }
void show() { cout << i << " " << j << "\n"; }
};
class derived : public base
{
int k;
public:
derived(int x) { k = x; }
void showk() { cout << k << "\n"; }
};
int main()
{
derived ob(3);
ob.set(1, 2); // acesso a membro da base
ob.show(); // acesso a membro da base
ob.showk(); // uso de membro da classe derivada
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Conseguimos acessar as funes set() e show() porque so heradadas como publicas.
Agora modifiquemos o atributo de acesso na declarao da herana da classe base:
#include <iostream>
using namespace std;
class base
{
int i, j;
public:
void set(int a, int b) { i = a; j = b; }
void show() { cout << i << " " << j << "\n"; }
};
class derived : private base
Herana
111
{
int k;
public:
derived(int x) { k = x; }
void showk() { cout << k << "\n"; }
};
int main()
{
derived ob(3);
ob.set(1, 2); // Erro, no possvel acessar set()
ob.show(); // Erro, no possvel acessar show()
ob.showk(); // uso de membro da classe derivada
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Agora j no podemos acessar as funes porque esto privadas.
Heranas mltiplas
Podemos ter a situao em que uma classe derivada possa herdar membros de vrias classes base. Esta caracterstica
uma distino entre C++ e outras linguagens orientadas a objeto. Este recurso d mais poder de modelagem ao
programador, mas vale a pena lembrar que mais poder exige mais cautela no uso.
// Um exemplo de mltiplas classes base.
#include <iostream>
using namespace std;
class base1
{
protected:
int x;
public:
void showx() { cout << x << "\n"; }
};
class base2
{
protected:
int y;
public:
void showy() { cout << y << "\n"; }
};
class derived: public base1, public base2 // Inherit multiple base
Herana
112
classes.
{
public:
void set(int i, int j) { x = i; y = j; }
};
int main()
{
derived ob;
ob.set(10, 20); // Disponvel pela classe "derived"
ob.showx(); // Pela classe base1
ob.showy(); // Pela classe base2
#ifndef WIN32
system ("pause");
#endif
return 0;
}
Repare que utilizamos o operador vrgula para dizer ao compilador que a classe derivada herda mais de uma classe.
Com efeito, temos uma lista de classes separadas por vrgulas depois do operador ":" (dois pontos).
Quando queremos que a classe derivada herde uma classe como pblica e outra como privada ou protegida basta
preceder a classe com o seu especificador de acesso. Da mesma forma, a omisso do especificador leva o compilador
a usar o padro que privado (private).
Construtores e destrutores
Temos uma srie de classes que mantm relaes de parentesco conforme mostramos nas sees anteriores. Em
termos genricos, classes que herdam caractersticas de uma base precisam de regras claras quando forem criadas e
destrudas. Precisamos definir a sequncia em que os construtores e destrutores sero chamados, uma vez que cada
classe tem pelo menos um construtor e um destrutor.
Agora temos a questo: Quando que os construtores so chamados quando eles so herdados?
Quando um objeto da classe derivada instanciado, o construtor da classe base chamado primeiro seguido do
construtor das classes derivadas, em sequncia da base at a ltima classe derivada.
Quando o objeto da classe derivada destrudo, o seu destrutor chamado primeiro seguido dos destrutores das
outras classes derivadas logo abaixo, em sequncia at a base.
Vamos testar e ver como isto funciona.
No caso em que termos herana sequencial A-B-C, teremos:
#include <iostream>
using namespace std;
class base
{
public:
base() { cout << "Construindo base" << endl; }
~base() { cout << "Destruindo base" << endl; }
};
Herana
113
class derivada1 : public base
{
public:
derivada1() { cout << "Construindo derivada1" << endl; }
~derivada1() { cout << "Destruindo derivada1" << endl; }
};
class derivada2: public derivada1
{
public:
derivada2() { cout << "Construindo derivada2\n"; }
~derivada2() { cout << "Destruindo derivada2\n"; }
};
int main()
{
derivada2 ob; // constri e destri o objeto ob
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Caso de mltipla herana A - B e C
#include <iostream>
using namespace std;
class base1
{
public:
base1() { cout << "Construindo base1\n"; }
~base1() { cout << "Destruindo base1\n"; }
};
class base2
{
public:
base2() { cout << "Construindo base2\n"; }
~base2() { cout << "Destruindo base2\n"; }
};
class derivada: public base2,public base1
{
public:
derivada() { cout << "Construindo derivada\n"; }
Herana
114
~derivada() { cout << "Destruindo derivada\n"; }
};
int main()
{
derivada ob;// construindo e destruindo o objeto.
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Neste caso a sequncia de inicializao segue ordem estabelecida na lista de herana. Mais explicitamente, temos a
construo das bases: "base2" e "base1", nesta ordem respectivamente e depois a derivada. O que, automaticamente,
nos revela a sequncia de destruio na ordem inversa, ou seja: destroi-se a "derivada", depois "base1" e, finalmente,
a estrutura da "base2".
Passando parmetros para construtores da classe base
Agora imaginemos que temos um conjunto de bases para uma classe que queiramos derivar, ento podemos ter um
construtor em cada base que precise de parmetros para que possa ser invocado pela nossa classe. Como poderemos
passar os parmetros, uma vez que os mesmos s podem ser passados durante a inicializao da classe?
Para que possamos passar os parmetros para as classes bases durante a inicializao do objeto da classe derivada
temos o recurso de passagem de parmetros pelo construtor. Basicamente, ele funciona como se passssemos valores
para variveis membro. Chamamos cada construtor na lista de passagem de valores, a sintax para declarar o corpo do
construtor a seguinte:
class Classe_derivada : public Base1, public Base2, ..., public BaseN
{ // Membros...
public:
Classe_derivada(lista_de_argumentos);
// Outras funes...
};
Classe_derivada::Classe_derivada(lista_de_argumentos) :
Base1(lista_de_argumentos), Base2(lista_de_argumentos),
...BaseN(lista_de_argumentos);
{
//Corpo do construtor da classe derivada
}
Este exemplo um pouco mais complexo, ateno!
#include <iostream>
using namespace std;
class base
{
Herana
115
protected:
int i;
public:
base(int x) { i = x; cout << "Construindo base\n"; }
~base() { cout << "Destruindo base\n"; }
};
class derivada: public base
{
int j;
public:
derivada(int x, int y): base(y) { j = x; cout << "Construindo derivada\n"; }// derivada usa x; y passada em lista para a base.
~derivada() { cout << "Destruindo derivada\n"; }
void mostrar() { cout << i << " " << j << "\n"; }
};
int main()
{
derivada ob(3, 4);
ob.mostrar(); // mostra 4 3
#ifdef WIN32
system ("pause");
#endif
return 0;
}
No exemplo, a o construtor da classe derivada declarado com 2 argumentos (x e y). no entanto a funo derivada()
usa apenas um para inicializar a varivel interna da classe, o segundo argumento usado para passar o valor de
inicializao para a classe base.
Vejamos mais um exemplo:
#include <iostream>
using namespace std;
class base1
{
protected:
int i;
public:
base1(int x) { i = x; cout << "Construindo base1\n"; }
~base1() { cout << "Destruindo base1\n"; }
};
class base2
{
protected:
int k;
Herana
116
public:
base2(int x) { k = x; cout << "Construindo base2\n"; }
~base2() { cout << "Destruindo base2\n"; }
};
class derivada: public base1, public base2
{
int j;
public:
derivada(int x, int y, int z): base1(y), base2(z)
{ j = x; cout << "Construindo derivada\n"; }
~derivada() { cout << "Destruindo derivada\n"; }
void mostrar() { cout << i << " " << j << " " << k << "\n"; }
};
int main()
{
derivada ob(3, 4, 5);
ob.mostrar(); // mostra 4 3 5
#ifdef WIN32
system ("pause");
#endif
return 0;
}
Superposio de funes
Muitas vezes temos classes derivadas que executam uma determinada ao de forma distinta da mesma ao definida
na classe base. Por exemplo, se temos uma classe "animal" e declaramos uma funo chamada "mover" e depois
declaramos duas derivadas: "ave" e "peixe" com a mesma funo "mover" teremos uma incoerncia devido ao fato
de que peixes se movem de forma totalmente diferente de aves. Uma vez que peixes devem "nadar" e "aves" podem
"voar" ou "andar" nosso modelo de objetos est incorreto.
Por questes de coerncia semntica, porm, precisamos manter o mesmo nome para as funes das classes base e
derivada em algumas construes. Isto essencial devido a necessidade de criarmos objetos generalistas, por
exemplo se tivermos classes "ave" e "peixe" abstradas em uma base "animal", como vimos acima. Havendo estas
condies, como poderemos criar comportamentos diferentes usando o mesmo nome para as funes?
A resposta est em uma das caractersticas que ser muito til quando quisermos usar de polimorfismo, que iremos
abordar em captulo especfico mais adiante: a ocultao e superposio de funes da classe base a partir de uma
classe derivada (conhecida como "overriding" em manuais de compiladores). Com este recurso podemos declarar em
uma classe derivada uma funo com nome e parmetros idnticos a uma existente em uma classe base, porm com
contedo diferente.
Vejamos o exemplo de cdigo e teremos uma noo mais concreta do que foi explanado:
#include <iostream>
using namespace std;
class animal
Herana
117
{
public:
void comer();
void mover();
void dormir() { cout << "Dormindo..." << endl; }
};
...
...
class ave : public animal
{
public:
void comer(){ cout << "Bicando..." << endl; }
void mover(){ cout << "Voando..." << endl; }
};
...
...
class peixe : public animal
{
public:
void comer(){ cout << "Mordendo..." << endl; }
void mover(){ cout << "Nadando..." << endl; }
};
int main()
{
ave passarinho;
peixe sardinha;
passarinho.mover();
sardinha.mover();
#ifdef WIN32
system("pause");
#endif
return 0;
}
Ao executar o programa gerado por este cdigo percebemos que a mesma funo: mover(), ter comportamento
diferente quando invocada por objetos de classes diferentes. O programa mostrar a mensagem "Nadando..." para a
funo invocada pelo objeto sardinha e "Voando..." para a invocada pelo objeto passarinho. Aqui, o mecanismo
bem simples de se entender, quando cada objeto tem uma verso diferente para a mesma funo fcil para o
compilador relacionar o objeto classe que ele pertence e invocar a funo apropriada.
Herana
118
Acessando funes superpostas da classe base
O mecanismo para obter acesso s classes base a partir da classe derivada intuitivo. Para isto usamos o operador de
resoluo de escopo, composto por um par de dois pontos "::", usando a seguinte sintaxe:
<CLASSE>::<FUNO>(lista_de_parmetros);
Ou seja, basta invocar a funo informando qual a verso especfica que se deseja utilizar. Se tivermos uma classe
"A" e outra "B" com uma funo "Print()", por exemplo, e quisermos usar a funo "Print()" da classe "B" fazemos:
B::Print();
Talvez seja melhor visualizar um exemplo no cdigo mais completo:
class B
{
public:
void Print()
{
cout << "Chamando Print() da classe B." << endl;
}
};
class A : public B
{
public:
void Print()
{
cout << "Chamando Print() da classe A." << endl;
B::Print();
}
};
int main()
{ A ca;
ca.Print();
return 0;
}
Polimorfismo
119
Polimorfismo
Esta pgina precisa ser reciclada (discuta).
Ao melhor-la, voc estar ajudando o Wikilivros.
Conceito
Polimorfismo em linguagens orientadas a objeto, a capacidade de objetos se comportarem de forma diferenciada
em face de suas caractersticas ou do ambiente ao qual estejam submetidos, mesmo quando executando ao que
detenha, semanticamente, a mesma designao.
O polimorfismo em C++ se apresenta sob diversas formas diferentes, desde as mais simples, como funes com
mesmo nome e lista de parmetros diferentes, at as mais complexas como funes virtuais, cujas formas de
execuo so dependentes da classe a qual o objeto pertence e so identificadas em tempo de execuo.
Funes virtuais
#include <iostream>
using std::cout;
using std::endl;
class Base {
public:
// declarao da funo virtual
virtual void Quem_VIRTUAL()
{
cout << "Base\n";
}
// funo comum
void Quem_NAO_VIRTUAL()
{
cout << "Base\n";
}
};
class Derivada : public Base {
public:
// funo virtual sobrescrita
virtual void Quem_VIRTUAL()
{
cout << "Derivada\n";
}
// funo comum sobrescrita
void Quem_NAO_VIRTUAL()
{
cout << "Derivada\n";
Polimorfismo
120
}
};
int main ()
{
Base *ptr_base;
Derivada derivada;
ptr_base = &derivada; // converso implcita permissvel
ptr_base->Quem_VIRTUAL(); // chamada polimrfica (mostra:
"Derivada")
ptr_base->Quem_NAO_VIRTUAL(); // chamada comum, no-polimrfica
(mostra: "Base")
cout << endl;
return 0;
}
Classe base virtual
Consideremos o seguinte programa:
// Este programa contm um erro e no ser compilado.
#include <iostream>
using namespace std;
class base
{
public:
int i;
};
class derived1 : public base // derived1 inherits base.
{
public:
int j;
};
class derived2 : public base // derived2 inherits base.
{
public:
int k;
};
class derived3 : public derived1, public derived2 /* "derived3" herda
caractersticas de "derived1" e "derived2". Isto significa que h duas
cpias da base em "derived3"! */
{
Polimorfismo
121
public:
int sum;
};
int main()
{
derived3 ob;
ob.i = 10; // Isto se torna ambguo; A qual "i" estamos nos
referindo???
ob.j = 20;
ob.k = 30;
ob.sum = ob.i + ob.j + ob.k;// "i" ambguo aqui, tambm
cout << ob.i << " ";// tambm ambguo, Qual "i"?
cout << ob.j << " " << ob.k << " ";
cout << ob.sum;
#ifdef WIN32
system ("pause");
#endif
return 0;
}
As classes derived1 e derived2 so herdadas como classes base. A classe derived3 herda tanto de derived1 quanto de
derived2. Como resultado temos 2 cpias da classe base presentes no objeto da derived3, por exemplo presente na
linha ob.i=10; isto resulta numa ambiguidade e o programa no vai compilar.
H duas maneiras para remediar a situao:
1. Aplicar o operador de resoluo de escopo manualmente:
//Este programa usa resoluo de escopo explicita para selecionar "i".
#include <iostream>
using namespace std;
class base
{
public:
int i;
};
class derived1 : public base // derived1 inherits base.
{
public:
int j;
};
class derived2 : public base // derived2 inherits base.
{
public:
int k;
};
Polimorfismo
122
class derived3 : public derived1, public derived2 /* "derived3" herda
as bases "derived1" e "derived2". Isto significa que h duas cpias de
bases em "derived3"! */
{
public:
int sum;
};
int main()
{
derived3 ob;
ob.derived1::i = 10; // escopo resolvido, usa o "i" em
"derived1".
ob.j = 20;
ob.k = 30;
ob.sum = ob.derived1::i + ob.j + ob.k; // escopo
resolvido.
cout << ob.derived1::i << " "; // tambm resolvido aqui.
cout << ob.j << " " << ob.k << " ";
cout << ob.sum;
#ifdef WIN32
system ("pause");
#endif
return 0;
}
2. A segunda maneira atravs de classes bases virtuais:
Quando temos 2 ou mais objetos que so derivados da mesma base class, podemos prevenir mltiplas cpias da base
class declarando a base class como virtual quando ela herdada. Exemplificando:
// Este program usa classes bases virtuais.
#include <iostream>
using namespace std;
class base
{
public:
int i;
};
class derived1 : virtual public base // derived1 inherits base as
virtual.
{
public:
int j;
};
class derived2 : virtual public base // derived2 inherits base as
virtual.
{
public:
Polimorfismo
123
int k;
};
class derived3 : public derived1, public derived2 /* derived3 inherits
both derived1 and derived2. This time, there is only one copy of base
class. */
{
public:
int sum;
};
int main()
{
derived3 ob;
ob.i = 10; // now unambiguous
ob.j = 20;
ob.k = 30;
ob.sum = ob.i + ob.j + ob.k;// unambiguous
cout << ob.i << " ";// unambiguous
cout << ob.j << " " << ob.k << " ";
cout << ob.sum;
system ("pause");
return 0;
}
Repare que agora temos a palavra virtual antes da classe.
Friend
124
Friend
Esta pgina precisa ser reciclada (discuta).
Ao melhor-la, voc estar ajudando o Wikilivros.
O que
Friend um atributo especial de acesso a classes. Com ele declaramos que uma funo fora de uma classe amiga da
mesma.
Declarando que uma funo (externa classe) "friend" dentro de uma classe, permite que a funo (a amiga) possa
ler e manipular membros (variveis e funes membro) "private" - privados e "protected" - protegidos (e claro
"public" - publicas, mas isso j era permitido antes de serem "friends").
Considerando que o acesso a membros pode ser restrito para determinadas partes do cdigo, podemos adotar uma
postura mais flexvel para funes que conhecemos como confiveis e evitar os inconvenientes da restrio a
membros por cdigos que no provoquem problemas maiores a nossa estrutura da aplicao.
Declarar funes "friend"
O processo para fazer com que funes fora do escopo da classe tenham acesso a membros sem nenhuma restrio
muito simples. Para isto apenas temos de colocar o prottipo da funo externa dentro da classe precedido da palavra
"friend". Desta forma o compilador passa a ignorar os atributos de restrio de acesso da classe quando a funo
acessa membros da mesma.
Vamos ao exemplo:
// friend functions
#include <iostream>
using namespace std;
class CRectangle
{
int width, height;
public:
void set_values (int, int);
int area () {return (width * height);}
friend CRectangle duplicate (CRectangle);
};
void CRectangle::set_values (int a, int b)
{
width = a;
height = b;
}
CRectangle duplicate (CRectangle rectparam)
{
CRectangle rectres;
rectres.width = rectparam.width*2;
rectres.height = rectparam.height*2;
return (rectres);
}
Friend
125
int main ()
{
CRectangle rect, rectb;
rect.set_values (2,3);
rectb = duplicate (rect);
cout << rectb.area();
system (pause);
return 0;
}
O uso de funes amigas deve ser evitado sempre que possvel, pois diminui a identidade da orientao a objetos.
Isto ocorre porque o uso desse mecanismo representa uma quebra no encapsulamento. Quando passamos a permitir
que funes tenham acesso a membros restritos dos objetos fazemos com que agentes externos interfiram na
autonomia dos mesmos. Isto pode dificultar a anlise de programas muito extensos.
No caso da criao de procedimentos que tem a finalidade de modificar o contedo do objeto explicitamente, como
nos casos de operadores e modificadores de comportamento, podemos usar as funes amigas "friends" para esta
finalidade tomando os devidos cuidados para torn-las muito bem restritas as funes que devem executar. muito
importante observar se estas funes alteram dados dentro dos objetos que no podem ser modificados. Se as devidas
precaues forem tomadas no haver problemas no uso de funes "friend".
Friend classes
Da mesma forma que podemos declarar funes como amigas de uma determinada classe, podemos declarar outra
classe como sua amiga. Este artifcio faz com que os membros da classe onde foi feita a declarao sejam acessveis
declarada. Assim, a segunda classe passa a ter possibilidade de manipulao livre dos membros da outra.
Apesar da funcionalidade ser um pouco semelhante que temos no uso das funes, quando declaramos uma classe
como "friend" dentro de outra, teremos todas as funes da primeira com poderes de acesso aos membros da
segunda. Esta caracterstica requer cuidado redobrado quando operaes da classe "friend" interferem no contedo
da outra.
// friend class
#include <iostream>
using namespace std;
class CSquare;
class CRectangle
{
int width, height;
public:
int area ()
{return (width * height);}
void convert (CSquare a); //consigo acessar porque friend
};
class CSquare
{
private:
int side;
public:
void set_side (int a) {side=a;}
Friend
126
friend class CRectangle; //declaro friend class
};
void CRectangle::convert (CSquare a)
{
width = a.side;
height = a.side;
}
int main ()
{
CSquare sqr;
CRectangle rect;
sqr.set_side(4);
rect.convert(sqr);
cout << rect.area();
system (pause);
return 0;
}
Nota:
No h a propriedade de reciprocidade (ou reverso). O facto de uma funo ou classe ser friend de uma
classe no implica o contrrio, ou seja, A ter B como friend no implica que B a tenha em mesma conta.
Outra propriedade que no h transitividade. Se numa class A for declarado que a class B friend. E depois
que na classe B estiver declarado que a classe C friend de B,Isto no implica que A seja friend de C.
Classes internas
Conceituao
As classes podem ser construdas uma dentro da outra para uma melhor organizao do cdigo. Esta possibilidade
nos leva a implicaes a serem consideradas durante a fase de implementao do cdigo. Devemos verificar as
particularidades de acesso a dados, o que nos leva a diversas particularidades devido ao escopo das mesmas.
No exemplo a seguir, temos a implementao bsica de uma classe interna a outra:
class data
{
int n;
char str[256];
public:
class idata
{ int x;
int y;
int z;
};
int getn();
char *getstr();
void setstr( const char *instr);
Classes internas
127
void setn(int inn);
};
Uma vez que criamos o prottipo de objeto dentro de outra classe podemos us-lo atravs do operador de resoluo
de escopo. Deveremos nos referir ao operador para acessar o corpo da primeira classe e depois o invocamos
novamente para alcanar a outra. Desta forma, poderamos us-la como exemplificado abaixo:
data::idata ni;
importante notar que objetos diferentes tero dados diferentes na regio da classe interna, isso impede que usemos
dados da classe mais externa dentro das classes internas. Devido a esta caracterstica as funes dentro da classe
interna no podem acessar dados da classe mais externa, a menos que sejam estticos, o que no exige definio do
objeto a qual eles pertencem. Portanto, o uso de classes internas permite um isolamento de parte dos dados e prover
um tratamento diferenciado para os mesmos.
Sobrecarga de operadores
Modificando operadores
A linguagem C++ possui os mesmos operadores presentes na linguagem C. Estes tm funes padronizadas e
comportamentos semelhantes a seus parentes diretos em C. Esta caracterstica a traz compatibilidade que um
requisito fundamental e adiciona uma nova funcionalidade chamada sobrecarga de operadores.
Quando operamos tipos nativos da linguagem, fazemos com funes especficas predefinidas e padronizadas. Como
poderemos operar os nossos objetos que definimos com nossas classes? Simples: criamos as funcionalidades e as
atribuimos a operadores j conhecidos, de forma a manter a idia bsica da operao embutida na simbologia.
Ao definir novas funes para os operadores padro, na verdade no substituimos a sua funo, apenas adicionamos
mais uma funo ao mesmo operador. Esta operao chamada de sobrecarga de operador. O nome parece um
pouco fora do comum, mas apenas reflete o comportamento da linguagem quando esta lida com a definio de vrios
tratamentos para o mesmo identificador, que, neste caso, o smbolo do operador. Portanto, sobrecarga de
operador a definio de novas tarefas para o mesmo operador.
Definindo novas operaes
Digamos que temos uma classe chamada ponto, que define dois inteiros para um plano hipoteticamente definido.
Este par de inteiros poder representar uma coordenada neste plano formado por pontos espaados um do outro. Sob
estas condies, cada objeto desta classe ser uma coordenada neste plano:
class ponto
{
int x,y;
public:
ponto(int a, int b)
{
x = a;
y = b;
}
};
Sobrecarga de operadores
128
Se quisermos operar estes objetos no teremos como faz-lo, pois no h meios de operar os objetos do tipo ponto.
Nenhuma operao possivel, pois a linguagem no define como oper-los. Cabe ao programador dizer ao
compilador como ele deve efetuar a operao do novo tipo criado.
ponto p1(1,5), p2(3,4), Soma;
Soma = p1 + p2;
Ao tentar compilar este trecho de cdigo o compilador retornar um erro por no conhecer a maneira de como operar
este tipo de dado. Como criamos o tipo de dado, precisamos definir como fazer a soma do mesmo. Podemos fazer a
seguinte definio:
class ponto
{
int x,y;
public:
ponto(int a, int b)
{
x = a;
y = b;
}
ponto operator+(ponto p);
};
ponto ponto::operator+(ponto p)
{
int a, b;
a = x + p.x;
b = y + p.y;

return ponto(a, b);
}
A sintaxe desta definio, muitas vezes causa confuso, mas poder ser facilmente entendida depois que tenhamos
assimilado as idias bsicas por traz dela. Ela opera, aparentemente, apenas um dado de entrada, porm o operador
deve somar dois. Como isto possvel? Observando mais atentamente o cdigo poderemos entender:
Verificamos que, no cdigo, nos referimos a x e y sem definir a qual objeto pertence. Acontece que a operao est
ocorrendo dentro de um dos objetos, aquele imediatamente antes do operador. Esta a primeira coisa a ter em mente:
O operador "pertence" a um dos objetos que est sendo operado, sendo sempre aquele que o antecede. Com isso, s
precisamos declarar o segundo dado a operar.
Podemos visualizar isto melhor, da seguinte forma:
P3 = P1 + P2;
Que pode ser entendido como a invocao da funo:
P3 = P1.operator+( P2);
Agora podemos entender como acontece a invocao da funo que define o operador. Observe que P1 contm o
operador que recebe P2, fazendo o clculo e devolvendo uma cpia do objeto resultante para P3. A sintaxe esconde o
mecanismo para tornar o cdigo mais simples de ser entendido quando tiver que ser lido.
Alocao dinmica de memria
129
Alocao dinmica de memria
Esta pgina precisa ser reciclada (discuta).
Ao melhor-la, voc estar ajudando o Wikilivros.
Alocao dinmica de memria
O compilador reserva espao na memria para todos os dados declarados explicitamente, mas se usarmos ponteiros
precisamos reservar o espao necessrio e colocar o endereo inicial nos mesmos. Para isto, podemos usar o
endereo de uma varivel definida previamente ou reservar o espao necessrio no momento que precisemos. Este
espao que precisamos reservar em tempo de execuo chamada de memria alocada dinamicamente.
Refere-se possibilidade de termos o nosso programa a correr e o utilizador ter de inserir dados e como tal no
sabemos exatamente a quantidade de dados que o utilizador vai colocar, portanto temos de arranjar uma memria
que nos permita lidar com esta indeterminao quanto quantidade de dados inseridos.
Este o caso em que no sabemos no momento da programao a quantidade de dados que devero ser inseridos
mas o programa j est a correr. tentar responder a perguntas: quantas pessoas existem na tua turma? Quantas
letras vamos escrever, etc. Em vez de estarmos a prever um limite superior para abarcar todas as situaes, temos
esta possibilidade do dinmico. Alm de que colocar no momento da programao cria reserva de memria por isso,
estaramos a reservar memria para um limite que possivelmente no iramos ter necessidade. O exemplo tpico disto
os processadores de texto. em que no sabemos a quantidade de letras que o utilizador vai escrever.
Vamos voltar a uma ponta solta num dos captulos anteriores, onde queramos fazer com que o utilizador dissesse
quantos elementos do array que se deveria utilizar. J dissemos antes que o declarador do n de elementos do array
tem de ser ou uma constante ou um literal, mas no pode ser uma varivel. Isso d erro. Aqui vai o exemplo desse
erro:
#include <iostream>
using namespace std;
int main ()
{
int numTests;
cout << "digite o numero de testes : ";
cin >> numTests;
int testScore[numTests];
return 0;
}
A razo da exigncia de ter uma constante (ou literal) que vamos alocar memria para o array na altura da
compilao, e o compilador necessita de saber exatamente a quantidade de memria que deve reservar porm se a
varivel o size declarator, o compilador no sabe quanta memria deve reservar para alocar a varivel, pois o seu
valor pode mudar.
Alocao dinmica de memria
130
Operador new
Reformulando o exemplo anterior agora com dados dinmicos.
#include <iostream>
using namespace std;
int main ()
{
int numTests;
cout << "Enter the number of test scores:";
cin >> numTests;
int * iPtr = new int[numTests]; //colocamos um ponteiro no
inicio da memria dinmica
for (int i = 0; i < numTests; i++)
{
cout << "Enter test score #" << i + 1 << " : ";
cin >> iPtr[i];
}
for (int i = 0; i < numTests; i++)
cout << "Test score #" << i + 1 << " is "<< iPtr[i] << endl;
delete [] iPtr;
return 0;
}
Ou seja conseguimos criar um array onde o utilizador a definir o tamanho do array e que depois coloca o valor para
cada um dos elementos.
O operador new retorna o endereo onde comea o bloco de memria. e como retorna um endereo vamos coloc-lo
num pointer.
Necessitamos do uso do pointer que dever ser do mesmo tipo que o tipo de varivel que alocado dinamicamente.
int * iPtr = new int[numTests];
Temos termo NEW. Que um operador cuja funo alocar dinamicamente memria
Temos o tipo da varivel alocada dinamicamente
Repare que NO temos o nome do array
Uma vez que o array fica sem nome para nos referirmos a cada elemento do array teremos de usar o pointer.
Podemos inicializar de duas maneiras:
int *IDpt = new int;
*IDpt = 5;
ou
int *IDpt = new int(5); //Allocates an int object and initializes
it to value 5.
char *letter = new char('J');
Alocao dinmica de memria
131
Operador Delete - Memory Leak
O tempo de vida de uma varivel criada dinamicamente o tempo de execuo do programa. Se um ponteiro aponta
para uma varivel dinmica e fica out of scope, j no conseguiremos acessar essa memria criada dinamicamente.
Fica indisponvel. A isso se chama Memory Leak
Explicando: se alocamos memria dinamicamente dentro de uma funo usando um ponteiro local, quando a funo
termina, o ponteiro ser destrudo, mas a memria mantm-se. Assim j no teramos maneira de chamar essa
memria porque ela no tem nome! Apenas tnhamos o endereo que estava no ponteiro.
Portanto, se realmente no necessitamos mais dos dados que esto nessa memria dinmica, em vez de eles estarem
a ocupar espao vamos apag-los! Necessitamos de libertar essa memria atravs do operador delete este operador
entrega ao sistema operacional a memria reservada dinamicamente.
A sintaxe
delete [] iPtr;
Este delete operator no apaga o ponteiro mas sim a memria onde o ponteiro aponta.
dynamic memory allocation funciona porque a memria no reservada no momento da compilao, mas antes na
execuo. Em vez de ser no STACK (compilao) a memria reservada no HEAP (execuo). O heap uma parte
da memria que usada como memria temporria.
Pergunta: onde que fica situado o Heap?
Vamos explicar melhor todo este processo: pois isto tem de entrar na cabea!
void myfunction()
{
int *pt;
int av;
pt = new int(1024);
....
....
//No delete
}
int main()
{
while (some condition exists) // Pseudo-code
{
myfunction();
}
exit 0;
}
quando a funo myfunction chamada a varivel av criada no stack e quando a funo acaba a varivel
retirada do stack. O mesmo acontece com o ponteiro pt, ele uma varivel local. ou seja quando a funo acaba o
ponteiro tambm termina e retirado do stack. Porm o objeto alocado dinamicamente ainda existe.
E agora no conseguimos apagar esse objeto por que ele no tem nome e a nica maneira que tnhamos para saber
onde ele estava era atravs do ponteiro que terminou quando termina a funo pois ele local.
Ento medida que o programa continua a operar mais e mais memria ser perdida do Heap (free store). se o
programa continuar o tempo suficiente, deixaremos de ter memria disponvel e o programa deixar de operar.
Alocao dinmica de memria
132
Retornando um ponteiro para uma varivel local
#include <iostream>
using namespace std;
char * setName();
int main (void)
{
char* str = setName(); //ponteiros para a funo
cout << str; //imprimo o valor do ponteiros?
return 0;
}
char* setName (void)
{
char name[80];
cout << "Enter your name: ";
cin.getline (name, 80);
return name;
}
O que se passou aqui que o ponteiro que sai da funo setName aponta para o array local cuja vida acaba quando a
funo termina de executar. A soluo estender o tempo de vida. Uma soluo era tornar esse array global, mas
existem alternativas melhores.
Retornando um Ponteiro a uma Varivel Local Esttica
Uma dessas alternativas
#include <iostream>
using namespace std;
char * setName();
int main (void)
{
char* str = setName();
cout << str;
return 0;
}
char* setName (void)
{
static char name[80]; //crio como static
cout << "Enter your name: ";
cin.getline (name, 80);
return name;
}
A diferena que usamos a palavra static.
O ponteiro do setName aponta para o array local, e como foi utilizado o static, ele perdura at fim da funo,
terminando apenas quando o programa acaba.
Alocao dinmica de memria
133
Returning a Pointer to a Dynamically Created Variable
Outra alternative, talvez melhor
#include <iostream>
using namespace std;
char * setName();
int main (void)
{
char* str= setName();
cout << str;
delete [] str; //fao o delete para evitar o memory leak
return 0;
}
char* setName (void)
{
char* name = new char[80]; //crio ponteiro chamado de name e dou
o valor do endereo da memoria dinmica
cout << "Enter your name: ";
cin.getline (name, 80);
return name;
}
Isto funciona porque o ponteiro retornado da funo setname aponta para o array cujo tempo de vida persiste. O
address do ponteiro local atribudo no main a outro ponteiro no main str. Depois este ponteiro usado at ao fim
da execuo do programa. Este um exemplo onde diferentes ponteiros apontam para o mesmo endereo.
Mas ter ateno que se fizermos o delete atravs de um ponteiro, ter cuidado com o segundo ponteiro que aponta
para a memoria que acabou de ser deslocada.
Alocar dinamicamente Arrays
Ora o que fizemos antes com variveis, vamos ter de fazer com arrays.
int *pt = new int[1024]; //allocates an array of 1024 ints
double *myBills = new double[10000];
/* This doesn't mean I owe 10000.0, but rather allocates an array of
10000 doubles to hold the amounts of the thousands of bills I receive
monthly. */
Notar a diferena:
int *pt = new int[1024]; //allocates an array of 1024 ints
int *pt = new int(1024); //allocates a single int with value 1024
a melhor maneira para alocar um array dinamicamente usar o loop
int *buff = new int[1024];
for (i = 0; i < 1024; i++)
{
*buff = 52; //Assigns 52 to each element;
buff++;
}
Alocao dinmica de memria
134
ou se quisermos desta maneira
int *buff = new int[1024];
for (i = 0; i < 1024; i++)
{
buff[i] = 52; //Assigns 52 to each element;
}
para utilizar o delete em arrays
delete[] pt;
delete[] myBills;
Dangling Pointers
int *myPointer;
myPointer = new int(10);
cout << "The value of myPointer is " << *myPointer << endl;
delete myPointer;
*myPointer = 5;
cout << "The value of myPointer is " << *myPointer << endl;
neste exemplo libertmos a memria dinmica, mas o ponteiro continua isto um bug tremendo, e muito difcil de
detectar. o programa continua a correr e a seco de memria pode ser usada por outro objeto dinmico. acontece
que essa memoria estar corrompida se continuar a usar o myPointer. a melhor maneira depois do delete fazer
apontar para zero, faz-lo um ponteiro nulo. se tentarem usar o ponteiro iremos ter a run time exception e o bug pode
ser identificado
Assim, corrigindo o cdigo anterior ficaramos com:
int *myPointer;
myPointer = new int(10);
cout << "The value of myPointer is " << *myPointer << endl;
delete myPointer;
myPointer = 0;
*myPointer = 5; //This statement will cause an run-time exception,
now.
cout << "The value of myPointer is " << *myPointer << endl;
Verificar a existncia de memria para dinmica
Na alocao dinmica temos de nos certificar de que a alocao no heap foi feita com sucesso e podemos ver isso de
duas maneiras:
Uma so as excees (este o mtodo defaut)
bobby = new int [5]; // se isso falhar, lanada uma "bad_alloc"
(exception)
vamos ver este caso quase no ultimo capitulo- isto uma captulo avanado
nothrow, aqui no caso de no se conseguir a memria retorna um ponteiro nulo, e o programa continua.
bobby = new (nothrow) int [5];
supostamente este mtodo pode ser tedioso para grandes projetos
Alocao dinmica de memria
135
Vamos ver um exemplo com o caso de nothrow
// rememb-o-matic
#include <iostream>
using namespace std;
int main ()
{
int i,n,* p;
cout << "How many numbers would you like to type? ";
cin >> i;
p= new (nothrow) int[i]; //crimos I variaveis na execuo
if (p == 0)
cout << "Error: memory could not be allocated";
else
{
for (n=0; n<i; n++)
{
cout << "Enter number: ";
cin >> p[n];
}
cout << "You have entered: ";
for (n=0; n<i; n++)
cout << p[n] << ", ";
delete[] p;
}
return 0;
}
Excees
136
Excees
Esta pgina precisa ser reciclada (discuta).
Ao melhor-la, voc estar ajudando o Wikilivros.
Uma exception um erro que ocorre em tempo de execuo. Podemos lidar com estes erros e criar rotinas para
muitos deles, o que nos permite automatizar muitos erros que antes teriam de ser emendados mo.
Standard Exceptions
A biblioteca de C++ contm exceptions j definidas para erros comuns. Elas so divididas em dois setores: Erros
lgicos e Erros de tempo de execuo.
Aqui vemos um exemplo de cdigo usando exceptions de erros lgicos:
#include <iostream>
#include <stdexcept> // std::invalid_argument
#include <bitset>
#include <string>
int main (void)
{
try
{
// O construidor de bitset joga uma invalid_argument se
inicializado com uma
// string contendo caracteres diferentes de 0 e 1
std::bitset<5> mybitset (std::string("01234"));
}
catch ( const std::invalid_argument& ia )
{
std::cerr << "Invalid argument: " << ia.what() << '\n';
}
return 0;
}
Namespace
137
Namespace
Esta pgina precisa ser reciclada (discuta).
Ao melhor-la, voc estar ajudando o Wikilivros.
O propsito dos namespace localizar os identifiers (os nomes) por forma a evitar que haja apenas um, para evitar
colises. Por exemplo eu poderia criar uma funo com um determinado nome e depois vir a saber que esse mesmo
nome existia na biblioteca. E isto pode ocorrer bem freqentemente quando temos vrios programadores
contribuindo para o mesmo projeto e ainda mais quando se recorre a bibliotecas para usar cdigo criado por outros.
O que o namespace permite continuar a termos o mesmo nome mas ir fazer a diferenciao pela deteco do
contexto de aplicao para cada nome.
Templates
Esta pgina precisa ser reciclada (discuta).
Ao melhor-la, voc estar ajudando o Wikilivros.
Os templates permitem a criao de cdigo reusado, usando templates possvel criar funes e classes genricas.
Assim o tipo de dados usados pelas funes so parmetros. Podemos criar um template para soma, e depois
enviamos que tipo de dados queremos somar, podemos at utilizar a sobrecarga de operadores para tal fim.
Funes genricas
template <class Ttype> ret-type func-name(parameter list)
{
// body of function
}
vamos dar o exemplo
// Function template example.
#include <iostream>
using namespace std;
template <class X> void swapargs(X &a, X &b)// This is a function template.
{
X temp;
temp = a;
a = b;
b = temp;
}
int main()
{
int i=10, j=20;
double x=10.1, y=23.3;
char a='x', b='z';
cout << "Original i, j: " << i << ' ' << j << '\n';
cout << "Original x, y: " << x << ' ' << y << '\n';
Templates
138
cout << "Original a, b: " << a << ' ' << b << '\n';
swapargs(i, j); // swap integers
swapargs(x, y); // swap floats
swapargs(a, b); // swap chars
cout << "Swapped i, j: " << i << ' ' << j << '\n';
cout << "Swapped x, y: " << x << ' ' << y << '\n';
cout << "Swapped a, b: " << a << ' ' << b << '\n';
system ("pause");
return 0;
}
Aqui criamos uma template para uma funo que troca os valores, e essa funo pode ser usada quer tendo ints,
doubles ou chars. ns utilizamos o X como data type. neste caso temos swapargs() como uma funo genrica. O
compilador automaticamente cria 3 verses para a funo swapargs(). portanto os templates no so bem funes
que funcionam para as vrios tipos, mas antes os templates permitem poupar escrita ao programador para no ter de
especificar cada tipo.
template function ou generic function ( uma definio de uma funo precedida pela statement template
especializao == quando o compilador cria a verso especifica da funo. tambm chamada de generated
function. o ato de gerar a funo referido como instantiating.
h quem prefira ter a declarao do template da seguinte forma
template <class X>
void swapargs(X &a, X &b)// This is a function template.
{
X temp;
temp = a;
a = b;
b = temp;
}
O que se torna bem parecido com o modelo utilizado anteriormente.
Uma funo com dois tipos genricos:
#include <iostream>
using namespace std;
template <class type1, class type2>
void myfunc(type1 x, type2 y)
{
cout << x << ' ' << y << '\n';
}
int main()
{
myfunc(10, "hi");
myfunc(0.23, 10L);
system ("pause");
return 0;
}
Repare que temos dois tipos de dados diferentes na mesma funo.
Templates
139
Sobrecarregando explicitamente uma funo genrica
apesar de uma funo genrica poder ser overload automaticamente se necessrio, ns podemos explicitar. a isso
chamamos deexplicit specialization
Containers
list
set
unordered_set
map
unordered_map
Compilao
Esta pgina precisa ser reciclada (discuta).
Ao melhor-la, voc estar ajudando o Wikilivros.
Compilao o processo de "traduo" do programa escrito em uma linguagem de programao para um formato no
qual o computador entenda. A compilao gera um ficheiro - arquivo em portugus brasileiro - binrio (executvel) a
partir do cdigo fonte.
A traduo do cdigo para o computador
Em C e C++ so 3 os programas usados para fazer a traduo do cdigo fonte (que so as linhas de cdigo que o
programador escreve) num ficheiro executvel, que o computador pode executar:
1. 1. Preprocessor - pr-processador
2. 2. Compiler - compilador
3. 3. Linker
Pr-processador
Este um programa que busca no cdigo fonte no cdigo que escrevemos por diretivas que foram dirigidas a
ele, ou seja linhas iniciadas com #, assim o pr-processador sabe que aquela instruo dirigida para ele. No
exemplo tnhamos:
#include <iostream>
Ento o pr-processador inclui ficheiros localizados no ficheiro iostream. Ento tnhamos o cdigo fonte que depois
transformado num outro cdigo fonte de acordo com as diretivas pr-processadas.
Essencialmente, o pr-processador um processador de macros para uma linguagem de alto nvel.
[1]
Compilao
140
Compilador
Compilador um programa que pega cdigo fonte preprocessado e o traduz em instrues de linguagem de mquina,
linguagem que o computador entende. Estas so guardadas num arquivo a parte, chamado de "object file" e tem a
extenso .o ou .obj dependendo do compilador. Existem diferentes compiladores para diferentes linguagens de
programao. Essa traduo feita se o cdigo estiver na linguagem que o compilador compilar. Existem regras de
escrita e de gramtica. No caso de existir um erro de sintaxe, ento dar um erro de compilao.
Linker
Apesar do nosso "object file" ter as instrues em linguagem mquina, o computador ainda no poder correr como
um programa. A razo que necessrio outro cdigo da biblioteca, que o cdigo do run-time library, que para
as operaes comuns tipo a traduo o input do teclado ou a capacidade para interagir com hardware externo tipo o
monitor para apresentar uma mensagem. Estas bibliotecas run-time costumam j estar instaladas com o sistema
operacional, caso isso no acontea teremos de fazer o download delas.
Ento o resultado da combinao do "object file" com as partes necessrias da biblioteca run-time fazem finalmente
a criao de um ficheiro executvel com a extenso .exe
Processo de compilao
Em primeiro lugar, vamos escrever um cdigo que est na linguagem C++ e vamos gravar esse cdigo todo num
ficheiro, que uma quantidade de memria no computador. Esse ficheiro fica com a terminao .CPPou .CP ou
C.. Chama-se a este conjunto de linhas que escrevemos de, cdigo fonte ou source code (pode ter a terminao .c,
.cpp, e .cc - estas extenses dependem do compilador que se utiliza). Esse "source code" de alguma forma
crptica e para algum que no saiba de c++ no entanto aquilo que neste momento chamamos de humam readable
form.
Para tornar o nosso source code num programa usamos um compilador que ir produzir um "object file". Este
ficheiro tem normalmente a extenso. OBJ porm ainda no temos um programa executvel. Para isso vamos utilizar
o linker. Uma das vantagens do c++ que usufrui de uma estrutura multi-file. A linguagem permite compilao
separada, onde partes do programa total podem estar numa ou mais source files e estes podem ser compilados
independentemente de cada um. A ideia que o processo de compilao produz files que depois podem ser linked
together usando um editor de link ou loads que o sistema provem.
Os programas feitos em c++ so tipicamente ficheiros .OBJ ligados uns aos outros com uma ou mais libraries. Estas
so uma coleo de linkable files que ns crimos ou que foram fornecidas (vm com o compilador ou compramos).
Depois de se fazer este linking que obtemos o arquivo executvel. No Windows, ele tem terminao .exe. Assim,
o sistema operacional reconhece o programa como independente.
Os compiladores atuais incluem tambm pr-compiladores, (ou pr-processadores) (antes eram software
independente, extra), estes pr-compiladores vo fazer alteraes ao cdigo fonte, que basicamente consistem em
eliminar pedaos de cdigo que escrevemos, e/ou substituir pedaos de cdigo que escrevemos por outro
(copy-paste), enfim, alterar o cdigo fonte por outro cdigo fonte. Depois que se compila.
Compilao
141
Referncias
[1] http:/ / www. dca.fee. unicamp. br/ cursos/ EA876/ apostila/ HTML/ node150. html
O pr-processador C
Lista de Palavras Reservadas do C++
Estas so as palavras reservadas do c++:
alignas (since C++11) alignof (since C++11) and
and_eq asm auto
bitand bitor bool
break case catch
char char16_t (since C++11) char32_t (since C++11)
class compl const
constexpr (since C++11) const_cast continue
decltype (since C++11) default delete
do double dynamic_cast
else enum explicit
export extern false
float for friend
goto if inline
int long mutable
namespace new noexcept (since C++11)
not not_eq nullptr (since C++11)
operator or or_eq
private protected public
register reinterpret_cast return
short signed sizeof
static static_assert (since C++11) static_cast
struct switch template
this thread_local (since C++11) throw
true try typedef
typeid typename union
unsigned using virtual
void volatile wchar_t
while xor xor_eq
Maiores detalhes podem ser encontrados em: http:/ / en. cppreference. com/ w/ cpp/ keyword
Lista de Sequncias de Escape
142
Lista de Sequncias de Escape
Estes so caracteres que so difceis de serem expressos de outra forma em um cdigo fonte. Todos eles so
precedidos de uma barra invertida. A Tabela 1 apresenta a lista de sequncias de escape.
Controle/Caracter Sequncia de escape Valor ASCII
Nulo (null) \0 00
Campainha (bell) \a 07
Retrocesso (backspace) \b 08
Tabulao horizontal \t 09
Nova linha (new line) \n 10
Tabulao vertical \v 11
Alimentao de folha (form feed) \f 12
Retorno de carro (carriage return) \r 13
Aspas (") \" 34
Apstrofo (') \' 39
Interrogao (?) \? 63
Barra invertida (\) \\ 92
Tabela 1 - Lista de Sequncias de Escape em C++
Tabela ASCII
Programa que gera a tabela ASCII do C++ (programa escrito em c++). Nenhum dos 2 programas mostra a tabela
inteira. O programa mostra alguns caracteres que o programa 2 no mostra. De modo geral, faltam alguns caracteres.
Esta pgina um esboo de informtica. Ampliando-a voc ajudar a melhorar o Wikilivros.
Programa 1
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
//CARACTER " " (ENTER) = DECIMAL 10 HEXADECIMAL A;

int s = -127;

cout<<" CARAC DEC HEX\n\n";
for ( char i = -127; i<127; i++ )
Tabela ASCII
143
{
cout<<" "<<i<<" "<<s<<" ";
printf("%X",s);
cout<<"\n";
s++;
}
cout<<"\n CARAC DEC HEX\n\n";
cout<<" \x122 ENTER \x122 10 A\n\n";
system ("PAUSE");
return 0;
}
Programa 2
#include <stdio.h>
#include <iostream>
int main()
{
int x;
printf(" DEC\tHEX\tA DEC\tHEX\t");
printf(" DEC\tHEX\n");
for(x=-173;x<360;x++)
{
printf("%c %3i\t%2X\t",x,x,x);
printf("%c %3i\t%2X\t",x+32,x+32,x+32);
printf("%c %3i\t%2X\t",x+64,x+64,x+64);
printf("%c %3i\t%2X\n",x+96,x+96,x+96);
}
system ("PAUSE");
return 0;
}
C++11
144
C++11
Origem: Wikipdia, a enciclopdia livre.
C++11, anteriormente conhecido por C++0x o novo padro para a linguagem de programao C++. Ele substitui o
antigo padro do C++, o ISO/IEC 14882, que foi publicado em 1998 e atualizado em 2003. Estes predecessores
foram informalmente chamados C++98 e C++03. O novo padro incluir muitas adies ao ncleo da linguagem
(sua implementao principal), e estender a biblioteca padro do C++, incluindo a maior parte da biblioteca do
chamado C++ Technical Report 1 um documento que prope mudanas ao C++ com exceo das funes
matemticas especficas.
Esse nome uma referncia ao ano no qual o padro ser lanado. O comit pretendia introduzir o novo padro em
2009,1 a partir do que o ento chamado "C++0x" passaria a se chamar "C++09", o que significa que o documento
deveria estar pronto para a ratificao dos membros do comit at o final de 2008. Para cumprir o prazo, o comit
decidiu focar seus esforos nas solues introduzidas at 2006 e ignorar novas propostas.2 porm ele ficar pronto
apenas em 2010.
Linguagens de programao como o C++ utilizam um processo evolucionrio para desenvolverem suas definies.
Tal processo inevitavelmente culmina em problemas de compatibilidade com cdigo pr-existente, o que
ocasionalmente aconteceu durante o processo de desenvolvimento do C++. Entretanto, de acordo com o anncio
feito por Bjarne Stroustrup inventor da linguagem C++ e membro do comit o novo padro ser quase
completamente compatvel com o padro atual.3
Novas classes:
std::array
std::tuple
std::foward_list
std::unordered_set
std::unordered_multiset
std::unordered_map
std::unordered_multimap
Regular expressions library: http:/ / en. cppreference. com/ w/ cpp/ regex
Atomic operations library: http:/ / en. cppreference. com/ w/ cpp/ atomic
Thread support library: http:/ / en. cppreference. com/ w/ cpp/ thread
Fontes e Editores da Pgina
145
Fontes e Editores da Pgina
Objetivo Fonte: http://pt.wikibooks.org/w/index.php?oldid=212683 Contribuidores: Contribuidor, He7d3r, Marcos Antnio Nunes de Moura, SallesNeto BR, Wbrito
Por que C++? Fonte: http://pt.wikibooks.org/w/index.php?oldid=244119 Contribuidores: Abacaxi, He7d3r, Jorge Morais, Marcos Antnio Nunes de Moura, SallesNeto BR, Wbrito, 2 edies
annimas
Diferenas entre C e C++ Fonte: http://pt.wikibooks.org/w/index.php?oldid=265805 Contribuidores: Abacaxi, Fabio Basso, He7d3r, Marcos Antnio Nunes de Moura, Master, Torneira, 1
edies annimas
Introduo Fonte: http://pt.wikibooks.org/w/index.php?oldid=267436 Contribuidores: Abacaxi, He7d3r, Mappim, Marcos Antnio Nunes de Moura, Rautopia, 4 edies annimas
Al, Mundo! Fonte: http://pt.wikibooks.org/w/index.php?oldid=267384 Contribuidores: Abacaxi, Albmont, Carlosmacapuna, Daveiro, Edudobay, Focli, He7d3r, Jorge Morais, Marcelo-Silva,
Marcos Antnio Nunes de Moura, Petrusz1, Rautopia, Renatofq, Sygmn, Wbrito, 20 edies annimas
Variveis e constantes Fonte: http://pt.wikibooks.org/w/index.php?oldid=238714 Contribuidores: Jorge Morais, Marcos Antnio Nunes de Moura, Rautopia
Ponteiros Fonte: http://pt.wikibooks.org/w/index.php?oldid=269171 Contribuidores: Abacaxi, Albmont, Jonathan Queiroz, Jorge Morais, Marcos Antnio Nunes de Moura, 5 edies annimas
Vetores Fonte: http://pt.wikibooks.org/w/index.php?oldid=267854 Contribuidores: Abacaxi, Daveiro, Edudobay, Jorge Morais, Marcelo-Silva, Marcos Antnio Nunes de Moura, Master,
Raylton P. Sousa, Wbrito, 6 edies annimas
Estruturas Fonte: http://pt.wikibooks.org/w/index.php?oldid=270790 Contribuidores: Abacaxi, Albmont, Defender, Marcos Antnio Nunes de Moura, 6 edies annimas
Operadores Fonte: http://pt.wikibooks.org/w/index.php?oldid=244121 Contribuidores: Abacaxi, Marcos Antnio Nunes de Moura
Deciso e controle de fluxo Fonte: http://pt.wikibooks.org/w/index.php?oldid=266793 Contribuidores: Abacaxi, Marcos Antnio Nunes de Moura, 11 edies annimas
Estruturas de repetio Fonte: http://pt.wikibooks.org/w/index.php?oldid=266523 Contribuidores: Abacaxi, Diegobza, He7d3r, LlamaAl, Lucas Daltro, Marcos Antnio Nunes de Moura, 1
edies annimas
Funes Fonte: http://pt.wikibooks.org/w/index.php?oldid=249232 Contribuidores: Abacaxi, Jonas AGX, 2 edies annimas
Referncias de dados Fonte: http://pt.wikibooks.org/w/index.php?oldid=239660 Contribuidores: Albmont, Marcos Antnio Nunes de Moura, Reder, 5 edies annimas
Entrada e sada de dados Fonte: http://pt.wikibooks.org/w/index.php?oldid=266602 Contribuidores: Abacaxi, Albmont, Daveiro, Edudobay, Jeferson90, Jonathan Queiroz, Jorge Morais,
Marcelo-Silva, Marcos Antnio Nunes de Moura, Torneira, Wbrito, 16 edies annimas
Entrada e sada de dados 2 Fonte: http://pt.wikibooks.org/w/index.php?oldid=256748 Contribuidores: Abacaxi, Daveiro, Diego.g.a, Edudobay, Jorge Morais, Marcelo-Silva, Marcos Antnio
Nunes de Moura, Raylton P. Sousa, Wbrito, 19 edies annimas
Manipulando strings Fonte: http://pt.wikibooks.org/w/index.php?oldid=264914 Contribuidores: Abacaxi, Albmont, Daveiro, Fabiobasso, Jorge Morais, Marcelo-Silva, Marcos Antnio Nunes
de Moura, Wbrito, 20 edies annimas
Classes Fonte: http://pt.wikibooks.org/w/index.php?oldid=266994 Contribuidores: Abacaxi, Albmont, Daveiro, Hudsonkem, Jeferson90, Jorge Morais, Marcelo-Silva, Marcos Antnio Nunes
de Moura, Wbrito, 18 edies annimas
Encapsulamento Fonte: http://pt.wikibooks.org/w/index.php?oldid=214125 Contribuidores: MGFE Jnior, Marcos Antnio Nunes de Moura, 2 edies annimas
Herana Fonte: http://pt.wikibooks.org/w/index.php?oldid=214299 Contribuidores: Albmont, Daveiro, Jorge Morais, Marcelo-Silva, Marcos Antnio Nunes de Moura, Wbrito, 14 edies
annimas
Polimorfismo Fonte: http://pt.wikibooks.org/w/index.php?oldid=265821 Contribuidores: Abacaxi, Daveiro, Jorge Morais, Marcelo-Silva, Marcos Antnio Nunes de Moura, Torneira, Wbrito, 5
edies annimas
Friend Fonte: http://pt.wikibooks.org/w/index.php?oldid=255619 Contribuidores: Abacaxi, Daveiro, Jorge Morais, Marcelo-Silva, Marcos Antnio Nunes de Moura, Wbrito, 8 edies
annimas
Classes internas Fonte: http://pt.wikibooks.org/w/index.php?oldid=212708 Contribuidores: Marcos Antnio Nunes de Moura
Sobrecarga de operadores Fonte: http://pt.wikibooks.org/w/index.php?oldid=271234 Contribuidores: Marcos Antnio Nunes de Moura, Raylton P. Sousa, 6 edies annimas
Alocao dinmica de memria Fonte: http://pt.wikibooks.org/w/index.php?oldid=271233 Contribuidores: Abacaxi, Daveiro, He7d3r, Jorge Morais, Marcelo-Silva, Marcos Antnio Nunes de
Moura, Petrusz1, Wbrito, 15 edies annimas
Excees Fonte: http://pt.wikibooks.org/w/index.php?oldid=271213 Contribuidores: Daveiro, Jorge Morais, Marcelo-Silva, Marcos Antnio Nunes de Moura, SallesNeto BR, Wbrito, 6 edies
annimas
Namespace Fonte: http://pt.wikibooks.org/w/index.php?oldid=203888 Contribuidores: Daveiro, Jorge Morais, Marcelo-Silva, Marcos Antnio Nunes de Moura, Wbrito, 4 edies annimas
Templates Fonte: http://pt.wikibooks.org/w/index.php?oldid=271965 Contribuidores: Abacaxi, Daveiro, Jorge Morais, Marcelo-Silva, Marcos Antnio Nunes de Moura, Wbrito, 9 edies
annimas
Containers Fonte: http://pt.wikibooks.org/w/index.php?oldid=267423 Contribuidores: Abacaxi, 1 edies annimas
Compilao Fonte: http://pt.wikibooks.org/w/index.php?oldid=266790 Contribuidores: Abacaxi, Daveiro, Edudobay, Jonas AGX, Jorge Morais, Marcelo-Silva, Marcos Antnio Nunes de
Moura, Master, Renatofq, SallesNeto BR, Wbrito, 5 edies annimas
Lista de Palavras Reservadas do C++ Fonte: http://pt.wikibooks.org/w/index.php?oldid=266289 Contribuidores: Abacaxi, Lucas Daltro, 1 edies annimas
Lista de Sequncias de Escape Fonte: http://pt.wikibooks.org/w/index.php?oldid=253634 Contribuidores: Abacaxi, Yoroi
Tabela ASCII Fonte: http://pt.wikibooks.org/w/index.php?oldid=265804 Contribuidores: Abacaxi, He7d3r, Torneira, 2 edies annimas
C++11 Fonte: http://pt.wikibooks.org/w/index.php?oldid=267422 Contribuidores: Abacaxi, 1 edies annimas
Fontes, Licenas e Editores da Imagem
146
Fontes, Licenas e Editores da Imagem
Image:Nuvola apps konsole.png Fonte: http://pt.wikibooks.org/w/index.php?title=Ficheiro:Nuvola_apps_konsole.png Licena: GNU Lesser General Public License Contribuidores: Alno,
Alphax
Image:Recycle001.svg Fonte: http://pt.wikibooks.org/w/index.php?title=Ficheiro:Recycle001.svg Licena: desconhecido Contribuidores: Users Cbuckley, Jpowell on en.wikipedia
Licena
147
Licena
Creative Commons Attribution-Share Alike 3.0
//creativecommons.org/licenses/by-sa/3.0/