Logo Passei Direto
Buscar
Material
páginas com resultados encontrados.
páginas com resultados encontrados.

Prévia do material em texto

PEARSON -Addison 
\\esley www. aw. com / sav itch_l5r 
Página em branco
Walter J. Savitch
Tradução
Claudia Martins
Revisão Técnica
Oswaldo Ortiz Fernandes Jr.
Professor concursado em Teoria da Computação e Compiladores
no Centro Universitário Municipal de SC do Sul
Bacharel e Licenciado em Física pela USP
Pós-graduado em Física pela USP
Mestrando em Engenharia Eletrônica e Computação pelo ITA
ASSOCIAÇÃO BRASILEIRA DE DIREITOS REPROGRÁFICOS
C ++ HBSOLUTO 
PEARSON 
• • • • 
'~d'°.; 
~o.,111z•"° • 
São Paulo 
Brasil Argentina Colômbia Costa Rica Chile Espanha Guatemala México Peru Porto Rico Venezuela 
 2004 by Pearson Education do Brasil
Título original: Absolute C++ — first edition
 2002 by Pearson Education, Inc.
Publicação autorizada a partir da edição original em inglês publicada pela
Pearson Education, Inc., sob o selo Addison Wesley
Todos os direitos reservados. Nenhuma parte desta publicação poderá ser reproduzida ou trans-
mitida de qualquer modo ou por qualquer outro meio, eletrônico ou mecânico, incluindo fotocó-
pia, gravação ou qualquer outro tipo de sistema de armazenamento e transmissão de
informação, sem prévia autorização, por escrito, da Pearson Education do Brasil.
Diretor Editorial: José Martins Braga
Editor: Roger Trimer
Editora de Texto: Adriane Gozzo
Preparação: Sandra Garcia
Revisão: Nilma Guimarães
Designer de Capa: Marcelo Françozo, sobre o projeto original de Leslie Haimes, com foto de Re-
nee Lynn/Stone by Getty Images
Editoração Eletrônica: ERJ Composição Editorial e Artes Gráficas Ltda.
Dados Internacionais de Catalogação na Publicação (CIP)
(Câmara Brasileira do Livro, SP, Brasil)
Savitch, Walter J.
C++ absoluto / Walter Savitch ; tradução Claudia Martins ; 
revisão técnica Oswaldo Ortiz Fernandes Jr. -- São Paulo : 
Addison Wesley, 2004.
ISBN: 85-88639-09-2
1. C++ (Linguagem de programação para computadores)
I. Título.
 03-2860 CDD-005.133
Índices para catálogo sistemático
 1. C++ : Linguagem de programação : Computadores :
 Processamento de dados 005.133
2004
Direitos exclusivos para a língua portuguesa cedidos à
Pearson Education do Brasil,
uma empresa do grupo Pearson Education
Av. Ermano Marchetti, 1435
CEP: 05038-001, Lapa – São Paulo – SP
Tel: (11) 3613-1222 Fax: (11) 3611-0444
e-mail: vendas@pearsoned.com
Prefácio
C++ Absoluto foi projetado como um manual e livro de referência para a programação na linguagem C++. Embora
inclua técnicas de programação, foi organizado mais em função dos recursos da linguagem C++ do que de algum
currículo específico de técnicas de programação. O público que eu tinha em mente ao escrevê-lo era o de estudan-
tes universitários, especialmente de ciências da computação, ainda sem muita experiência em programação com a
linguagem C++. Este livro foi projetado para ser útil a um grande número de usuários. Os capítulos iniciais foram
escritos em um nível acessível a iniciantes, embora os quadros desses capítulos sirvam para apresentar rapidamente
a sintaxe básica do C++ a programadores mais experientes. Os últimos capítulos também são acessíveis, mas foram
escritos em um nível adequado a estudantes que já evoluíram para tópicos mais avançados. 
Este livro também inclui uma introdução aos padrões e à Linguagem Unificada de Modelagem (UML) e um
capítulo inteiro sobre Recursão.
RECURSOS ESPECIAIS
PADRÕES ANSI/ISO C++
Este livro foi escrito de acordo com os novos padrões ANSI/ISO C++.
STANDARD TEMPLATE LIBRARY
A Standard Template Library é uma extensa coleção de bibliotecas de classes de estrutura de dados pré-programa-
das e algoritmos importantes. A STL talvez seja um tópico tão extenso quanto o núcleo da linguagem C++. Este
livro contém uma sólida introdução à STL. Há um capítulo inteiro sobre templates e outro sobre as particularida-
des da STL, além de outros assuntos relacionados com a STL em capítulos diversos.
PROGRAMAÇÃO ORIENTADA A OBJETOS
Este livro trata da estrutura da linguagem C++. Dessa forma, os primeiros capítulos, que abordam aspectos do
C++ comuns a quase todas as linguagens de programação de alto nível, não estão direcionados especificamente à
programação orientada a objetos (OOP). Isso faz sentido em se tratando de um livro de referência e para ensino
de uma segunda linguagem. Entretanto, considero C++ uma linguagem OOP. Se você estiver programando real-
mente em C++ e não em C, precisa tirar proveito dos recursos OOP do C++. Este livro fornece uma extensa
abordagem sobre encapsulamento, herança e polimorfismo como entendidos na linguagem C++. O capítulo final
sobre padrões e UML apresenta outros assuntos relacionados à OOP.
FLEXIBILIDADE NA ORDENAÇÃO DOS TÓPICOS
C++ Absoluto permite aos professores uma grande liberdade de reordenação do material. Isso é importante para
uma obra de referência e combina com a minha filosofia de escrever livros que se adaptem ao estilo do professor
em vez de amarrá-lo à preferência pessoal de ordenamento de tópicos do autor. Tendo isso em mente, a introdu-
ção de cada capítulo explica que material deve ser estudado antes que se execute cada seção do capítulo.
ACESSÍVEL AOS ESTUDANTES
Não é suficiente que um livro apresente os tópicos certos na ordem certa. Nem é suficiente que seja claro e corre-
to quando lido por um professor ou outro especialista. O material precisa ser apresentado em uma forma acessível
a quem ainda não o conhece. Como meus outros manuais, que se revelaram bastante populares entre os estudan-
tes, este livro foi redigido de maneira amigável e acessível.
Quadros
Todos os pontos principais são resumidos em quadros, espalhados ao longo de cada capítulo, que servem como
resumos do conteúdo, como fonte de referência rápida e como forma de aprender rapidamente a sintaxe do C++
para recursos que o leitor já conhece de forma geral, mas para os quais necessita saber os detalhes do emprego da
linguagem C++.
Exercícios de Autoteste
Cada capítulo contém diversos Exercícios de Autoteste em pontos estratégicos. As respostas completas para todos
os exercícios são dadas ao final de cada capítulo.
Outros Recursos
Seções de "armadilhas", de técnicas de programação e exemplos de programas completos com amostras E/S são
dadas ao longo de cada capítulo, que termina com uma seção de resumo e vários projetos de programação ade-
quados para serem atribuídos aos estudantes.
MATERIAL DE APOIO
Este livro foi planejado para uso com o Microsoft Visual C++. No site do livro em www.aw.com/savitch_br você
encontra links para diversos sites relacionados, além dos seguintes recursos:
■ Código-fonte do livro
■ Transparências em PowerPoint
Os seguintes recursos estão disponíveis somente para os professores que adotam o livro. Por favor, entre em
contato com o seu representante de vendas local ou envie um e-mail para universitarios@pearsoned.com para ter
acesso ao:
■ Manual do professor (em inglês)
AGRADECIMENTOS
Diversas pessoas contribuíram de forma inestimável para tornar este livro uma realidade. Frank Ruggirello e minha
editora Susan Hartman, da Addison-Wesley, foram os primeiros a imaginarem esta obra. Susan Hartman, Galia
Shokry, Lisa Kalner e outras pessoas fantásticas da Addison-Wesley foram uma contínua fonte de apoio e encora-
jamento para a revisão técnica, revisão de provas e publicação.
Cindy Kogut fez um incrível trabalho de edição de texto. Sally Boylan e outros da Argosy Publishing fizeram
um ótimo trabalho, efetuado em um curto espaço de tempo, na digitalização das páginas.
David Teague merece um agradecimento especial. Apreciei muito seu trabalho árduo, suas ótimas sugestões e
a pesquisa cuidadosa para este livro.
Agradeço a meu bom amigo Mario Lopez pelas muitas conversas proveitosas que tivemos sobre o C++.
Os seguintes revisores forneceram correções e sugestões que contribuíram imensamente para o produto final.
Agradeço a todos. Em ordem aleatória, eles são: Kenrick Mock, University of Alaska, Anchorage; Richard Al-
bright, University of Delaware; H. E. Dunsmore, Purdue University; Christopher E. Cramer;de Terminal
Lixo para dentro quer dizer lixo para fora.
Ditado do programador
A entrada simples de terminal é feita com os objetos cin, cout e cerr, todos definidos na biblioteca iostream. Para uti-
lizar essa biblioteca, seu programa deve conter as seguintes linhas junto ao início do arquivo contendo seu código:
1.3
18 Fundamentos do C++
-
1 
#include 
using namespace std;
■ SAÍDA UTILIZANDO cout
Os valores das variáveis, assim como de strings de texto, podem ser apresentados como saída na tela por meio de
cout. Qualquer combinação de variáveis e strings pode ser apresentada. Por exemplo, considere as seguintes linhas
do programa no Painel 1.1:
coutlu-
gar de 2. Entretanto, quando você repete a fórmula mágica, só precisa repetir a última linha da fórmula. Se a fór-
mula mágica já apareceu uma vez em seu programa, a linha seguinte alterará o número de dígitos após o ponto
decimal para cinco para todos os valores subseqüentes de qualquer tipo de ponto flutuante apresentado na saída:
cout.precision(5);
SAÍDA DE VALORES DE TIPO double
Se você inserir a seguinte "fórmula mágica" em seu programa, todos os números de tipo double (ou qualquer outro tipo de
número de ponto flutuante) serão apresentados na saída em notação comum com dois dígitos após o ponto decimal:
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
Você pode usar qualquer outro número inteiro não-negativo no lugar do 2 para especificar um número diferente de dígitos
após o ponto decimal. Pode até usar uma variável de tipo int no lugar do 2.
■ SAIDA COM cerr
O objeto cerr é utilizado da mesma forma que cout. O objeto cerr envia sua saída para o fluxo de saída padrão
de erro, que normalmente é a tela do terminal. Isso proporciona a você uma forma de distinguir dois tipos de saí-
da: cout para a saída regular e cerr para a mensagem de saída de erro. Se você não fizer nada de especial para al-
terar as coisas, tanto cout quanto cerr enviarão suas saídas para a tela do terminal, de modo que não há diferença
entre eles.
Em alguns sistemas é possível redirecionar a saída do programa para um arquivo. Esta é uma instrução do sis-
tema operacional, não do C++, mas pode ser útil. Em sistemas que permitem o redirecionamento de saída, cout e
cerr podem ser redirecionados para arquivos diferentes.
Entrada/Saída de Terminal 21
■ ENTRADA UTILIZANDO cin
Usa-se cin para a entrada mais ou menos da mesma forma que cout para a saída. A sintaxe é similar, a não ser
pelo fato de cin ser usado no lugar de cout e de as setas apontarem para a direção oposta. Por exemplo, no pro-
grama no Painel 1.1, a variável numeroDeLinguagens era preenchida pelo seguinte comando cin:
cin >> numeroDeLinguagens;
Pode-se listar mais de uma variável em um único comando cin, como ilustrado a seguir:
cout > dragoes >> trolls;
Se você preferir, o comando cin acima pode ser escrito em duas linhas:
cin >> dragoes
 >> trolls;
Observe que, como no comando cout, há apenas um ponto-e-vírgula para cada ocorrência de cin.
Quando um programa chega a um comando cin, espera que a entrada seja fornecida a partir do teclado e
atribui à primeira variável o primeiro valor digitado ao teclado, à segunda variável o segundo valor digitado, e as-
sim por diante. Entretanto, o programa não lê a entrada até que o usuário pressione a tecla Return. Isso permite
que o usuário possa utilizar a tecla de retrocesso e corrigir erros na digitação de uma linha de entrada.
Os números na entrada devem ser separados por um ou mais espaços ou por uma quebra de linha. Quando se
usam comandos cin, o computador ignorará qualquer número de brancos ou quebras de linha até encontrar o
próximo valor de entrada. Assim, não importa se os números de entrada são separados por um ou vários espaços,
ou mesmo uma quebra de linha.
Você pode ler números inteiros, de ponto flutuante ou caracteres por meio de cin. Mais adiante neste livro
discutiremos a leitura de outros tipos de dados utilizando cin.
COMANDOS cin
Um comando cin atribui a variáveis valores digitados no teclado.
SINTAXE
cin >> Variavel_1 >> Variavel_2 >>...;
EXEMPLOS
cin >> numero >> tamanho;
cin >> tempoRestante
 >> pontosNecessarios;
Dica QUEBRAS DE LINHA EM E/S
É possível manter a saída e a entrada na mesma linha, e às vezes isso pode produzir uma interface mais
agradável para o usuário. Se você simplesmente omitir um \n ou endl ao final da última linha digitada ao
prompt, então a entrada do usuário aparecerá na mesma linha que o prompt. Por exemplo, suponha que
você use os seguintes comandos de prompt e entrada:
cout > custoPorPessoa;
Quando o comando cout é executado, o que aparecerá na tela é:
Digite o custo por pessoa: R$
Quando o usuário digitar a entrada, esta aparecerá na mesma linha, assim:
Digite o custo por pessoa: R$ 1.25
22 Fundamentos do C++
Exercícios de Autoteste
9. Forneça uma declaração de saída que produza a seguinte mensagem na tela:
A resposta à questão da
Vida, Universo e Sabe Lá o Que Mais é 42.
10. Forneça uma declaração de entrada que preencherá a variável oNumero (de tipo int) com um número
digitado ao teclado. Antes da declaração de entrada, coloque uma declaração de prompt pedindo ao usuário
para digitar um número inteiro.
11. Que declarações você incluiria em seu programa para assegurar que, quando um número de tipo double for
apresentado na saída, ele será apresentado em notação comum com três dígitos após o ponto decimal?
12. Escreva um programa completo em C++ que escreva a frase Olá mundo na tela. O programa não faz nada
além disso.
13. Forneça uma declaração de saída que produza a letra ’A’, seguida pelo caractere de nova linha, seguido pela
letra ’B’, seguido pelo caractere de tabulação, seguido pela letra ’C’.
Estilo de Programa
Em questões de muita importância, o estilo, não a sinceridade, é que é vital.
Oscar Wilde, A Importância de Ser Prudente
O estilo de programação em C++ é similar ao que é usado em outras linguagens. O objetivo é tornar o código
fácil de ler e de modificar. Vamos falar um pouco sobre o alinhamento no próximo capítulo. Já falamos a respeito
das constantes definidas. Em um programa, a maioria dos literais, senão todos, devem ser constantes definidas. A
escolha dos nomes de variáveis e um alinhamento cuidadoso eliminam a necessidade de muitos comentários, mas
quaisquer pontos que permanecerem obscuros merecem comentário.
■ COMENTÁRIOS
Existem duas formas de se inserir comentários em um programa em C++. Em C++, duas barras, //, são usadas
para indicar o início de um comentário. Todo o texto entre as // e o fim da linha é um comentário. O compila-
dor simplesmente ignora qualquer coisa que se siga às // em uma linha. Se você quiser um comentário que abran-
ja mais do que uma linha, coloque // em cada linha do comentário. Os símbolos // não possuem um espaço entre si.
Outro modo de se inserir comentários em um programa em C++ é usar o par de símbolos /* e */. O texto entre
esses símbolos é considerado um comentário e ignorado pelo compilador. Diferentemente dos comentários com //, que
requerem // adicionais em cada linha, os comentários entre /* e */ podem abranger várias linhas, como:
/* Este é um comentário que abrange
três linhas. Observe que não há nenhum símbolo
de comentário de nenhum tipo na segunda linha.*/
Comentários do tipo /* */ podem ser inseridos em qualquer lugar em um programa em que um espaço ou
quebra de linha seja permitido. Entretanto, eles não devem ser inseridos em qualquer lugar, a não ser que sejam
fáceis de ler e não perturbem a estrutura do programa. Normalmente, os comentários são colocados nos finais das
linhas ou em linhas separadas.
As opiniões diferem em relação a que tipo de comentário é melhor. As duas variedades (o tipo // ou /* */) podem
ser eficazes se usadas com cuidado. Um bom método é utilizar os comentários com // em códigos finais e reservar o es-
tilo /* */ para "comentar" o código (fazendo o compilador ignorar o trecho) quando se faz a depuração (debugging).
É difícil dizer quantos comentários deve conter um programa. A única resposta correta é "somente o necessá-
rio", o que, é claro, não significa muito para o programador iniciante. É necessário um pouco de experiência para se
saber quando é melhor incluir um comentário. Quando algo é importante e não óbvio, merece um comentário. Entre-
tanto, comentários demais são tão prejudiciais quanto de menos. Um programa que tenha comentários em cada linha
estará tão carregado de comentários que a estrutura do programa ficará oculta em um mar de observações óbvias. Co-mentários como o seguinte não contribuem em nada para a compreensão e não deveriam aparecer em um programa:
distancia = velocidade * tempo; // Calcula a distância percorrida.
1.4
Estilo de Programa 23
1 
Bibliotecas e Namespaces
O C++ vem com diversas bibliotecas-padrão. Essas bibliotecas colocam suas definições em um namespace, que
é simplesmente um nome dado a uma coleção de definições. As técnicas para incluir bibliotecas e lidar com na-
mespaces serão discutidas em detalhe mais adiante neste livro. Esta seção tratará apenas dos detalhes necessários
para que você utilize as bibliotecas-padrão C++.
■ BIBLIOTECAS E INSTRUÇÕES DE include
O C++ contém diversas bibliotecas-padrão. Na verdade, é quase impossível escrever um programa em C++ sem
utilizar pelo menos uma dessas bibliotecas. O jeito normal de se tornar uma biblioteca disponível em um programa é
com uma instrução de include. Uma instrução de include para uma biblioteca-padrão possui a forma:
#include 
Por exemplo, a biblioteca para E/S de terminal é iostream. Assim, a maioria de nossos programas de demons-
tração começará com
#include 
Os compiladores (pré-processadores) podem ser muito rigorosos com as questões de espaço em instruções de
include. Assim, é mais seguro digitar uma instrução de include sem nenhum espaço extra: nenhum espaço antes
de #, nenhum espaço depois de # e nenhum espaço dentro do .
Uma instrução de include é simplesmente uma instrução para incluir o texto que se encontra em um arquivo
no local especificado pela instrução de include. Um nome de biblioteca é apenas o nome de um arquivo que in-
clui todas as definições de itens na biblioteca. Mais tarde trataremos das instruções de include para outras coisas
que não as bibliotecas-padrão, mas por enquanto só precisaremos de instruções de include para bibliotecas-padrão
de C++. Uma lista de algumas bibliotecas-padrão de C++ é fornecida no Apêndice 4.
O C++ tem um pré-processador que lida com algumas manipulações textuais simples antes que o texto do seu
programa seja dado ao compilador. Algumas pessoas lhe dirão que as instruções de include não são processadas
pelo compilador, e sim por um pré-processador. Isso está correto, mas esta é uma diferença com a qual você não
deve se preocupar muito. Em quase todos os compiladores, o pré-processador é chamado automaticamente quan-
do você compila o seu programa.
Falando tecnicamente, apenas parte da definição da biblioteca é fornecida no arquivo de cabeçalho. Entretan-
to, neste estágio, esta não é uma distinção importante, já que utilizar a instrução de include com o arquivo de ca-
beçalho para uma biblioteca (em quase todos os sistemas) fará com que o C++ acrescente automaticamente o que
faltar da definição de biblioteca.
■ NAMESPACES
Um namespace é uma coleção de definições de nome. Um nome, como por exemplo um nome de função,
pode receber diferentes definições em dois namespaces. Um programa pode, então, utilizar um desses namespaces
em um lugar e o outro em outra localização. Vamos tratar dos namespaces em detalhe posteriormente neste livro.
Por enquanto, só precisamos falar a respeito do namespace std. Todas as bibliotecas-padrão que usaremos colocam
suas definições no namespace std (standard, ou padrão). Para usar qualquer dessas definições em seu programa,
você deve inserir as seguintes instruções de using:
using namespace std;
Assim, um programa simples que utilize E/S de terminal começará:
#include 
using namespace std;
Se você quiser que alguns nomes em um namespace, mas não todos, fiquem disponíveis em seu programa, há
uma forma da instrução de using que torna apenas um nome disponível. Por exemplo, se você quer tornar so-
mente o nome cin do namespace std disponível em seu programa, pode utilizar a seguinte instrução de using:
1.5
24 Fundamentos do C++
using std::cin;
Assim, se os únicos nomes do namespace std que seu programa utilizará forem cin, count e endl, você poderá
iniciar seu programa desta forma:
#include 
using std::cin;
using std::cout;
using std::endl;
em vez de
#include 
using namespace std;
Arquivos de cabeçalho de C++ mais antigos não colocavam suas definições no namespace std; então, se você
observar para códigos mais antigos de C++, provavelmente perceberá que os nomes dos arquivos de cabeçalho são
escritos de modo ligeiramente diferente e que o código não contém nenhuma instrução de using. Isso é permitido
para garantir a compatibilidade com programas mais antigos. Entretanto, você deve usar os arquivos de cabeçalhos
das bibliotecas mais novas e a instrução de namespace std.
Armadilha PROBLEMAS COM NOMES DE BIBLIOTECAS
A linguagem C++ está atualmente em transição. Um novo padrão surgiu, entre outras coisas, com novos
nomes para bibliotecas. Se você estiver usando um compilador que ainda não foi revisado para se adaptar
aos novos padrões, precisará adotar nomes diferentes de bibliotecas.
Se a seguinte instrução não funcionar
#include 
use
#include 
De forma similar, outros nomes de bibliotecas são diferentes em compiladores antigos. O Apêndice 5 fornece
a correspondência entre os nomes de bibliotecas antigos e novos. Este livro sempre utiliza os nomes dos
compiladores mais novos. Se um nome de biblioteca não trabalha com seu compilador, troque-o por um
nome de biblioteca correspondente mais antigo. Provavelmente ou todos os novos nomes de bibliotecas
funcionarão ou você precisará utilizar todos os nomes de bibliotecas antigos. É improvável que apenas
alguns dos nomes de bibliotecas tenham sido atualizados em seu sistema.
Se você utiliza os antigos nomes de bibliotecas (aqueles que terminam em .h), não precisa utilizar a
instrução
using namespace std;
Resumo do Capítulo
■ O C++ faz diferença entre maiúsculas e minúsculas. Por exemplo, count e COUNT são dois identificadores diferentes.
■ Utilize nomes significativos para as variáveis.
■ As variáveis devem ser declaradas antes de ser usadas. Desde que essa regra seja obedecida, uma declaração
de variável pode vir em qualquer lugar.
■ Assegure-se de que as variáveis sejam inicializadas antes que o programa tente utilizar seu valor. Isso pode ser
feito quando a variável é declarada com uma declaração de atribuição antes de ser utilizada pela primeira vez.
■ Você pode atribuir um valor de um tipo inteiro, como int, a uma variável de tipo de ponto flutuante,
como double, mas o contrário não é verdadeiro.
■ Quase todas as constantes numéricas em um programa devem receber nomes com significado que possam
ser utilizados em lugar dos números. Isso pode ser feito utilizando-se o modificador const em uma declara-
ção de variável.
■ Use parênteses em expressões aritméticas para tornar clara a ordem das operações.
■ O objeto cout é utilizado para a saída de terminal.
Bibliotecas e Namespaces 25
-
■ Um \n em uma string entre aspas ou um endl enviado para a saída do terminal inicia uma nova linha de saída.
■ O objeto cerr é utilizado para mensagens de erro. Em um ambiente típico, cerr se comporta da mesma
forma que cout.
■ O objeto cin é utilizado para a entrada de terminal.
■ Para usar cin, cout ou cerr, você deve colocar as seguintes instruções junto ao começo do arquivo com o
seu programa:
#include 
using namespace std;
■ Há duas formas de comentários em C++. Tudo o que se seguir a // na mesma linha é um comentário, e
tudo o que estiver entre /* */ é um comentário.
■ Não exagere nos comentários.
RESPOSTAS DOS EXERCÍCIOS DE AUTOTESTE
1. int pes = 0, polegadas = 0;
int pes(0), polegadas(0);
2. int count = 0;
double distancia = 1.5;
int count(0);
double distancia(1.5);
3. A saída real de um programa como esse depende do sistema e do histórico de uso do sistema.
#include 
using namespace std;
int main( )
{
 int primeiro, segundo, terceiro, quarto, quinto;
 cout+ y
(x + y)/7 Observe que x + y/7 não é correto.
(3*x + y)/(z + 2)
5. bcbc
6. (1/3) * 3 é igual a 0
Como 1 e 3 são do tipo int, o operador / efetua divisão de inteiros, que descarta o resto, assim o valor de
1/3 é 0, não 0.3333… Isso faz com que o valor da expressão toda, 0 * 3, seja igual, é claro, a 0.
7. #include 
using namespace std;
int main( )
{
 int numero1, numero2;
 cout > numero1 >> numero2;
 cout > oNumero;
11. cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(3);
12. #include 
using namespace std;
int main( )
{
 cout =. Tenha cuidado para utilizar um sinal duplo de igual, ==, para simbolizar o sinal de
igual e para utilizar os dois símbolos != para não-igual. Esses dois operadores-símbolo não
devem conter espaços entre os dois símbolos.
■ CONSTRUINDO EXPRESSÕES BOOLEANAS
Você pode combinar duas comparações utilizando o operador "e", que se escreve &&
em C++. Por exemplo, a seguinte expressão booleana é verdadeira desde que x seja maior
que 2 e x seja menor que 7:
(2 12)
Quando duas comparações são ligadas por meio de um ||, toda a expressão é verdadeira desde que uma ou
ambas as comparações sejam verdadeiras; caso contrário, toda a expressão é falsa.Você pode negar qualquer expressão booleana utilizando o operador !. Se quiser negar uma expressão boolea-
na, coloque a expressão entre parênteses e o operador ! na frente dele. Por exemplo, !(x = y. Em
alguns casos você pode omitir com segurança os parênteses, mas estes nunca causam nenhum dano. Os detalhes
exatos da omissão de parênteses serão dados na subseção intitulada Regras de Precedência.
 
Painel 2.1 Operadores de comparação
SÍMBOLO
MATEMÁTICO
PORTUGUÊS NOTAÇÃO
C++
C++ SIMPLES EQUIVALENTE
MATEMÁTICO
= Igual a == x + 7 == 2*y x + 7 = 2y
≠ diferente de != resp != ’n’ resp ≠ ’n’
 Maior que > tempo > limite tempo > limite
≥ Maior ou igual a >= idade >= 21 idade ≥ 21
STRINGS DE DESIGUALDADES
Não utilize uma string de desigualdades como x 0) && (resultado 7))
Painel 2.2 Tabelas da verdade
 OU
Exp_I Exp_2 Exp_I || Exp_2
true true true
true false true
false true true
false false false
 E
Exp_I Exp_2 Exp_I && Exp_2
true true true
true false false
false true false
false false false
 NÃO
Exp ! (Exp)
true false
false true
EXEMPLO (DENTRO DE UM COMANDO if-else)
if ( (x == 1) || (x == y))
cout 7) é true. Assim, a expressão booleana apresentada é equivalente a
!(false || true)
Consultando as tabelas para || (OU), o computador calcula essa expressão dentro dos parênteses como true.
Assim, o computador vê toda a expressão como equivalente a
!(true)
Consultando as tabelas novamente, o computador vê que !(true) é false, e conclui que false é o valor da
expressão booleana original.
■ REGRAS DE PRECEDÊNCIA
As expressões booleanas (e aritméticas) não precisam ficar todas entre parênteses. Se você omitir os parênteses,
a precedência-padrão é a seguinte: ! é executada primeiro, depois as operações relacionais como 90) && (umidade > 0.90) && (piscina == ABERTA)
Como os operadores relacionais > e == são executados antes da operação &&, você poderia omitir os parênteses na
expressão acima e ela teria o mesmo significado, mas incluir alguns parênteses torna a expressão mais legível.
Quando os parênteses são omitidos em uma expressão, o compilador agrupa os itens de acordo com regras co-
nhecidas como regras de precedência. A maioria das regras de precedência em C++ são fornecidas no Painel 2.3.
A tabela apresenta um número de operadores que serão discutidos mais adiante neste livro, mas que foram in-
cluídos para deixá-la mais completa e para aqueles que já são capazes de compreendê-los.
Painel 2.3 Precedência de operadores (parte 1 de 2)
:: Operador de resolução de escopo
.
→
[ ]
( )
++
–.–
Operador ponto
Seleção de membros
Indexação vetorial
Chamada de função
Operador de incremento em posição de sufixo (colocado após a variável)
Operador de decremento em posição de sufixo (colocado após a variável)
++
–.–
!
–
+
*
&
new
delete
delete [ ]
sizeof
( )
Operador de incremento em posição de prefixo (colocado antes da variável)
Operador de decremento em posição de prefixo (colocado antes da variável)
Não
Sinal negativo
Sinal positivo
Desreferenciação
Endereço de
Cria (aloca memória)
Destrói (libera)
Destrói vetor (libera)
Tamanho do objeto
Casting de tipo
*
/
%
Multiplicação
Divisão
Resto (módulo)
Maior precedência
(efetuado antes)
Menor precedência
(efetuado depois)
OS VALORES BOOLEANOS (bool) SÃO true E false
true e false são constantes predefinidas de tipo bool. (Devem ser escritas em letras minúsculas.) Em C++, uma expressão boo-
leana produz o valor bool true quando é satisfeita e o valor bool false quando não é satisfeita.
32 Fluxo de Controle
Painel 2.3 Precedência de operadores (parte 2 de 2)
+
–
AdiçãoSubtração
>
Operador de inserção (saída de console)
Operador de extração (entrada de console)
=
Menor que
Maior que
Maior ou igual a
Menor ou igual a
==
!=
Igual
Não-igual
&& E
|| Ou
= 
+=
–=
*=
/=
%=
Atribuição
Adição e atribuição
Subtração e atribuição
Multiplicação e atribuição
Divisão e atribuição
Módulo e atribuição
? : Operador condicional
throw Lança uma exceção
, Operador vírgula
Se uma operação é executada antes de outra, dizemos que a operação executada primeiro possui maior prece-
dência. Todos os operadores em uma dada caixa no Painel 2.3 possuem a mesma precedência. Os operadores nas
caixas mais elevadas apresentam maior precedência que os operadores de caixas mais baixas.
Quando os operadores têm a mesma precedência e a ordem não é determinada por parênteses, as operações
unárias são realizadas da direita para a esquerda. As operações de atribuição também são feitas da direita para a es-
querda. Por exemplo, x = y = z significa x = (y = z). Outras operações binárias que possuem as mesmas
precedências são executadas da esquerda para a direita. Por exemplo, x+y+z significa (x+y)+z.
Observe que as regras de precedência incluem tanto operadores aritméticos, como + e *, quanto operadores
booleanos, como && e ||. Isso porque muitas expressões combinam operações aritméticas e booleanas, como no
seguinte exemplo simples:
(x + 1) > 2 || (x + 1) 2) || ((x + 1) e 2 || x + 1 e o = 0) && (y > 1)
Menor precedência
(efetuado depois)
Todos os operadores da parte 2 têm menor precedência que os da parte 1.
Expressões Booleanas 33
Se x é negativo, então (x >= 0) é false. Como você pode ver nas tabelas do Painel 2.1, quando uma subex-
pressão em uma expressão && é false, toda a expressão é false, não importa se a outra expressão é true ou
false. Assim, se sabemos que a primeira expressão é false, não há necessidade de avaliar a segunda expressão.
Algo similar acontece com expressões com ||. Se a primeira de duas expressões unidas pelo operador || é true, en-
tão se sabe que toda a expressão é true, sem importar se a segunda expressão é true ou false. A linguagem C++
utiliza esse fato para, às vezes, poupar a si própria o trabalho de avaliar a segunda subexpressão em uma expressão
lógica ligada por um && ou ||. O C++ avalia primeiro a expressão mais à esquerda das duas expressões unidas
por && ou ||. Se esta fornece informação suficiente para determinar o valor final da expressão (independentemen-
te do valor da segunda expressão), o C++ não se preocupa em avaliar a segunda expressão. Esse método de avalia-
ção é chamado avaliação curto-circuito.
Algumas outras linguagens, que não C++, utilizam a avaliação completa. Na avaliação completa, quando duas
expressões estão unidas por && ou ||, ambas as subexpressões são sempre avaliadas e depois se utilizam as tabelas
de verdade para obter o valor da expressão final.
Tanto a avaliação curto-circuito quanto a avaliação completa fornecem a mesma resposta, então por que você
deveria se preocupar se o C++ utiliza a avaliação curto-circuito? Na maioria das vezes, não precisa se preocupar.
Desde que ambas as subexpressões unidas por && ou || possuam um valor, os dois métodos produzem o mesmo
resultado. Entretanto, se a segunda subexpressão é indefinida, talvez você fique feliz em saber que C++ utiliza a
avaliação curto-circuito. Vamos ver um exemplo que ilustra esta questão. Considere as seguintes linhas:
if ( (criancas != 0) && (( pedacos/criancas) >= 2) )
cout limite
Isso parece perfeito se você ler em voz alta: "não-tempo maior que limite". A expressão booleana está erra-
da, todavia, e o compilador não emitirá uma mensagem de erro. O compilador aplicará as regras de prece-
dência do Painel 2.3 e interpretará sua expressão booleana como o seguinte:
(!tempo) > limite
Isso parece absurdo, e intuitivamente é absurdo. Se o valor do tempo é, por exemplo, 36, qual poderia ser
o significado de (!tempo)? Afinal, isso é o equivalente a "não 36". Mas em C++ qualquer inteiro não-zero
se converte em true e 0 é convertido em false. Assim, !36 é interpretado como "não true" e produz como re-
sultado false, que é convertido novamente em 0, porque estamos fazendo a comparação com um int.
O que queremos como valor dessa expressão booleana e o que o C++ nos fornece não é o mesmo. Se
tempo possui um valor de 36 e limite, um valor de 60, você quer que a expressão booleana acima produza
como resultado true (porque é não true que tempo > limite). Infelizmente, a expressão booleana, em vez
disso, é executada da seguinte forma: (!tempo) é false e convertido em 0 e, assim, toda a expressão boo-
leana é equivalente a:
0 > limite
O que, por sua vez, é equivalente a 0 > 60, porque 60 é o valor de limite e isso é avaliado como false.
Assim, a expressão lógica acima é avaliada como false, quando você desejaria que fosse true.
Há duas formas de corrigir esse problema. Uma forma é usar o operador ! corretamente. Quando usar o opera-
dor !, inclua parênteses em torno do argumento. A forma correta de se escrever a expressão booleana acima é
34 Fluxo de Controle
 
 
Estruturas de Controle
Quando você chegar a uma bifurcação na estrada, siga por ela.
Atribuído ao Iogue Berra
■ COMANDOS if-else
Um comando if-else escolhe entre dois comandos alternativos, com base no valor de uma expressão boolea-
na. Por exemplo, suponha que você queira escrever um programa para calcular o salário semanal de um emprega-
do que ganha por hora de trabalho.Presuma que a empresa pague uma hora extra de 1,5 vezes a taxa regular
após as primeiras 40 horas trabalhadas. Quando o empregado trabalha 40 horas ou mais, o salário é igual a
taxa*40 + 1.5*taxa*(horas - 40)
2.2
!(tempo > limite)
Outra forma de corrigir o problema é evitar completamente a utilização do operador !. Por exemplo, a linha
seguinte também é correta e mais fácil de ler:
if (tempo 20) || (contagem = 0) )
h. ((limite/contagem) > 7) || (limite 7)
j. ((limite/contagem) > 7) && (limite 7)
l. (5 && 7) + (!6)
2. Às vezes você vê intervalos numéricos fornecidos como
2 40)
pagamentoBruto = taxa*40 + 1.5*taxa*(horas - 40);
else
pagamentoBruto = taxa*horas;
A sintaxe para um comando if-else é dada na tabela a seguir. Se a expressão booleana entre parênteses (de-
pois do if) resultar em true, então o comando antes de else é executado. Se a expressão booleana resultar em
false, o comando depois de else é executado.
Observe que um comando if-else possui comandos menores inseridos em seu interior. A maioria das formas
de comandos em C++ permite que se façam comandos maiores a partir de comandos menores combinando os co-
mandos menores de determinado modo.
Lembre-se de que, quando você utiliza uma expressão booleana em um comando if-else, a expressão boolea-
na deve estar entre parênteses.
COMANDO if-else
O comando if-else escolhe entre duas ações alternativas, com base no valor de uma expressão booleana. A sintaxe é mostrada
abaixo. Observe que a expressão booleana deve estar entre parênteses.
SINTAXE: UM COMANDO ÚNICO PARA CADA ALTERNATIVA
if (Expressao_Booleana)
Sim_Comando
else
Nao_Comando
Se a Expressao_Booleana é true, então Sim_Comando é executada. Se a Expressao_Booleana é false, então Nao_Comando é exe-
cutada.
SINTAXE: UMA SEQÜÊNCIA DE COMANDOS
if (Expressao_Booleana)
{
Sim_Comando_1
 Sim_Comando_2
 ...
 Sim_Comando_Final
}
else
{
Nao_Comando_1
Nao_Comando_2
 ...
Nao_Comando_Final
}
EXEMPLO
if (meusPontos > seusPontos)
{
cout seusPontos)
{
cout seusPontos){
cout = minimo)
salario = salario + bonus;
cout 0) && (1/(j+1) > 10))
coutEscreva um comando if-else que apresente como saída a palavra Alto, se o valor da variável pontos
for maior que 100, e Baixo, se o valor de pontos for no máximo 100. A variável pontos é do tipo int.
7. Suponha que economias e despesas são variáveis de tipo double que receberam valores. Escreva um co-
mando if-else que apresente como saída a palavra Solvente, subtraia o valor de despesas do valor de
economias e atribua o valor 0 a despesas desde que economias seja no mínimo igual a despesas. Se, to-
davia, economias for menor que despesas, o comando if-else simplesmente apresenta como saída a pa-
lavra Falido e não altera o valor de nenhuma variável.
8. Escreva um comando if-else que apresente como saída a palavra Aprovado desde que o valor da variá-
vel exame seja maior ou igual a 60 e o valor da variável programasFeitos seja maior ou igual a 10. Caso
contrário, o comando if-else apresenta como saída a palavra Reprovado. As variáveis exame e progra-
masFeitos são ambas de tipo int.
9. Escreva um comando if-else que apresente como saída a palavra Alerta desde que o valor da variável
temperatura seja maior ou igual a 100 ou o valor da variável pressao seja maior ou igual a 200, ou am-
bos. Caso contrário, o comando if-else apresenta como saída a palavra OK. As variáveis temperatura e
pressao são ambas de tipo int.
10. Qual é a saída dos seguintes trechos? Explique suas respostas.
a. if(0)
cout = -10
cout 0
cout 3)
if (x != 0)
cout 100
COMANDO switch
SINTAXE
switch (Expressao_De_Controle)
{
case Constante_1:
Sequencia_Do_Comando_1
break;
case Constante_2:
Sequencia_Do_Comando_2
break;
 . . .
Você não precisa colocar um comando break
em cada case. Se omitir um break, esse case
continua até encontrar um break (ou até o
final do comando switch).
40 Fluxo de Controle
Exercícios de Autoteste (continuação) 
O comando switch termina quando um comando break é encontrado ou quando se chega ao fim do coman-
do switch. Um comando break é formado pela palavra-chave break seguida por um ponto-e-vírgula. Quando o
computador executa os comandos depois de um case, continua até chegar a um comando break. Quando o com-
putador encontra um comando break, o comando switch se encerra. Se você omitir o comando break, então, de-
pois de executar o código para um case, o computador continuará e executará o código do próximo case.
Observe que se pode ter dois case para a mesma seção de código, como no seguinte trecho de um comando
switch:
case ’A’:
case ’a’:
 coutexpressão de controle, então nada acontecerá quan-
do o comando switch for executado. Entretanto, é mais seguro ter sempre uma seção default. Se você acha que
seus rótulos case listam todas as saídas possíveis, pode colocar uma mensagem de erro na seção default.
case Constante_n:
Sequencia_Do_Comando_n
break;
default:
Sequencia_Do_Comando_Default
}
EXEMPLO
int classeVeiculo;
double pedagio;
cout > classeVeiculo;
switch (classeVeiculo)
{
case 1:
cout n2)
max = n1;
else
max = n2;
Isto pode ser expresso utilizando o operador condicional da seguinte forma:
max = (n1 > n2) ? n1 : n2;
A expressão do lado direito da declaração de atribuição é a expressão de operador condicional:
(n1 > n2) ? n1 : n2
O ? e o : juntos formam um operador ternário conhecido como o operador condicional. Uma expressão de
operador condicional começa com uma expressão booleana seguida por um ? e depois seguida por duas expressões
separadas por dois-pontos. Se a expressão booleana é true, a primeira das duas expressões é fornecida; caso contrá-
rio, a segunda das duas expressões é que é fornecida.
 
Loops
Não é verdade que a vida seja uma chatice atrás da outra. É uma chatice que fica se repetindo.
Edna St. Vincent Millay
Carta a Arthur Darison Ficke, 24 de outubro de 1930
Os mecanismos de loop em C++ são semelhantes aos de outras linguagens de alto nível. Os três comandos
loop em C++ são o comando while, o comando do-while e o comando for. A mesma terminologia utilizada em
outras linguagens é utilizada em C++. O código repetido em um loop é chamado corpo do loop. Cada repetição
do corpo do loop é chamada de uma iteração do loop.
■ COMANDOS while E do-while
A sintaxe para o comando while e sua variante, o comando do-while, é fornecida na caixa que acompanha a
seção. Em ambos os casos, a sintaxe do corpo de múltiplos comandos é um caso especial da sintaxe para um loop
com um corpo de um comando único. O corpo de comandos múltiplos é um comando composto de comandos
únicos. Exemplos de um comando while e de um comando do-while são fornecidos nos Painéis 2.4 e 2.5.
2.3
16. Dadas as seguintes declarações e comando de saída, presuma que tenham sido inseridos em um progra-
ma correto, que é executado. Qual é a saída?
enum Direcao { N, S, L, O };
//...
cout 
2 using namespace std;
3 int main( )
4 {
5 int countDown;
6 cout > countDown;
8 
9 
10 
11 
12 
13 cout 0)
 {
 cout 
2 using namespace std;
3 int main( )
4 {
5 int countDown;
6 cout > countDown;
8 
9 
10 
11 
12 
13 couta expressão booleana é verificada antes que o corpo do loop seja
executado. Se a expressão booleana é avaliada como false, o corpo não é executado. Com um comando do-while, o
corpo do loop é executado primeiro, e a expressão booleana é verificada depois que o corpo do loop é executado.
Assim, o comando do-while sempre executa o corpo do loop pelo menos uma vez. Depois deste início, o loop
while e o do-while se comportam da mesma forma. Após cada iteração do corpo do loop, a expressão booleana é
verificada novamente; se for true, o loop é iterado outra vez. Caso tenha mudado de true para false, o coman-
do loop se encerra.
Painel 2.4 Exemplo de um comando while (parte 2 de 2)
Quantas saudações você quer? 0
Acabou! O corpo do loop é executado zero vezes.
 do
 {
 cout 0);
Quantas saudações você quer? 3
Olá Olá Olá
Acabou!
Quantas saudações você quer? 0
Olá
Acabou!
O corpo do loop é executado
pelo menos uma vez.
Loops 45
A primeira coisa que acontece quando um loop while é executado é que a expressão booleana de controle é
avaliada. Se a expressão booleana é avaliada como false a essa altura, o corpo do loop nunca é executado. Pode
parecer inútil executar o corpo de um loop zero vezes, mas às vezes esta é a ação desejada. Por exemplo, muitas
vezes se usa um loop while para somar uma lista de números, mas a lista poderia estar vazia. Para sermos mais es-
pecíficos, um programa de contabilidade de cheques poderia usar um loop while para somar os valores de todos
os cheques que você emitiu em um mês — mas você pode ter tirado um mês de férias, em que não emitiu ne-
nhum cheque. Nesse caso, há zeros a serem somados e, assim, o loop é iterado zero vezes.
■ NOVA VISÃO DOS OPERADORES DE INCREMENTO E DECREMENTO
Em geral não aconselhamos o uso de operadores de incremento e decremento em expressões. Entretanto, mui-
tos programadores gostam de utilizá-los nas expressões booleanas de controle de um comando while ou do-while.
Se realizado com cuidado, isso pode funcionar bem. Apresentamos um exemplo no Painel 2.6. Não se esqueça de
que em contagem++ 
2 using namespace std;
3 int main( )
4 {
5 int numeroDeProdutos, count,
6 caloriasPorProduto, totalCalorias;
7 cout > numberOfItems;
9 totalCalories = 0;
10 count = 1;
11 cout > caloriesForItem;
16 totalCalories = totalCalories
17 + caloriesForItem;
18 }
19 cout 0)
cout 0)
cout 0)
{
cout fosse substituído por 0);
25. Qual é a saída do seguinte trecho de programa? (x é de tipo int.)
int x = -42;
do
{
cout 0);
26. Qual é a diferença mais importante entre um comando while e um comando do-while?
Loops 47
1 Exercícios de Autoteste 1 
A primeira expressão é avaliada, depois a segunda. Como dissemos no Capítulo 1, a declaração de atribuição,
quando usada como uma expressão, fornece o novo valor da variável do lado esquerdo do operador de atribuição.
Assim, essa expressão vírgula fornece o valor final da variável segundo, o que significa que a variável resultado é
fixada como igual a 3.
Como apenas o valor da segunda expressão é fornecido, a primeira expressão é avaliada apenas por seus efeitos
colaterais. No exemplo anterior, o efeito colateral da primeira expressão é mudar o valor da variável primeiro.
Pode-se ter uma lista maior de expressões ligadas por vírgulas, mas isso deve ser feito somente quando a ordem de
avaliação não for importante. Se a ordem de avaliação for importante, você deve usar parênteses. Por exemplo:
resultado = ((primeiro = 2, segundo = primeiro + 1), terceiro = segundo + 1);
estabelece o valor de resultado como sendo 4. Entretanto, o valor que a seguinte linha dá a resultado é imprevi-
sível, porque não há garantias de que a expressão será avaliada em ordem:
resultado = (primeiro = 2, segundo = primeiro + 1, terceiro = segundo + 1);
Por exemplo, terceiro = segundo + 1 pode ser avaliado antes de segundo = primeiro + 1.1
■ COMANDO for
O terceiro e último comando loop em C++ é o comando for. O comando for é mais usado para se percorrer
uma variável inteira em incrementos iguais. Como veremos no Capítulo 5, o comando for geralmente é utilizado
para se percorrer um vetor. O comando for é, entretanto, um mecanismo geral de looping que pode fazer qual-
quer coisa que um loop while faça.
Por exemplo, o seguinte comando for soma os inteiros de 1 a 10:
soma = 0;
for (n = 1; nDrue Coles, Boston
University; Evan Golub, University of Maryland; Stephen Corbesero, Moravian College; Fredrick H. Colclough,
Colorado Technical University; Joel Weinstein, Northeastern University; Stephen P. Leach, Florida State Univer-
sity; Alvin S. Lim, Auburn University; e Martin Dulberg, North Carolina State University.
Mais uma vez, agradeço a David Teague, desta vez pelo seu excelente trabalho na preparação do manual do
professor.
Finalmente, agradeço a Christina por ter sido companheira quando eu ficava trabalhando até tarde no livro e
por haver me encorajado em vez de reclamar.
 Walter Savitch
 http://www-cse.ucsd.edu/users/savitch/
 wsavitch@ucsd.edu
VI Prefácio
Sumário
Capítulo 1 Fundamentos do C++ 1
1.1 Introdução ao C++ 1
1.2 Variáveis, Expressões e Declarações de Atribuição 4
1.3 Entrada/Saída de Terminal 18
1.4 Estilo de Programa 23
1.5 Bibliotecas e Namespaces 24
Capítulo 2 Fluxo de Controle 29
2.1 Expressões Booleanas 29
2.2 Estruturas de Controle 35
2.3 Loops 43
Capítulo 3 Fundamentos das Funções 61
3.1 Funções Predefinidas 61
3.2 Funções Definidas pelo Programador 69
3.3 Regras de Escopo 79
Capítulo 4 Parâmetros e Sobrecarga 91
4.1 Parâmetros 91
4.2 Sobrecarga e Argumentos-Padrão 103
4.3 Testando e Depurando Funções 110
Capítulo 5 Vetores 117
5.1 Introdução aos Vetores 117
5.2 Vetores em Funções 123
5.3 Programando com Vetores 132
5.4 Vetores Multidimensionais 139
Capítulo 6 Estruturas e Classes 153
6.1 Estruturas 153
6.2 Classes 162
Capítulo 7 Construtores e Outras Ferramentas 177
7.1 Construtores 177
7.2 Mais Ferramentas 191
7.3 Vectors — Introdução à Standard Template Library 200
SUMÁRIO 
Capítulo 8 Sobrecarga de Operador, Amigos e Referências 207
8.1 Fundamentos da Sobrecarga de Operador 207
8.2 Funções Amigas e Conversão de Tipo Automática 218
8.3 Referências e Mais Operadores Sobrecarregados 223
Capítulo 9 Strings 241
9.1 Tipo Vetor para Strings 241
9.2 Ferramentas de Manipulação de Caracteres 249
9.3 Classe-Padrão string 258
Capítulo 10 Ponteiros e Vetores Dinâmicos 277
10.1 Ponteiros 277
10.2 Vetores Dinâmicos 288
10.3 Classes, Ponteiros e Vetores Dinâmicos 297
Capítulo 11 Compilação Separada e Namespaces 313
11.1 Compilação Separada 313
11.2 Namespaces 324
Capítulo 12 E/S de Arquivo e Streams 343
12.1 Streams de E/S 344
12.2 Ferramentas para E/S de Stream 355
12.3 Hierarquias de Stream: Introdução à Herança 363
12.4 Acesso Aleatório a Arquivos 369
Capítulo 13 Recursão 377
13.1 Funções void Recursivas 377
13.2 Funções Recursivas que Retornam um Valor 386
13.3 Pensando Recursivamente 390
Capítulo 14 Herança 403
14.1 Fundamentos da Herança 403
14.2 Programando com Herança 409
Capítulo 15 Polimorfismo e Funções Virtuais 435
15.1 Princípios das Funções Virtuais 435
15.2 Ponteiros e Funções Virtuais 444
Capítulo 16 Templates (Gabaritos) 455
16.1 Templates de Função 455
16.2 Templates de Classe 464
16.3 Templates e Herança 472
Capítulo 17 Estruturas de Dados Ligadas 481
17.1 Nós e Listas Ligadas 482
17.2 Aplicações de Lista Ligada 498
17.3 Iteradores 508
17.4 Árvores 515
VIII Sumário
Capítulo 18 Tratamento de Exceções 529
18.1 Fundamentos do Tratamento de Exceções 530
18.2 Técnicas de Programação para o Tratamento de Exceções 543
Capítulo 19 Standard Template Library 549
19.1 Iteradores 550
19.2 Containers 559
19.3 Algoritmos Genéricos 569
Capítulo 20 Padrões e UML 585
20.1 Padrões 585
20.2 UML 593
Apêndice 1 599
Apêndice 2 600
Apêndice 3 602
Apêndice 4 603
Apêndice 5 608
Índice 609
Sumário IX
Fundamentos do C++
Capítulo 1C++ Básico
Fundamentos do C++
A Máquina Analítica não tem nenhuma pretensão de criar nada. Pode fazer qual-
quer coisa que saibamos como mandá-la fazer. Pode acompanhar a análise; mas não
tem o poder de antecipar quaisquer relações analíticas ou verdades. Sua ocupação é
nos assistir tornando disponível aquilo que já conhecemos.
Ada Augusta, Condessa de Lovelace
INTRODUÇÃO
Este capítulo apresenta a linguagem C++ e fornece detalhes suficientes para permitir que você
lide com programas simples envolvendo expressões, atribuições e entrada e saída (E/S) de ter-
minal. Os detalhes das atribuições e expressões são semelhantes aos da maioria de outras lin-
guagens de alto nível. Cada linguagem possui sua sintaxe de E/S de terminal; portanto, se
você não está familiarizado com C++, esse aspecto pode lhe parecer novo e diferente.
Introdução ao C++
A linguagem é o único instrumento da ciência.
Samuel Johnson
Esta seção fornece uma visão geral da linguagem de programação C++.
■ ORIGENS DA LINGUAGEM C++
Pode-se pensar nas linguagens de programação C++ como a linguagem de programa-
ção C com classes (e outros recursos modernos adicionados). A linguagem de programação C
foi desenvolvida por Dennis Ritchie, dos AT&T Bell Laboratories, na década de 70. Foi
usada, a princípio, para escrever e manter o sistema operacional UNIX. (Até aquela época,
os programas de sistema UNIX eram escritos em linguagem assembly ou em uma lingua-
gem chamada B, desenvolvida por Ken Thompson, o criador do UNIX.) C é uma lin-
guagem de finalidade geral que pode ser usada para escrever qualquer tipo de programa,
mas seu sucesso e popularidade estão intimamente ligados ao sistema operacional UNIX.
Se você quisesse preservar seu sistema UNIX, precisava usar C. C e UNIX se deram tão
bem que logo não só os programas de sistema mas quase todos os programas comerciais
executados no UNIX eram escritos na linguagem C. C se tornou tão popular que versões
da linguagem foram escritas para outros sistemas operacionais populares; assim, seu uso
não se limitou aos computadores que utilizavam UNIX. Entretanto, apesar de sua popula-
ridade, C não era uma linguagem isenta de problemas.
A linguagem C é peculiar porque é uma linguagem de alto nível com muitos recursos
de linguagem de baixo nível. C está entre os dois extremos, o de uma linguagem de nível
muito alto e o de uma linguagem de baixo nível, e nisso residem tanto sua força quanto
sua fraqueza. Como a linguagem (de baixo nível) assembly, os programas em linguagem
1.1
CAPÍTULO 
C podem manipular diretamente a memória do computador. Por outro lado, C possui recursos de uma linguagem
de alto nível, o que a torna mais fácil de ler e escrever do que a linguagem assembly. Isso faz de C uma excelente
escolha para escrever programas de sistema, mas para outros programas (e em certo sentido até para programas de
sistema) C não é tão fácil de entender quanto outras linguagens; além disso, não possui tantas verificações auto-
máticas quanto outras linguagens de alto nível.
Para superar essas e outras desvantagens de C, Bjarne Stroustrup, dos AT&T Bell Laboratories, desenvolveu o
C++ no início da década de 80. Stroustrup projetou o C++ como um C aperfeiçoado. A maior parte da lingua-
gem C é um subconjunto da C++, e, assim, muitos programas em C também são programas em C++. (O inverso
não é verdade; muitos programas em C++ não são, definitivamente, programas em C.) Ao contrário de C, C++
possui recursos para classes e, portanto, pode ser usada para a programação orientada a objetos.
■ C++ E PROGRAMAÇÃO ORIENTADA A OBJETOS
A programação orientada a objetos (Object-oriented programming — OOP) é uma técnica de programação
atual popular e poderosa. As principais características da OOP são encapsulamento, herança e polimorfismo. O encap-
sulamento é uma forma de ocultação de informação, ou abstração. A herança tem a ver com a escrita de código reuti-
lizável. O polimorfismo se refere à forma pela qual um único nome pode ter múltiplos significados no contexto da
herança. Tendo dado essas definições, precisamos admitir que elas possuem pouco significado para os leitores que nun-
ca ouviram falaro operador vírgula, você pode acrescentar múltiplas ações à primeira ou à última (mas normalmen-
te não à segunda) das três expressões dentro dos parênteses. Por exemplo, você pode deslocar a inicialização da va-
riável soma para dentro do loop for para obter a seguinte linha, que é equivalente ao código do comando for que
mostramos anteriormente:
for (soma = 0, n = 1; n = 0; numero--)
{
cout 0)
cout = 0; numero--)
 cout = 0)
 {
 coutpara sempre (em princípio), tal como o principal loop externo de um
programa de reservas de passagens aéreas, que só fica pedindo mais reservas até que você desligue o com-
27. Qual é a saída do seguinte trecho (quando inserido em um programa completo)?
for (int contagem = 1; contagem 0; n = n - 2)
{
cout 0; amostra = amostra - 0.5)
 cout 0)
{
cout 
2 using namespace std;
3 int main( )
4 {
5 int numero, soma = 0, contagem = 0;
6 cout 
2 using namespace std;
3 int main( )
4 {
5 int numero, soma = 0, contagem = 0;
6 cout > number;
 if (number >= 0)
 {
 cout > numero;
 if (numero >= 0)
 {
 cout = 1; m--)
 coutobter o equivalente da instrução "repita o corpo do loop n vezes".
■ Um loop pode ser interrompido por meio do comando break. Uma única iteração do corpo do loop pode
ser interrompida por meio do comando continue. Não se deve exagerar no uso de comandos break. É
melhor evitar comandos continue, embora alguns programadores os utilizem em raras ocasiões.
RESPOSTAS DOS EXERCÍCIOS DE AUTOTESTE
1. a. true.
b. true. Observe que as expressões a e b querem dizer exatamente a mesma coisa. Como os operadores
== e 7), envolve uma divisão por zero.
i. true. Como o valor da primeira expressão, (limite 7),
nunca é avaliada e, portanto, o fato de que envolve uma divisão por zero nunca é notado pelo compu-
tador. Trata-se de uma avaliação curto-circuito.
j. Esta expressão produz um erro quando é avaliada porque a primeira subexpressão, ((limite/contagem)
> 7), envolve uma divisão por zero.
k. false. Como o valor da subexpressão, (limite 7),
nunca é avaliada e, portanto, o fato de que envolve uma divisão por zero nunca é notado pelo compu-
tador. Trata-se de uma avaliação curto-circuito.
Respostas dos Exercícios de Autoteste 55
Resumo do Capítulo 
l. Se você acha que esta expressão é absurda, tem razão. A expressão não possui nenhum significado in-
tuitivo, mas o C++ converte os valores int para bool e avalia as operações && e !. Assim, o C++ ava-
liará essa bagunça! Lembre-se de que em C++ qualquer inteiro não-zero se converte em true, e 0 se
converte em false. Logo, C++ avaliará
(5 && 7) + (!6)
da seguinte forma: na expressão (5 && 7), 5 e 7 se convertem em true; true && true se convertem em
true, que o C++ converte em 1. Na expressão (!6) 6 é convertido em true, e !(true) resulta em false, que
o C++ converte em 0. Assim, a expressão inteira resulta em 1 + 0, que é 1. O valor final é 1. O C++ con-
verterá o número 1 em true, mas a resposta não possui grande significado intuitivo como true; talvez seja
melhor dizer apenas que a resposta é 1. Você não precisa se especializar em avaliar expressões absurdas como
esta, mas um pouco de treino ajudará a entender por que o compilador não fornece uma mensagem de erro
quando você se engana e mistura operadores numéricos e booleanos em uma única expressão.
2. A expressão 2 2)
4. (x > 1) && (x 0) é false (j acabou de receber a atribuição do valor -1). O &&
utiliza avaliação curto-circuito, que não avalia a segunda expressão se o resultado final puder ser determi-
nado pela primeira expressão. A primeira expressão é false, então a segunda não tem importância.
 6. if (pontos > 100)
cout = despesas)
{
economias = economias - despesas;
despesas = 0;
cout = 60) && (programasFeitos >= 10) )
cout = 100) || (pressao >= 200) )
cout 100)
cout3 vezes 10 = 30
.
.
.
PROJETOS DE PROGRAMAÇÃO
1. É difícil elaborar um orçamento que abranja vários anos, porque os preços não são estáveis. Se sua
empresa necessita de 200 lápis por ano, você não pode simplesmente utilizar o preço dos lápis este ano
para uma projeção para daqui dois anos. Devido à inflação, o custo provavelmente será maior do que é
hoje. Escreva um programa para estimar o custo esperado de um item em um número especificado de
anos. O programa pede o custo de cada item, o número de anos, a partir de agora, em que os itens serão
adquiridos e a taxa de inflação. Então, o programa apresenta como saída o custo estimado de cada item
após o período especificado. Faça com que o usuário informe a taxa de inflação como uma porcentagem,
como, por exemplo, 5,6 (por cento). Seu programa deve converter a porcentagem em uma fração, como
0,056, e utilizar um loop para estimar o preço ajustado com a inflação. (Dica: utilize um loop.)
58 Fluxo de Controle
2. Você acaba de adquirir um aparelho estereofônico que custa R$ 1.000 por meio do seguinte plano de cre-
diário: zero de entrada, juros de 18% ao ano (e, portanto, 1,5% ao mês) e prestações mensais de R$ 50.
A prestação mensal de R$ 50 é utilizada para pagar os juros, e o restante é utilizado para pagar parte da
dívida remanescente. Assim, no primeiro mês você paga 1,5% de R$ 1.000 em juros. Isso dá R$ 15. Os
restantes R$ 35 são deduzidos do seu débito, o que o deixa com um débito de R$ 965,00. No mês se-
guinte você paga um juro de 1,5% sobre R$ 965,00, que dá R$ 14,48. Assim, você pode deduzir
R$ 35,52 (que é R$ 50 – R$ 14,48) da soma que deve.
Escreva um programa que lhe diga quantos meses você levará para pagar o que deve, assim como a soma
total paga em juros. Utilize um loop para calcular a soma paga em juros e o tamanho do débito a cada
mês. (Seu programa final não precisa fornecer a quantia paga mensalmente a título de juros, mas você
pode querer escrever uma versão preliminar do programa que apresente esses valores.) Utilize uma variável
para contar o número de iterações do loop e, portanto, o número de meses até que o débito seja zero.
Você pode querer utilizar outras variáveis também. O último pagamento pode ser inferior a R$ 50 se o
débito for menor, mas não se esqueça dos juros. Se você deve R$ 50, então sua prestação mensal de
R$ 50 não saldará seu débito, embora vá chegar perto disso. Os juros de um mês sobre R$ 50 são de
apenas 75 centavos.
Projetos de Programação 59
Página em branco
Fundamentos das Funções
Fundamentos das Funções
Capítulo 3Os Fundamentos das Funções
Os melhores perfumes vêm nos menores frascos.
Sabedoria popular
INTRODUÇÃO
Se você já programou em alguma outra linguagem, o conteúdo deste capítulo lhe será
bastante familiar. Mesmo assim, você deve dar uma olhada neste capítulo para ver a sinta-
xe e a terminologia de C++ para os fundamentos das funções. O Capítulo 4 contém o
material sobre funções em C++ que pode ser diferente das outras linguagens.
Pode-se considerar que um programa consiste em subpartes, como a obtenção dos da-
dos de entrada, o cálculo dos dados de saída e a exibição dos dados de saída. C++, como
a maioria das linguagens de programação, possui recursos para nomear e codificar cada
uma dessas partes em separado. Em C++, essas subpartes são chamadas funções. A maioria
das linguagens de programação possui funções ou algo similar, embora nem sempre sejam
chamadas por esse nome. Os termos procedimento, subprograma e método, dos quais você
já deve ter ouvido falar, significam essencialmente a mesma coisa que função. Em C++,
uma função pode retornar um valor (produzir um valor) ou pode executar alguma ação
sem retornar um valor, mas, quer a subparte forneça um valor ou não, ainda é chamada
de função em C++. Este capítulo apresenta os detalhes básicos sobre as funções em C++.
Antes de lhe dizer como escrever suas próprias funções, vamos lhe contar como utilizar al-
gumas das funções predefinidas do C++.
Funções Predefinidas
Não reinvente a roda.
Sabedoria popular
O C++ vem com bibliotecas de funções predefinidas que você pode utilizar em seus progra-
mas. Existem dois tipos de funções em C++; funções que retornam (produzem) um valor e fun-
ções que não retornam um valor. Funções que não retornam um valor são chamadas de funções
void. Primeiro falaremos das funções que retornam um valor, e depois das funções void.
■ FUNÇÕES PREDEFINIDAS QUE RETORNAM UM VALOR
Vamos usar a função sqrt para ilustrar como se utiliza uma função predefinida que
retorna um valor. A função sqrt calcula a raiz quadrada de um número. (A raiz quadrada
de um número é aquele número que, quando multiplicado por si mesmo, produzirá o
número com o qual você começou. Por exemplo, a raiz quadrada de 9 é 3, porque 32 é
igual a 9.) A função sqrt começa com um número, como 9.0, e calcula sua raiz quadra-
da, no caso 3.0. O valor da função começa com o que é chamado seu argumento. O va-
3.1
CAPÍTULO 
lor que ela calcula é chamado de valor retornado. Algumas funções podem ter mais de um argumento, mas ne-
nhuma função pode ter mais de um valor retornado.
A sintaxe para utilizar funções em seu programa é simples. Para estabelecer que uma variável chamada aRaiz é
igual à raiz quadrada de 9.0, você pode utilizar a seguinte declaração de atribuição:
aRaiz = sqrt(9.0);
A expressão sqrt(9.0) é conhecida como uma chamada de função ou invocação de função. Um argumento
em uma função pode ser uma constante, como 9.0, uma variável, ou uma expressão mais complicada. Uma cha-
mada de função é uma expressão que pode ser usada como qualquer outra expressão. Por exemplo, o valor retor-
nado por sqrt é do tipo double; portanto, a linha seguinte é legal (embora talvez muito restrita):
bonus = sqrt(vendas)/10;
vendas e bonus são variáveis que normalmente seriam do tipo double. A chamada de função sqrt(vendas) é um
item único, como se estivesse entre parênteses. Assim, a declaração de atribuição acima é equivalente a
bonus = (sqrt(vendas))/10;
Você pode utilizar uma chamada de função onde seja legal utilizar uma expressão do tipo especificado pelo va-
lor retornado pela função.
O Painel 3.1 contém um programa completo que utiliza a função predefinida sqrt. O programa calcula o ta-
manho da maior casinha de cachorro que pode ser construída com a quantidade de dinheiro que o usuário está
disposto a gastar. O programa pede ao usuário uma quantia e, então, determina quantos pés* quadrados de área
podem ser adquiridos com essa quantia. O cálculo fornece a área da casinha de cachorro em pés quadrados. A
função sqrt fornece o comprimento de um lado do piso da casinha.
A biblioteca cmath contém a definição da função sqrt e diversas outras funções matemáticas. Se seu programa
utiliza uma função predefinida de alguma biblioteca, deve conter uma instrução de include que dê nome a essa
biblioteca. Por exemplo, o programa no Painel 3.1 utiliza a função sqrt e assim contém
#include 
Este programa em particular possui duas instruções de include. Não importa em que ordem estejam essas ins-
truções. As instruções de include foram discutidas no Capítulo 1.
As definições para funções predefinidas normalmente colocam essas funções no ambiente de nomes std e tam-
bém requerem a seguinte instrução de using, como ilustrado no Painel 3.1:
using namespace std;
Painel 3.1 Função predefinida que retorna um valor (parte 1 de 2)
1 //Calcula o tamanho de uma casinha de cachorro que possa ser adquirida
2 //dado o orçamento do usuário.
3 #include > budget;
12 area = budget/COST_PER_SQ_FT;
13 lengthSide = 
14 cout.setf(ios::fixed);
15 cout.setf(ios::showpoint);
#include 
using namespace std;
sqrt(area);
62 Fundamentos das Funções
* Um pé equivale a 30,48 cm. (N. do R.T.)
16 cout.precision(2);17 cout 
Observe também que existem três funções de valor absoluto. Se você quiser produzir o valor absoluto de um
número de tipo int, utilize abs; se quiser produzir o valor absoluto de um número do tipo long, utilize labs; e
se quiser produzir o valor absoluto de um número de tipo double, utilize fabs. Para complicar ainda
mais as coisas, abs e labs estão na biblioteca com o arquivo de cabeçalho cstdlib, enquanto fabs está na biblio-
teca com o arquivo de cabeçalho cmath. fabs é uma abreviação de floating-point absolute value (valor absoluto de
ponto flutuante). Lembre-se de que os números com uma fração após o ponto decimal (ou vírgula decimal),
como os números de tipo double, geralmente são chamados de números de ponto flutuante.
Outro exemplo de uma função predefinida é pow, que está na biblioteca com o arquivo de cabeçalho cmath. A
função pow pode ser usada para efetuar a potenciação em C++. Por exemplo, se você quiser fixar uma variável re-
sultado como igual a xy, pode utilizar a forma:
resultado = pow (x, y);
Painel 3.1 Função predefinida que retorna um valor (parte 2 de 2)
Informe quanto quer gastar com a casinha de cachorro $25.00
Por um preço de $25.00
Posso construir uma magnífica casinha de cachorro
com 1.54 pés em cada lado.
FUNÇÕES QUE RETORNAM UM VALOR
Para uma função que retorna um valor, uma chamada de função é uma expressão que consiste no nome da função seguido por
argumentos entre parênteses. Se houver mais de um argumento, os argumentos são separados por vírgulas. Se a chamada da
função retornar um valor, então a chamada da função é uma expressão que pode ser usada como qualquer outra expressão do
tipo especificado para o valor retornado pela função.
SINTAXE
Nome_Da_Funcao(Lista_De_Argumentos)
em que Lista_De_Argumentos é uma lista de argumentos separados por vírgulas:
Argumento_1, Argumento_2, . . . , Argumento_Final
EXEMPLOS
lado = sqrt(area);
cout 
using namespace std;
A linha seguinte é uma amostra de invocação (amostra de chamada) da função exit:
exit(1);
Uma invocação à função exit encerra o programa imediatamente. O Painel 3.3 contém um programa que de-
monstra a função exit.
Painel 3.3 Chamada de função para uma função void predefinida (parte 1 de 2)
1 #include 
2
3
4 int main( )
5 {
6 couté executado), o programa termina imediatamente. Qualquer
Valor_Inteiro pode ser usado, mas, por convenção, 1 é usado para uma chamada a exit que seja provocada por um erro, e 0 é
usado em outros casos.
A definição da função exit está na biblioteca cstdlib e coloca a função exit no ambiente de nomes std (namespace std). Por-
tanto, qualquer programa que utilizar a função exit deve conter as seguintes instruções:
#include 
using namespace std;
#include 
using namespace std;
exit(1);
Este é apenas um exemplo fictício.
Produziria o mesmo efeito se você
omitisse estas linhas.
Funções Predefinidas 65
/ 
DIÁLOGO PROGRAMA-USUÁRIO
 
Observe que a função exit possui um argumento, que é de tipo int. O argumento é fornecido para o sistema opera-
cional. No que se refere ao seu programa em C++, você pode utilizar qualquer valor int como argumento, mas, por con-
venção, 1 é utilizado para uma chamada a exit que seja provocada por um erro, e 0 é utilizado nos outros casos.
Uma função void pode ter qualquer número de argumentos. Os detalhes a respeito dos argumentos para fun-
ções void são os mesmos que para as funções que retornam um valor. Em particular, se você utilizar um argu-
mento do tipo errado, em muitos casos o C++ realizará a conversão automática de tipos para você. Entretanto, os
resultados podem não ser os que você esperava.
 
■ GERADOR DE NÚMEROS ALEATÓRIOS
Gerador de números aleatórios é uma função que retorna um número "aleatoriamente escolhido". É diferente
das funções que já vimos até agora, no sentido de que o valor retornado não é determinado por argumentos (que
normalmente não existem), e sim por algumas condições globais. Como é possível pensar-se no valor retornado
como sendo um número aleatório, pode-se utilizar um gerador de números aleatórios para simular eventos aleató-
rios, como o resultado do lançamento de um dado ou moeda. Além de simular jogos de azar, os geradores de nú-
meros aleatórios podem ser usados para simular coisas que, estritamente falando, podem não ser aleatórias, mas
que parecem ser, como o intervalo de tempo entre a chegada de carros em um posto de pedágio.
A biblioteca C++ com o arquivo de cabeçalho contém uma função de números aleatórios chamada
rand. Essa função não possui argumentos. Quando seu programa invoca rand, a função retorna um inteiro no intervalo
entre 0 e RAND_MAX, inclusive. (O número gerado pode ser igual a 0 ou a RAND_MAX.) RAND_MAX é uma constante inteira
definida cuja definição também está na biblioteca com o arquivo de cabeçalho . O valor exato de RAND_MAX
depende do sistema, mas será no mínimo 32767 (o máximo inteiro positivo de dois bytes). Por exemplo, as linhas se-
guintes apresentam como saída uma lista de dez números "aleatórios" no intervalo entre 0 e RAND_MAX:
int i;
for (i = 0; i 
using namespace std;
Funções Predefinidas 67
* O número 11 é chamado de fator de escala. (N. do R.T.)
O Painel 3.4 mostra um programa que utiliza o gerador de números aleatórios para "prever" o clima. Nesse
caso, a previsão é aleatória, mas algumas pessoas a consideram tão boa quanto qualquer previsão meteorológica.
(As previsões meteorológicas podem, na realidade,ser bastante precisas, mas este programa é apenas um jogo para
ilustrar os números pseudo-aleatórios.)
Observe que, no Painel 3.4, o valor da semente usado para o argumento de srand é o mês multiplicado pelo
dia. Assim, se o programa é reexecutado e a mesma data é fornecida, a mesma previsão será dada. (Claro que se
trata de um programa bastante simples. A previsão para o dia depois do dia 14 pode ou não ser a mesma que a
do dia 15, mas esse programa serve como um exemplo simples.)
Probabilidades geralmente são representadas como um número de ponto flutuante entre 0.0 e 1.0. Suponha
que você queira uma probabilidade aleatória em vez de um inteiro aleatório. Isso pode ser produzido por outra
forma de ajuste de escala. A linha seguinte gera um valor de ponto flutuante pseudo-aleatório entre 0.0 e 1.0:
rand( )/static_cast (RAND_MAX)
A conversão (cast) de tipo é feita para que obtenhamos uma divisão de ponto flutuante em vez de uma divisão
de inteiros.
Painel 3.4 Função utilizando um gerador de número aleatório (parte 1 de 2)
1 #include 
2
3
4 int main( )
5 {
6 int month, day;
7 cout > month;
10 cin >> day;
11 
12 int prediction;
13 char ans;
14 cout > ans;
34 } while (ans == ’y’ || ans == ’Y’);
35 cout 
using namespace std;
srand(month*day);
rand( ) %
68 Fundamentos das Funções
-
Painel 3.4 Função utilizando um gerador de número aleatório (parte 2 de 2)
DIÁLOGO PROGRAMA-USUÁRIO
 
Funções Definidas pelo Programador
Um terno feito sob medida sempre cai melhor do que um de marca.
Meu tio, alfaiate
A seção anterior explicou como utilizar funções predefinidas. Esta seção lhe dirá como definir suas próprias
funções.
■ DEFININDO FUNÇÕES QUE RETORNAM UM VALOR
Você pode definir suas próprias funções, no mesmo arquivo da parte principal do seu programa (main) ou em
um arquivo separado, de modo que as funções possam ser utilizadas por vários programas diferentes.
A definição é a mesma em ambos os casos, mas por enquanto vamos assumir que a definição da função esteja
no mesmo arquivo que a parte main do seu programa. Esta subseção trata apenas de funções que retornam um va-
lor. Uma subseção posterior lhe dirá como definir funções void.
O Painel 3.5 contém uma amostra de definição de função que é um programa completo demonstrando uma
chamada à função. A função se chama custoTotal e requer dois argumentos — o preço de um item e o número
de itens adquiridos. A função retorna o custo total, incluindo imposto sobre vendas, para todos os itens com o
preço especificado. A função é chamada da mesma forma que uma função predefinida. A definição da função que
o programador deve escrever é um pouco mais complicada.
A descrição da função é fornecida em duas partes. A primeira parte é chamada declaração de função ou protótipo
de função. A linha seguinte é a declaração de função (protótipo de função) da função definida no Painel 3.5:
double custoTotal(int numeroParametro, double precoParametro);
Bem-vindo ao seu programa de previsão do tempo.
Informe a data de hoje utilizando dois inteiros para o mês e para o dia:
2 14
Previsão para hoje:
O dia será nublado.
Quer a previsão para o dia seguinte? (s/n): s
O dia será nublado.
Quer a previsão para o dia seguinte? (s/n): s
Vai haver fortes chuvas!
Quer a previsão para o dia seguinte? (s/n): s
Vai haver fortes chuvas!
Quer a previsão para o dia seguinte? (s/n): s
O dia será ensolarado!!
Quer a previsão para o dia seguinte? (s/n): n
Este é o final do seu programa de previsão do tempo de 24 horas.
5. Forneça uma expressão para produzir um número inteiro pseudo-aleatório no intervalo entre 5 e 10 (in-
clusive).
6. Escreva um programa completo que peça ao usuário uma semente e depois apresente uma lista de dez
números aleatórios baseados nessa semente. Os números devem ser de ponto flutuante no intervalo
entre 0.0 e 1.0 (inclusive).
3.2
Funções Definidas pelo Programador 69
1 Exercícios de Autoteste 1 
1 
A primeira palavra em uma declaração de função especifica o tipo do valor retornado pela função. Assim, para
a função custoTotal, o tipo do valor retornado é double. A seguir, a declaração de função diz a você o nome da
função; nesse caso, custoTotal. A declaração de função diz a você (e ao compilador) tudo o que você precisa sa-
ber para escrever e utilizar uma chamada de função. Diz a você quantos argumentos a função requer e de que
tipo; nesse caso, a função custoTotal requer dois argumentos, o primeiro de tipo int e o segundo de tipo dou-
ble. Os identificadores numeroParametro e precoParametro são chamados de parâmetros formais, ou simplesmen-
te parâmetros. Um parâmetro formal é utilizado como um tipo de espaço em branco, ou "guardador" de lugar,
para ficar no lugar do argumento. Quando escreve uma declaração de função, você não sabe o que vão ser os ar-
gumentos, então utiliza os parâmetros formais no lugar dos argumentos. Nomes de parâmetros formais podem ser
quaisquer identificadores válidos. Observe que uma declaração de função termina com um ponto-e-vírgula.
Embora a declaração de função lhe revele tudo o que precisa saber para escrever uma chamada de função, não
lhe conta que valor será retornado como saída. O valor retornado é determinado pela definição de função. No
Painel 3.3 a definição de função está nas linhas 2 a 30 do programa. Uma definição de função descreve como a
função calcula o valor que retorna como saída. Uma definição de função consiste em um cabeçalho de função se-
guido por um corpo de função. Um cabeçalho de função é escrito de forma similar à declaração de função, a não
ser pelo fato de o cabeçalho não ter um ponto-e-vírgula no final. O valor retornado é determinado pelos coman-
dos no corpo da função.
O corpo da função segue o cabeçalho e completa a definição da função. O corpo da função consiste em de-
clarações e comandos executáveis entre chaves. Assim, o corpo da função é exatamente como o corpo da parte
main de um programa. Quando uma função é chamada, os valores do argumento são conectados aos parâmetros
formais e os comandos do corpo da função são executados. O valor retornado pela função é determinado quando
a função executa um comando return. (Os detalhes dessa "conexão" serão discutidos no Capítulo 4.)
Painel 3.5 Função utilizando um gerador de número aleatório (parte 1 de 2)
1 #include 
2 using namespace std;
3
4 //Calcula o custo total, inclusive 5% de imposto sobre a venda,
5 //em numberParameter itens a um custo de priceParameter cada.
6 int main( )
7 {
8 double price, bill;
9 int number;
10 cout > number;
12 cout > price;
14 bill = 
15 cout.setf(ios::fixed);
16 cout.setf(ios::showpoint);
17 cout.precision(2);
18 couttambém chamada de
protótipo de função.
totalCost(number, price); Chamada de função
70 Fundamentos das Funções
24
25
26 
27 
28
29
30
DIÁLOGO PROGRAMA-USUÁRIO
Um comando return é formado pela palavra-chave return seguida por uma expressão. A definição de função
no Painel 3.5 contém o seguinte comando return:
return (subtotal + subtotal*IMPOSTO)
Quando esse comando return é executado, o valor da seguinte expressão é retornado como o valor da chama-
da de função:
(subtotal + subtotal*IMPOSTO)
Os parênteses não são necessários. O programa será executado da mesma forma se os parênteses forem omiti-
dos. Entretanto, com expressões mais longas, os parênteses tornam o comando return mais legível. Para obter
maior consistência, alguns programadores aconselham o uso desses parênteses mesmo com expressões simples. Na
definição de função no Painel 3.3 não há nenhum comando após o comando return, mas, se houvesse, o comando
não seria executado. Quando um comando return é executado, a chamada de função termina.
Observe que o corpo da função pode conter quaisquer comandos em C++ e que os comandos serão executa-
dos quando a função for chamada. Assim, uma função que retorna um valor pode executar qualquer outra ação
além de retornar um valor. Na maioria dos casos, todavia, o principal objetivo de uma função que retorna um va-
lor é retornar esse valor.
Ou a definição de função completa ou a declaração de função (protótipo de função) devem aparecer no códi-
go antes que a função seja chamada. O mais comum é a declaração de função e a parte main do programa apare-
cerem em um ou mais arquivos, com a declaração de função antes da parte main, e a definição da função aparecer
em outro arquivo. Não abordamos ainda a questão da divisão de um programa em mais de um arquivo, e por
isso colocaremos as definições de função depois da parte main do programa. Se a definição de função completa for
colocada antes da parte main do programa, a declaração da função pode ser omitida.
■ FORMA ALTERNATIVA PARA DECLARAÇÕES DE FUNÇÃO
Não é preciso listar os nomes de parâmetros formais em uma declaração de função (protótipo de função). As
duas declarações de função seguintes são equivalentes:
double custoTotal(int numeroParametro, double precoParametro);
e
double custoTotal(int, double);
Normalmente utilizamos a primeira forma para nos referir aos parâmetros formais no comentário que acompa-
nha a declaração de função. Entretanto, muitas vezes você encontrará a segunda forma em manuais.
Painel 3.5 Função utilizando um gerador de número aleatório (parte 2 de 2)
double totalCost(int numberParameter, double priceParameter)
{
 const double TAXRATE = 0.05; //5% de imposto sobre a venda
 double subtotal;
 subtotal = priceParameter * numberParameter;
 return (subtotal + subtotal*TAXRATE);
}
Cabeçalho de função
Definição de função
Corpo da
função
Informe o número de itens adquiridos: 2
Informe o preço por item: $10.10
2 itens a $10.10 cada.
A soma final, incluindo impostos, é $21.21
Funções Definidas pelo Programador 71
Esta forma alternativa se aplica apenas a declarações de função. Uma definição de função deve sempre listar os
nomes dos parâmetros formais.
 
 
■ FUNÇÕES CHAMANDO FUNÇÕES
Um corpo de função pode conter chamada para outra função. A situação para esses tipos de chamadas de fun-
ção é a mesma que se a chamada de função houvesse ocorrido na parte main do programa; a única restrição é que
a declaração de função (ou definição de função) deve aparecer antes de a função ser usada. Se você houver mon-
tado seu programa conforme nossas orientações, isso ocorrerá automaticamente, já que todas as declarações de
função vêm antes da parte main do programa e todas as definições de função vêm depois da parte main do progra-
ma. Embora seja possível incluir uma chamada de função dentro da definição de outra função, não se pode colo-
car a definição de uma função dentro do corpo de outra definição de função.
 
ARGUMENTOS NA ORDEM ERRADA
Quando uma função é chamada, o computador substitui o primeiro parâmetro formal pelo primeiro argu-
mento, o segundo parâmetro formal pelo segundo argumento e assim por diante. Embora o computador ve-
rifique o tipo de cada argumento, ele não verifica a coerência. Se você confundir a ordem dos argumentos, o
programa não vai saber o que você pretendeu fazer. Se houver uma violação de tipo devido a um argumen-
to de tipo errado, você receberá uma mensagem de erro. Se não houver violação de tipo, seu programa pro-
vavelmente será executado normalmente, mas o valor retornado pela função será incorreto.
USO DOS TERMOS PARÂMETRO E ARGUMENTO
O uso dos termos parâmetro formal e argumento que adotamos neste livro é consistente com o uso comum,
mas muitas vezes os termos parâmetro e argumento são utilizados de forma invertida. Quando vir os termos
parâmetro e argumento, você deve determinar seu significado exato a partir do contexto. Muitas pessoas
utilizam o termo parâmetro tanto para o que chamamos de parâmetros formais quanto para o que chama-
mos de argumentos. Outras adotam o termo argumento tanto para o que chamamos de parâmetros formais
quanto para o que chamamos argumentos. Não espere consistência na forma como as pessoas utilizam es-
ses termos. (Neste livro, às vezes empregamos o termo parâmetro significando parâmetro formal, mas isto é
mais uma abreviação do que uma verdadeira inconsistência.)
FUNÇÃO ARREDONDADORA
A tabela de funções predefinidas (Painel 3.2) não inclui qualquer função para o arredondamento de um nú-
mero. As funções ceil e floor são quase, mas não completamente, funções arredondadoras. A função ceil
sempre retorna o próximo número inteiro maior (ou seu argumento, se for um número inteiro). Assim,
ceil(2.1) retorna 3.0, não 2.0. A função floor sempre retorna o próximo número inteiro menor que o ar-
gumento, ou igual a ele. Assim, floor(2.9) retorna 2.0, não 3.0. Felizmente, é fácil definir uma função que
faça um verdadeiro arredondamento. A função é definida em Painel 3.6. A função round arredonda seu argu-
mento para o inteiro mais próximo. Por exemplo, round(2.3) retorna 2 e round (2.6) retorna 3.
Para verificar se round funciona corretamente, vamos utilizar alguns exemplos. Considere round(2.4). O va-
lor retornado é o seguinte (convertido em um valor int):
floor(2.4 + 0.5)
que é floor(2.9), ou 2.0. Na verdade, para qualquer número que seja maior ou igual a 2.0 e estritamente
menor que 2.5, esse número mais 0.5 será menor que 3.0 e, assim, floor aplicado a esse número mais 0.5
retornará 2.0. Assim, round aplicado a qualquer número maior ou igual a 2.0 e estritamente menor que 2.5
apresentará como resultado 2. (Como a declaração de função para round especifica que o tipo para o valor
retornado é int, convertemos o tipo do valor calculado em int.)
Agora considere números maiores ou iguais a 2.5; por exemplo, 2.6. O valor retornado pela chamada
round(2.6) é o seguinte (convertido em valor int):
floor(2.6 + 0.5)
que é floor(3.1) ou 3.0. Na realidade, para qualquer número que seja maior que 2.5 e menor ou igual a
3.0, esse número mais 0.5 será maior que 3.0. Assim, round chamada com qualquer número que seja maior
que 2.5 e menor que 3.0 apresentará como resultado 3.
Desse modo, round funciona corretamente para todos os argumentos entre 2.0 e 3.0. É óbvio que não exis-
te nada de especial em relação aos argumentos entre 2.0 e 3.0. Um argumento similar se aplica a todos os
números não-negativos. Portanto, round funciona corretamente para todos os argumentos não-negativos.
72 Fundamentos das Funções
Painel 3.6 Função round
1 #include 
2 #include 
3 using namespace std;
4
5
6
7 int main( )
8 {
9 double doubleValue;
10 char ans;
11 do
12 {
13 cout > doubleValue;
15 cout > ans;
18 }while (ans == ’s’|| ans == ’s’);
19 cout (floor(number + 0.5));
26 }
DIÁLOGO PROGRAMA-USUÁRIO
 
int round(double number);
//Assumes number >= 0. 
//Returns number rounded to the nearest integer.
Teste do programa
de função round
round(doubleValue)
Forneça um valor double: 9.6
Arredondado, esse número é 10
Outra vez? (s/n): s
Forneça um valor double: 2.49
Arredondado, esse número é 2
Outra vez? (s/n): n
Fim do teste.
7. Qual é a saída produzida pelo seguinte programa?
#include 
using namespace std;
char misterio(int primeiroParametro, int segundoParametro);
int main( )
{
 cout = 10) && (taxa = 10) && (taxa = segundoParametro)
 return ’G’’;
 else
 return ’R’;
}
8. Escreva uma declaração de função (protótipo de função) e uma definição de função para uma função
que necessite de três argumentos, todos de tipo int, e que forneça a soma desses três argumentos.
9. Escreva uma declaração e uma definição de função para uma função que necessite de um argumento de
tipo double. A função retorna o valor de caractere ’P’, se seu argumento for positivo, e ’N’, se seu ar-
gumento for zero ou negativo.
10. Pode uma definição de função aparecer dentro do corpo de outra definição de função?
11. Liste as similaridades e diferenças entre como se invoca (chama) uma função predefinida (ou seja, de bi-
blioteca) e uma função definida pelo usuário.
12. Escreva uma definição de função para uma função chamada emOrdem que requer três argumentos de tipo
int. A função apresenta como saída true se os três argumentos estiverem em ordem ascendente; caso
contrário, apresenta como saída false. Por exemplo, tanto emOrdem(1, 2, 3) quanto emOrdem(1, 2,
2) apresentam true como saída, enquanto emOrdem(1, 3, 2) apresenta false como saída.
13. Escreva uma definição de função para uma função chamada par que requer um argumento de tipo int e
retorna um valor bool. A função apresenta true como saída se seu único argumento for um número
par; caso contrário, apresenta false como saída.
14. Escreva uma definição de função para uma função chamada digito que requer um argumento de tipo
char e retorna um valor bool. A função apresenta true como saída se o argumento for um dígito deci-
mal; caso contrário, apresenta false como saída.
74 Fundamentos das Funções
Exercícios de Autoteste (continuação) 
1 Exercícios de Autoteste 1 
void mostraResultados(double fGraus, double cGraus)
{
 cout.setf(ios::fixed);
 cout.setf(ios::showpoint);
 cout.precision(1);
 coutfunção
apresenta como saída instruções para dividir uma dada quantidade de sorvete entre as pessoas de uma mesa. Se
não existirem pessoas na mesa (ou seja, se numero é igual a 0), o comando return dentro do comando if termina
a chamada de função e evita uma divisão por zero. Se numero não é 0, a chamada de função termina quando o
último comando cout é executado ao final do corpo da função.
■ PRÉ-CONDIÇÕES E PÓS-CONDIÇÕES
Uma boa forma de se escrever um comentário de declaração de função é dividi-lo em dois tipos de informa-
ção, chamadas pré-condição e pós-condição. A pré-condição afirma o que se presume ser verdade quando a função
é chamada. A função não deve ser usada e não se deve esperar que atue corretamente a não ser que a pré-condi-
ção se sustente. A pós-condição descreve o efeito da chamada de função; ou seja, a pós-condição diz o que será
verdadeiro depois que a função é executada em uma situação na qual a pré-condição se sustenta. Para uma função
que retorna um valor, a pós-condição descreverá o valor retornado pela função. Para uma função que altera o valor
Painel 3.7 Uso de return em uma função void (parte 1 de 2)
1 #include 
2 using namespace std;
3 void iceCreamDivision(int number, double totalWeight);
4 //Mostra na tela as instruções para dividir totalWeight onças de sorvete entre
5 //o número de pessoas. Se o número for 0, apenas uma mensagem de erro será mostrada.
6 int main( )
7 {
8 int number;
9 double totalWeight;
DECLARAÇÃO DE FUNÇÃO (PROTÓTIPO DE FUNÇÃO)
Uma declaração de função (protótipo de função) informa tudo o que você precisa saber para escrever uma chamada de função.
Uma declaração de função (ou a definição de função completa) deve aparecer em seu código antes da chamada à função. Decla-
rações de função normalmente são colocadas antes da parte main do seu programa.
SINTAXE
Tipo_Retornado_Ou_void NomeDaFuncao(Lista_De_Parametros);
em que Lista_De_Parametros é uma lista de parâmetros separada por vírgulas:
Tipo_1 Parametro_Formal_1, Tipo_2 Parametro_Formal_2, ...
... Tipo_Final Parametro_Formal_Final
EXEMPLOS
double pesoTotal(int numero, double pesoDeUm);
//Retorna o peso total de numero itens
//cujo peso unitário é pesoDeUm.
void mostraResultados(double fGraus, double cGraus);
//Exibe uma mensagem dizendo que fGraus Fahrenheit
//equivalem a cGraus Celsius.
Não se esqueça deste ponto-e-vírgula.
76 Fundamentos das Funções
----
Painel 3.7 Uso de return em uma função void (parte 2 de 2)
10 cout > number;
12 cout > totalWeight;
14 iceCreamDivision(number, totalWeight);
15 return 0;
16 }
17 void iceCreamDivision(int number, double totalWeight)
18 {
19 double portion;
20 if (number == 0)
21 {
22 cout 
using namespace std;
void amigavel( );
void timida(int contagemPlateia);
int main( )
{
 amigavel( );
 timida(6);
 coutde OOP. Entretanto, descreveremos todos esses termos em detalhes no decorrer deste livro. C++ favo-
rece a OOP fornecendo classes, um tipo de dado que combina dados e algoritmos. C++ não é o que algumas
autoridades chamariam de uma "linguagem pura de OOP". C++ compatibiliza seus recursos OOP com preocupações
em relação à eficiência e o que poderíamos chamar de "praticidade". Essa combinação tornou o C++ a linguagem de
OOP mais amplamente utilizada, embora nem sempre seu uso siga estritamente a filosofia da OOP.
■ CARACTERÍSTICAS DO C++
C++ possui classes que permitem sua utilização como uma linguagem orientada a objetos. Admite a sobrecarga
de funções e operadores. (Todos esses termos serão explicados ao longo do texto; não fique preocupado se não en-
tender alguns deles.) A ligação do C++ com a linguagem C lhe fornece uma aparência mais tradicional do que a
das linguagens orientadas a objetos mais recentes, e, no entanto, ele possui mais mecanismos poderosos de abstra-
ção do que muitas das linguagens populares atuais. C++ possui modelos que possibilitam a implementação total e
direta da abstração do algoritmo. Os modelos de C++ permitem que se escreva código utilizando parâmetros para
tipos. Os mais novos padrões de C++ e a maioria dos compiladores de C++ permitem namespaces múltiplos para
possibilitar maior reutilização dos nomes de classes e funções. Os recursos de tratamento das exceções são seme-
lhantes aos encontrados em outras linguagens de programação. O gerenciamento da memória em C++ é semelhan-
te ao de C. O programador deve alocar sua própria memória e lidar com sua própria coleção de lixo. A maioria
dos compiladores permitirá que você faça em C++ um gerenciamento de memória estilo C, já que o C é, em essência,
um subconjunto de C++. Entretanto, o C++ também tem sua própria sintaxe para um gerenciamento de memória es-
tilo C++, e seria aconselhável que você utilizasse o estilo C++ de gerenciamento de memória ao escrever código em
C++. Este livro utiliza apenas o gerenciamento de memória estilo C++.
■ TERMINOLOGIA DO C++
Todas as entidades semelhantes a procedimentos são chamadas de funções em C++. Tudo o que é chamado
de procedimento, método, função ou subprograma em outras linguagens é chamado de função em C++. Como vere-
mos na próxima subseção, um programa em C++ é basicamente apenas uma função chamada main. As outras ter-
minologias de C++ são praticamente as mesmas que as de outras linguagens de programação e serão explicadas
quando da apresentação de cada conceito.
■ AMOSTRA DE PROGRAMA EM C++
O Painel 1.1 contém um programa simples em C++ e duas possíveis saídas de tela que podem ser geradas
quando um usuário executa o programa. Um programa em C++ é, na realidade, uma definição de função para
2 Fundamentos do C++
uma função chamada main. Quando o programa é executado, a função chamada main é invocada. O corpo da
função main fica entre chaves, { }.Quando o programa é executado, as declarações entre as chaves são executadas.
As duas linhas seguintes fazem com que as bibliotecas com entrada e saída de terminal estejam disponíveis
para o programa. Os detalhes concernentes a essas duas linhas e tópicos relativos são tratados na Seção 1.3 e nos
Capítulos 9, 11 e 12.
# include 
using namespace std;
A linha seguinte diz que main é uma função sem parâmetros que ao terminar sua execução retornará um valor
inteiro int:
int main ( )
Alguns compiladores permitirão que você omita o int ou substitua-o por void, o que indica uma função que
não retorna nenhum valor. Entretanto, a forma acima é a mais aceita universalmente para iniciar a função main
em um programa C++.
O programa termina quando o seguinte comando é executado:
return 0;
Este comando termina a invocação da função main e fornece 0 como o valor da função. De acordo com o pa-
drão ANSI/ISO C++, este comando não é obrigatório, mas muitos compiladores o exigem. O Capítulo 3 discutirá
as funções de C++ em todos os detalhes.
Painel 1.1 Amostra de programa em C++ (parte 1 de 2)
1 #include 
2 using namespace std;
3 int main( )
4 {
5 int numberOfLanguages;
6 cout > numberOfLanguages;
10 if (numberOfLanguages > numeroDeLinguagens;
A primeira linha faz com que o texto entre aspas seja exibido na tela. A segunda linha lê um número que o
usuário digita no teclado e estabelece o número digitado como o valor da variável numeroDeLinguagens,
As linhas
coutdeclaradas em uma definição de função são chamadas variá-
veis locais e são o assunto desta seção.
■ VARIÁVEIS LOCAIS
Dê uma olhada no programa do Painel 3.1. Ele inclui uma chamada à função predefinida sqrt. Não precisa-
mos saber nada sobre os detalhes da definição de função de sqrt a fim de utilizar essa função. Em particular, não
precisamos saber que variáveis foram declaradas na definição de sqrt. Uma função que você defina não é diferen-
te. Declarações de variáveis dentro de uma definição de função são como se fossem declarações de variáveis em uma
função predefinida ou em outro programa. Se você declara uma variável em uma definição de função e depois declara
outra variável com o mesmo nome na função main do programa (ou no corpo de alguma outra definição de função),
então essas duas variáveis são diferentes, mesmo que possuam o mesmo nome. Vamos ver um exemplo.
O programa no Painel 3.8 possui duas variáveis chamadas ervilhaMedia; uma é declarada e utilizada na defi-
nição da função estimativaDoTotal, e a outra é declarada e utilizada na função main do programa. A variável er-
vilhaMedia na definição de função para estimativaDoTotal e a variável ervilhaMedia na função main são duas
variáveis diferentes. É como se a função estimativaDoTotal fosse uma função predefinida. As duas variáveis cha-
madas ervilhaMedia não interferirão uma com a outra, tanto quanto duas variáveis em dois programas completa-
mente diferentes não interfeririam.
Painel 3.8 Variáveis locais (parte 1 de 2)
1 //Calcula o rendimento médio de uma plantação experimental de ervilhas.
2 #include 
3 using namespace std;
4 double estimateOfTotal(int minPeas, int maxPeas, int podCount);
5 //Retorna uma estimativa do número total de ervilhas colhidas.
6 //O parâmetro formal podCount é o número de vagens.
7 //Os parâmetros formais MinPeas são o número mínimo
8 //e máximo de ervilhas em uma vagem.
9 int main( )
10 {
11 int maxCount, minCount, podCount;
12 double , yield;
13 cout > minCount >> maxCount;
15 cout > podCount;
17 cout > 
19 yield =
20 estimateOfTotal(minCount, maxCount, podCount) * averagePea;
21 cout.setf(ios::fixed);
3.3
averagePea
Esta variável chamada
ervilhaMedia é o local da
função main.
averagePea;
Regras de Escopo 79
1 
-----------
22 cout.setf(ios::showpoint);
23 cout.precision(3);
24 coutestiver dentro da definição de uma função, como no Painel 3.5, o nome IMPOSTO é local à
definição de função, o que significa que, fora da definição da função que contém a declaração, você pode usar o
nome IMPOSTO para outra constante nomeada, ou variável, ou qualquer outra coisa.
Por outro lado, se essa declaração aparecer no início do programa, fora do corpo de todas as funções (e fora
do corpo da parte main do programa), diz-se que a constante nomeada é uma constante nomeada global e a
constante nomeada pode ser usada em qualquer definição de função que siga a declaração da constante.
ABSTRAÇÃO PROCEDURAL
Quando aplicado a uma definição de função, o princípio da abstração procedural significa que sua função deve ser escrita de
modo que possa ser utilizada como uma caixa preta. Isso quer dizer que o programador que utiliza a função não deve precisar
olhar para o corpo da definição da função para ver como a função opera. A declaração de função e o comentário que a acom-
panha são tudo o que o programador precisa saber a fim de utilizar a função. Para garantir que suas definições de função te-
nham essa importante propriedade, obedeça estritamente às seguintes regras:
COMO ESCREVER UMA DEFINIÇÃO DE FUNÇÃO CAIXA PRETA
■ O comentário da declaração de função deve dizer ao programador toda e qualquer condição requerida dos argumentos da
função e deve descrever o resultado de uma invocação à função.
■ Todas as variáveis utilizadas no corpo da função devem ser declaradas no corpo da função. (Os parâmetros formais não pre-
cisam ser declarados, porque estão listados no cabeçalho da função.)
Regras de Escopo 81
O Painel 3.9 mostra um programa com um exemplo de uma constante nomeada global. O programa pede o
valor de um raio e depois calcula tanto a área de um círculo quanto o volume de uma esfera com aquele raio, uti-
lizando as seguintes fórmulas:
area = π x (raio)2
volume = (4/3) x π x (raio)3
Ambas as fórmulas incluem a constante π, que é aproximadamente igual a 3.14159. O símbolo π é a letra
grega chamada "pi". O programa utiliza a seguinte constante nomeada global:
const double PI = 3.14159;
que aparece fora da definição de qualquer função (inclusive fora da definição de main).
O compilador permite a você uma ampla liberdade quanto ao local onde deve colocar as declarações de suas
constantes nomeadas globais. Para facilitar a leitura, contudo, você deve colocar todas as suas instruções de inclu-
de juntas, todas as suas declarações de constantes nomeadas globais em outro grupo e todas as suas declarações de
função (protótipos de função) juntas. Seguiremos a prática-padrão e colocaremos todas as nossas declarações de cons-
tantes nomeadas globais após as instruções de include e using e antes das declarações de função.
Painel 3.9 Constante nomeada global (parte 1 de 2)
1 //Calcula a área de um círculo e o volume de uma esfera.
2 //Utiliza o mesmo raio para ambos os cálculos.
3 #include 
4 #include 
5 using namespace std;
6 const double PI = 3.14159;
7 double area(double radius);
8 //Retorna a área de um círculo com o raio especificado.
9 double volume(double radius);
10 //Retorna o volume de uma esfera com o raio especificado.
11 int main( )
12 {
13 double radiusOfBoth, areaOfCircle, volumeOfSphere;
14 cout > radiusOfBoth;
17 areaOfCircle = area(radiusOfBoth);
18 volumeOfSphere = volume(radiusOfBoth);
19 coutnome. Uma variável exis-
te só dentro do bloco interno e não se pode ter acesso a ela fora do bloco interno. A outra variável existe apenas
no bloco externo e não se pode ter acesso a ela no bloco interno. As duas variáveis são distintas, portanto mudan-
ças realizadas em uma delas não exercerão efeito sobre a outra.
 
■ VARIÁVEIS DECLARADAS EM UM LOOP for
Uma variável pode ser declarada no cabeçalho de um comando for de modo que a variável seja ao mesmo
tempo declarada e inicializada no início do comando for. Por exemplo,
for (int n = 1; n 
#include 
using namespace std;
int main( )
{
 int i;
 for (i = 1; i 
#include 
using namespace std;
int main( )
{
 cout > semente;
 srand(semente);
 cout (RAND_MAX))
 0)
 return ’P’;
 else
 return ’N’;
} 
10. Não, uma definição de função não pode aparecer dentro do corpo de outra definição de função.
11. Funções predefinidas e funções definidas pelo usuário são invocadas (chamadas) da mesma forma.
12. bool emOrdem(int n1, int n2, int n3)
{
 return ((n1 
using namespace std;
void produto(int n1, int n2, int n3);
int main( )
{
 int num1, num2, num3;
 cout > num1 >> num2 >> num3;
 produto(num1, num2, num3);
 return 0;
}
void produto(int n1, int n2, int n3)
{
 cout = 0.
//Retorna a raiz quadrada de n.
Você pode reescrever a segunda linha de comentário da seguinte forma, se preferir, mas a versão acima é
a forma usual utilizada para uma função que retorna um valor:
//Pós-condição: Retorna a raiz quadrada de n.
20. Se você usar uma variável em uma definição de função, deve declarar a variável no corpo da definição de
função.
21. Tudo vai dar certo. O programa compilará (presumindo-se que todo o resto esteja correto). O programa
será executado (presumindo-se que todo o resto esteja correto). O programa não gerará mensagem de erro
quando forexecutado (presumindo-se que todo o resto esteja correto). O programa fornecerá a saída cor-
reta (presumindo-se que todo o resto esteja correto).
22. O comentário explica que ação a função efetua, inclusive o valor retornado, e apresenta qualquer outra in-
formação de que você necessite a fim de utilizar a função.
23. O princípio da abstração procedural afirma que uma função deve ser escrita de modo a poder ser utilizada
como uma caixa preta. Isso significa que o programador que utiliza a função não precisa olhar para o cor-
po da definição de função para saber como essa função atua. A declaração de função e os comentários que
a acompanham devem ser suficientes para que o programador possa utilizar a função.
24. Quando dizemos que o programador que utiliza a função deve ser capaz de tratar a função como uma
caixa preta, queremos dizer que o programador não precisa olhar para o corpo da definição de função
para saber como a função atua. A declaração de função e os comentários que a acompanham devem ser
suficientes para que o programador possa utilizar a função.
Respostas dos Exercícios de Autoteste 87
25. Alterar levemente o código ajuda a entender a que se refere cada declaração. O código possui três variáveis
diferentes chamadas x. No trecho seguinte, renomeamos essas três variáveis como x1, x2 e x3. A saída é
dada nos comentários.
{
 int x1 = 1;// saída nesta coluna
 cout 
 {
 cout 
 int x2 = 2;
 cout 
 {
 cout 
 int x3 = 3;
 cout 
 }
 cout 
 }
 cout 
}
PROJETOS DE PROGRAMAÇÃO
1. Um litro equivale a 0.264179 galões. Escreva um programa que leia o número de litros de gasolina con-
sumidos pelo carro do usuário e o número de milhas* que o carro andou e apresente como saída o núme-
ro de milhas por galão que o carro rendeu. Seu programa deve permitir que o usuário repita o cálculo
quantas vezes quiser. Defina uma função para calcular o número de milhas por galão. Seu programa deve
usar uma constante globalmente definida para o número de galões por litro.
2. Escreva um programa para medir a taxa de inflação no ano passado. O programa pede o preço de um
item (como um cachorro quente ou um diamante de um quilate) no ano passado e hoje. Estima a taxa de
inflação como a diferença no preço dividida pelo preço do ano passado. Seu programa deve permitir que o
usuário repita esse cálculo quantas vezes desejar. Defina uma função para calcular a taxa de inflação. A taxa de
inflação deve ser um valor de tipo double, fornecendo a taxa como porcentagem, por exemplo, 5.3 para 5.3%.
3. Aperfeiçoe o programa do exercício anterior fazendo com que apresente também o preço estimado do
item um e dois anos depois da época do cálculo. O aumento no custo em um ano é estimado como a
taxa de inflação multiplicada pelo preço no início do ano. Defina uma segunda função para determinar o
custo estimado de um item em um número especificado de anos, dados o preço atual do item e a taxa de
inflação como argumentos.
4. A força de atração gravitacional entre dois corpos com massas m1 e m2, separados por uma distância d, é
dada pela seguinte fórmula:
F = 
Gm1m2
d 2
onde G é a constante de gravitação universal:
G = 6.673 x 10-8 cm3/(g • sec2)
Escreva uma definição de função que utilize argumentos para as massas de dois corpos e a distância entre
eles e forneça a força gravitacional entre eles. Como você irá utilizar a fórmula acima, a força gravitacional
será dada em dynes (dinas). Um dyne (dina) equivale a
1g • cm/sec2
Você deve usar uma constante globalmente definida para a constante de gravitação universal. Insira sua defini-
ção de função em um programa completo que calcule a força gravitacional entre dois objetos com dados de
entrada adequados. Seu programa deve permitir que o usuário repita esse cálculo quantas vezes desejar.
* Uma milha terrestre equivale a 1,609 km. (N. do R.T.)
88 Fundamentos das Funções
5. Escreva um programa que peça a altura, o peso e a idade do usuário e calcule o tamanho das roupas de
acordo com as seguintes fórmulas.
■ Tamanho do chapéu = peso em libras* dividido pela altura em polegadas e tudo isso multiplicado por 2.9.
■ Tamanho do casaco (tórax em polegadas) = altura vezes peso dividido por 288 e um ajuste efetuado
pelo acréscimo de um oitavo de uma polegada para cada 10 anos acima dos 30 anos. (Observe que o
ajuste só ocorre após 10 anos completos. Assim, não há ajuste para as idades de 30 a 39, mas um oi-
tavo de uma polegada é acrescentado para a idade 40.)
■ Cintura em polegadas = peso dividido por 5.7 e um ajuste efetuado pelo acréscimo de um décimo de
uma polegada para cada 2 anos acima dos 28 anos. (Observe que o ajuste só ocorre após 2 anos com-
pletos. Assim, não há ajuste para os 29 anos, mas um décimo de uma polegada é acrescentado para os
30 anos.)
Utilize funções para cada cálculo. Seu programa deve permitir que o usuário repita esse cálculo quantas
vezes desejar.
6. Escreva uma função que calcule o desvio médio e padrão de quatro pontuações. O desvio-padrão é defini-
do como a raiz quadrada da média dos quatro valores: (si - a)2, em que a é a média das quatro pontua-
ções, s1, s2, s3 e s4. A função terá seis parâmetros e chamará duas outras funções. Insira a função em um
programa que lhe permita testar a função repetidas vezes até dizer ao programa que terminou.
7. Quando está frio, os meteorologistas transmitem um índice chamado fator de frio do vento, que leva em
consideração a velocidade do vento e a temperatura. O índice fornece uma medida do efeito resfriador do
vento em uma dada temperatura do ar. Esse índice pode ser aproximado pela seguinte fórmula:
W = 13.12 + 0.6215*t – 11.37*v0.16 + 0.3965*t*v0.016
em que
 v = velocidade do vento em m/s
 t = temperatura em graus Celsius: tcomercial. Os detalhes
sobre os parâmetros chamados por valor e por referência serão dados nas próximas subseções.
■ PARÂMETROS CHAMADOS POR VALOR
Os parâmetros chamados por valor são mais do que apenas espaços em branco preen-
chidos com os valores dos argumentos da função. Um parâmetro chamado por valor é, na
realidade, uma variável local. Quando a função é invocada, o valor de um parâmetro cha-
mado por valor é calculado, e o parâmetro chamado por valor correspondente, que é uma
variável local, é inicializado com esse valor.
Na maioria dos casos, pode-se pensar em um parâmetro chamado por valor como um
tipo de espaço em branco, ou “guardador” de lugar, que é preenchido pelo valor do argu-
mento correspondente na invocação da função. Entretanto, em alguns casos é útil empre-
4.1
CAPÍTULO 
gar um parâmetro chamado por valor como uma variável local e alterar o valor de seu parâmetro dentro do corpo
da definição de função. Por exemplo, o programa no Painel 4.1 ilustra um parâmetro chamado por valor utilizado
como uma variável local cujo valor é alterado no corpo da definição de função. Observe o parâmetro formal mi-
nutosTrabalhados na definição da função taxa. Ele é usado como uma variável, e seu valor é alterado pela se-
guinte linha, que aparece dentro da definição de função:
minutosTrabalhados = horasTrabalhadas*60 + minutosTrabalhados;
Painel 4.1 Parâmetro formal utilizado como variável local
1 //Programa de faturamento de um escritório de advocacia.
2 #include 
3 using namespace std;
4 const double RATE = 150.00; //Dólares por 15 minutos de consulta.
5 double fee(int hoursWorked, int minutesWorked);
6 //Retorna o preço da hora hoursWorked e
7 //os minutos minutesWorked de serviços.
8 int main( )
9 {
10 int hours, minutes;
11 double bill;
12 cout > hours >> minutes;
18 bill = fee(hours, );
19 cout.setf(ios::fixed);
20 cout.setf(ios::showpoint);
21 cout.precision(2);
22 cout > receptor;
}
Em um programa que contenha essa definição de função, a seguinte chamada de função fixará a variável dou-
ble numeroEntrada como igual a um valor lido a partir do teclado:
getEntrada(numeroEntrada);
O C++ permite que você coloque o símbolo de “e” comercial junto ao nome do tipo ou junto ao nome do
parâmetro. Assim, às vezes você verá
int minutesWorked;
Não faça isso quando
minutosTrabalhados for
um parâmetro!
1. Descreva cuidadosamente o mecanismo do parâmetro chamado por valor.
2. Supõe-se que a seguinte função exija como argumentos um comprimento expresso em pés e polegadas
e retorne o número total de polegadas. Por exemplo, totalPolegadas(1, 2) deve apresentar como saída
14, porque 1 pé e 2 polegadas é o mesmo que 14 polegadas. A função seguinte atuará corretamente?
Se não, por quê?
double totalPolegadas(int pes, int polegadas)
{
polegadas = 12*pes + polegadas;
return polegadas;
}
Parâmetros 93
1 Exercícios de Autoteste 1 
void getEntrada(double &receptor);
que equivale a
void getEntrada(double& receptor);
Painel 4.2 Parâmetros chamados por referência
1 //Programa para demonstrar parâmetros chamados por referência.
2 #include 
3 using namespace std;
4 void getNumbers( );
5 //Lê dois inteiros a partir do teclado.
6 void swapValues( );
7 //Troca os valores variable1 e variable2.
8 void showResults(int output1, int output2);
9 //Mostra os valores de variable1 e variable2, nessa ordem.
10 int main( )
11 {
12 int firstNum, secondNum;
13 getNumbers(firstNum, secondNum);
14 swapValues(firstNum, secondNum);
15 showResults(firstNum, secondNum);
16 return 0;
17 }
18 void getNumbers( )
19 {
20 cout > input1 
 >> input2;variable1 = variable2; 
variable2 = temp; 
Forneça dois números inteiros: 5 6
Em ordem inversa, os números são: 6 5
94 Parâmetros e Sobrecarga
getNumeros(primeiroNum, segundoNum);
Os valores das variáveis primeiroNum e segundoNum são estabelecidos por essa chamada de função. Depois dis-
so, a função seguinte inverte os valores nas duas variáveis primeiroNum e segundoNum:
swapNumeros(primeiroNum, segundoNum);
As próximas subseções descrevem o mecanismo de chamada por referência em mais detalhes e explicam tam-
bém as funções particulares utilizadas no Painel 4.2.
■ MECANISMO DE CHAMADA POR REFERÊNCIA EM DETALHE
Na maioria das situações o mecanismo de chamada por referência funciona como se o nome da variável dado
como argumento da função substituísse literalmente o parâmetro formal chamado por referência. Entretanto, o
processo é um pouco mais sutil do que isso. Em algumas situações, essa sutileza é importante. Por isso, precisamos
analisar mais detalhadamente esse processo de substituição de chamada por referência.
Variáveis em um programa são implementadas como posições na memória. Cada posição na memória possui
um endereço único, que é um número. O compilador atribui uma posição de memória a cada variável. Por exem-
plo, quando o programa no Painel 4.2 é compilado, pode ser atribuída à variável primeiroNum a posição 1010, e
à variável segundoNum a posição 1012. Para todos os efeitos práticos, essas posições de memória são as variáveis.
Por exemplo, considere a seguinte declaração de função do Painel 4.2:
void getNumeros(int& entrada1, int& entrada2);
Os parâmetros formais chamados por referência entrada1 e entrada2 são “guardadores” de lugar para os ver-
dadeiros argumentos utilizados em uma chamada de função.
Agora considere uma chamada de função como a seguinte, do mesmo programa:
getNumeros(primeiroNum, segundoNum);
Quando a chamada de função é executada, a função não recebe os nomes de argumentos primeiroNum e se-
gundoNum. Em vez disso, recebe uma lista das posições de memória associadas a cada nome. Neste exemplo, a lista
consiste nas posições
1010
1012
que são as posições atribuídas às variáveis de argumento primeiroNum e segundoNum, nesta ordem. E são essas as
posições de memória associadas aos parâmetros formais. A primeira posição de memória ao primeiro parâmetro
formal, a segunda posição de memória ao segundo parâmetro formal, e assim por diante. Em um diagrama, neste
caso a correspondência é
primeiroNum → 1010 → entrada1
segundoNum → 1012 → entrada2
Quando os comandos da função são executados, o que quer que o corpo da função diga para fazer com um
parâmetro formal é, na verdade, feito com a variável na posição de memória associada com aquele parâmetro for-
mal. Nesse caso, as instruções no corpo da função getNumeros dizem que um valor deve ser armazenado no parâ-
metro formal entrada1 utilizando um comando cin, e assim o valor é armazenado na variável na posição de
PARÂMETROS CHAMADOS POR REFERÊNCIA
Para transformar um parâmetro formal em parâmetro chamado por referência, anexe o símbolo de “e” comercial, &, ao seu nome
de tipo. O argumento correspondente em uma chamada à função deve, então, ser uma variável, não uma constante ou outra
expressão. Quando a função é chamada, o argumento da variável correspondente (não seu valor) substituirá o parâmetro formal.
Qualquer alteração no parâmetro formal no corpo da função será feita na variável do argumento quando a função é chamada.
Os detalhes exatos dos mecanismos de substituição serão fornecidos no texto deste capítulo.
EXEMPLO
void getDados(int& primeiraEntrada, double& segundaEntrada);
Parâmetros 95
memória 1010 (que é a variável primeiroNum). De forma similar, as instruções no corpo da função getNumeros di-
zem que outro valor deve, então, ser armazenado no parâmetro formal entrada2 por meio de um comando cin e,
dessa forma, aquele valor é armazenado na variável na posição de memória 1012 (que é a variável segundoNum).
Assim, o que quer que a função instrua o computador a fazer com entrada1 e entrada2 é, na verdade, feito com
as variáveis primeiroNum e segundoNum.
Pode parecer que existam detalhes demais, ou, pelo menos, palavras demais nessa história. Se primeiroNum é a
variável com a posição de memória 1010, por que insistimos em dizer “a variável na posição de memória 1010"
em vez de simplesmente dizer “primeiroNum”? Essa quantidade a mais de detalhes é necessária se os argumentos e
os parâmetros formais contêm alguma coincidência de nomes criadora de confusão. Por exemplo, a função getNu-
meros possui parâmetros formais denominados entrada1 e entrada2. Suponha que você queira mudar o programa
no Painel 4.2 para que ele utilize a função getNumeros com argumentos que também se chamem entrada1 e en-
trada2, e suponha que você queira fazer algo que não seja tão óbvio. Suponha, ainda, que você queira que o pri-
meiro número digitado seja armazenado em uma variável chamada entrada2, e o segundo número digitado na
variável chamada entrada1 — talvez porque o segundo número será processado primeiro ou porque é o número
mais importante. Agora, vamos supor que às variáveis entrada1 e entrada2, que são declaradas na parte main do
seu programa, tenham sido atribuídas as posições de memória 1014 e 1016. A função poderia ser assim:
int entrada1, entrada2;
getNumeros(entrada2, entrada1);
Neste caso, se você disser “entrada1”, não saberemos se você se refere à variável chamada entrada1 declarada
na parte main do seu programa ou ao parâmetro formal entrada1. Entretanto, se à variável entrada1 declarada na
função main do seu programa é atribuída a posição de memória 1014, a frase “a variável de posição de memória
1014” é inequívoca. Vamos analisar os detalhes dos mecanismos de substituição nesse caso.
Nesta chamada o argumento correspondente ao parâmetro formal entrada1 é a variável entrada2, e o argu-
mento correspondente ao parâmetro formal entrada2 é a variável entrada1. Isso pode parecer confuso para nós,
mas não causa problema para o computador, já que este, na verdade, nunca “substitui entrada1 por entrada2” ou
“substitui entrada2 por entrada1”. O computador simplesmente lida com posições de memória. O computador
substitui o parâmetro formal entrada1 pela “variável na posição de memória 1016” e o parâmetro formal entra-
da2 pela “variável na posição de memória 1014”.
 
Observe a ordem dos argumentos.
FUNÇÃO trocaValores
A função trocaValores definida no Painel 4.2 troca os valores armazenados nas duas variáveis. A descrição
da função é dada pela seguinte declaração de função e comentário que a acompanha:
void trocaValores(int& variavel1, int& variavel2);
//Troca os valores da variavel1 e variavel2.
Para ver como se espera que a função trabalhe, presuma que a variável primeiroNum tenha valor 5 e a variá-
vel segundoNum tenha valor 6 e considere a seguinte chamada de função:
trocaValores(primeiroNum, segundoNum);
Depois desta chamada de função, o valor de primeiroNum será 6 e o valor de segundoNum será 5.
Como mostra o Painel 4.2, a definição da função trocaValores utiliza uma variável local chamada temp. A
variável local é necessária. Você pode ser levado a pensar que a definição de função poderia ser simplificada
para
void trocaValores(int& variavel1, int& variavel2);
{
variavel1 = variavel2;
variavel2 = variavel1;
}
Para verificar que esta definição alternativa não funciona, pense no que poderia acontecer com essa defini-
ção e a chamada de função
trocaValores(primeiroNum, segundoNum);
As variáveis primeiroNum e segundoNum substituiriam os parâmetros formais variavel1 e variavel2, de
modo que, com esta definição de função incorreta, a chamada de função seria equivalente a:
primeiroNum = segundoNum;
segundoNum = primeiroNum;
Isto não funciona!
96 Parâmetros e Sobrecarga
---
> 
 
■ PARÂMETROS DE REFERÊNCIA CONSTANTES
Colocamos esta subseção aqui porque um dos objetivos deste livro é servir como referência. Se você estiver lendo o
livro na seqüência, pode pular esta seção.O tópico será explicado com mais detalhes posteriormente.
Se você colocar um const antes de um tipo de parâmetro chamado por referência, obterá um parâmetro cha-
mado por referência que não pode ser alterado. Para os tipos que vimos até agora, isso não apresenta vantagens.
Entretanto, vai se revelar um recurso bastante eficiente com vetores e parâmetros de tipo classe. Discutiremos esses
parâmetros constantes quando falarmos em vetores e classes.
 
 
Este código não produz o resultado desejado. O valor de primeiroNum é fixado como igual ao valor de se-
gundoNum, como deveria ser. Mas, então, o valor de segundoNum é fixado como igual ao valor alterado de
primeiroNum, que agora é o valor original de segundoNum. Assim, o valor de segundoNum não é alterado. (Se
isso não estiver claro para você, atribua valores específicos às variáveis primeiroNum e segundoNum e refaça o
processo.) O que a função precisa fazer é salvar o valor original de primeiroNum, para que o valor não seja
perdido. É para isso que se utiliza a variável local temp na definição de função correta. A definição correta é
aquela apresentada no Painel 4.2. Quando esta versão correta é utilizada e a função é chamada com os ar-
gumentos primeiroNum e segundoNum, a chamada de função é equivalente ao código seguinte, que funciona
corretamente:
temp = primeiroNum;
primeiroNum = segundoNum;
segundoNum = temp;
PENSE EM AÇÕES, NÃO EM CÓDIGO
Embora possamos explicar como uma chamada de função atua em termos de substituir uma chamada de
função pelo código, não é assim que costumamos pensar em uma chamada de função. Em vez disso, você
deve pensar em uma chamada de função como uma ação. Por exemplo, considere a função trocaValores no
Painel 4.2 e uma invocação como
trocaValores(primeiroNum, segundoNum);
É mais fácil e mais claro pensar nessa chamada de função como a ação de trocar os valores desses dois ar-
gumentos. É muito mais obscuro pensar nela como o código
temp = primeiroNum;
primeiroNum = segundoNum;
segundoNum = temp;
3. Qual é a saída do seguinte programa?
#include 
using namespace std;
void descubra(int& x, int y, int& z);
int main( )
{
 int a, b, c;
 a = 10;
 b = 20;
 c = 30;
 descubra(a, b, c);
 cout 
4 using namespace std;
5 void doStuff(int par1Value, int& par2Ref);
6 //par1Valor é um parâmetro chamado por valor formal e
7 //par2Ref é um parâmetro chamado por referência formal.
8 int main( )
9 {
10 int n1, n2;
11
12 
13 
14 doStuff(n1, n2);
15 coutassim, como o diálogo
mostra, o valor de n2 é alterado de 2 para 222 pela chamada de função.
Se você não se esquecer da lição do Painel 4.3, é fácil decidir que mecanismo de parâmetro utilizar. Se você
quer que uma função altere o valor de uma variável, então o parâmetro formal correspondente deve ser um
parâmetro formal chamado por referência e deve ser assinalado com um sinal de “e” comercial, &. Em todos
os outros casos, pode-se usar um parâmetro formal chamado por valor.
n1 = 1;
n2 = 2;
par1Value = 111;
par2Ref = 222;
par1Valor na chamada de função = 111
par2Ref na chamada de função = 222
n1 depois da chamada de função = 1
n2 depois da chamada de função = 222
Parâmetros 99
IDica (continuação) 
 
 
 
Painel 4.4 Descuidos com variáveis locais (parte 1 de 2)
1 //Programa para demonstrar parâmetros chamados por referência.
2 #include 
3 using namespace std;
4 void getNumbers(int& input1, int& input2);
5 //Lê dois inteiros a partir do teclado.
6 void swapValues(int variable1, int variable2);
7 //Troca os valores de variable1 e variable2.
DESCUIDOS COM VARIÁVEIS LOCAIS
Se você quer que uma função altere o valor de uma variável, o parâmetro formal correspondente deve ser
um parâmetro chamado por referência e, portanto, deve ter o “e” comercial, &, anexado ao seu tipo. Se você
omitir o “e” comercial, a função terá um parâmetro chamado por valor em vez de um parâmetro chamado
por referência. Quando o programa for executado, você descobrirá que a chamada de função não altera o
valor do argumento correspondente, porque um parâmetro formal chamado por valor é uma variável local.
Se o parâmetro tiver seu valor alterado na função, então, como com qualquer variável local, essa alteração
não exercerá efeito fora do corpo da função. Este é um erro que pode ser bastante difícil de perceber, por-
que o código parece certo.
Por exemplo, o programa no Painel 4.4 é similar ao programa no Painel 4.2, a não ser pelo fato de o “e”
comercial ter sido erroneamente omitido na função trocaValores. Em conseqüência, os parâmetros formais
variavel1 e variavel2 são variáveis locais. As variáveis de argumento primeiroNum e segundoNum nunca
substituem variavel1 e variavel2; variavel1 e variavel2 são, em vez disso, inicializadas com os valores de
primeiroNum e segundoNum. Então, os valores de variavel1 e variavel2 são trocados, mas os valores de pri-
meiroNum e segundoNum permanecem inalterados. A omissão de dois “ee” comerciais tornou o programa to-
talmente errado e, no entanto, ele parece quase idêntico ao programa correto e compilará e será executado
sem qualquer mensagem de erro.
ESCOLHENDO NOMES DE PARÂMETROS FORMAIS
As funções devem ser módulos independentes projetados separadamente do resto do programa. Em grandes
projetos de programação, programadores diferentes são contratados para escrever funções diferentes. O pro-
gramador deve escolher os nomes mais descritivos que encontrar para os parâmetros formais. Os argumen-
tos que substituirão os parâmetros formais podem ser variáveis em outra função ou na função main. Essas
variáveis também devem receber nomes descritivos, muitas vezes escolhidos por outra pessoa que não o
programador que escreve a definição de função. Isso torna provável que alguns ou todos os argumentos te-
nham os mesmos nomes que alguns dos parâmetros formais. Isso é perfeitamente aceitável. Não importa
que nomes sejam escolhidos para as variáveis que serão utilizadas como argumentos, esses nomes não cau-
sarão qualquer confusão com os nomes empregados para os parâmetros formais.
COMPRANDO PIZZA
Nem sempre sai mais barato comprar o produto de maior tamanho. Isso é especialmente verdade em se tra-
tando de pizzas. Nos Estados Unidos, os tamanhos das pizzas são dados pelo diâmetro da pizza em pole-
gadas. Entretanto, a quantidade de pizza é determinada pela área da pizza, e a área da pizza não é
proporcional ao diâmetro. A maioria das pessoas não consegue estimar com facilidade a diferença de área
entre uma pizza de dez polegadas e uma de doze e, assim, não consegue decidir facilmente que tamanho é
o melhor para se comprar — isto é, que tamanho tem o preço mais baixo por polegada quadrada (1polega-
da quadrada = 6,4516 cm2). O Painel 4.5 mostra um programa que o consumidor pode utilizar para decidir
qual dos dois tamanhos de pizza comprar.
Observe que as funções getDados e forneceResultados possuem os mesmos parâmetros, mas como getDa-
dos alterará os valores de seus argumentos, seus parâmetros são chamados por referência. Por outro lado,
forneceResultados só necessita dos valores de seus argumentos e, assim, seus parâmetros são chamados
por valor.
Note também que forneceResultados possui duas variáveis locais e que seu corpo de função inclui chama-
das para as funções precoUnidade. Finalmente, observe que a função precoUnidade tem tanto as variáveis
locais quanto uma variável local definidas como constantes.
Esqueça o & aqui.
100 Parâmetros e Sobrecarga
IDica 
~-----~ 
8 void showResults(int output1, int output2);
9 //Mostra os valores de variable1 e variable2, nessa ordem.
10 int main( )
11 {
12 int firstNum, secondNum;
13 getNumbers(firstNum, secondNum);
14 swapValues(firstNum, secondNum);
15 showResults(firstNum, secondNum);
16 return 0;
17 }
18 void swapValues(int variable1, int variable2)
19 {
20 int temp;
21 temp = variable1;
22 = variable2;
23 = temp;
24 }
25 As definições de getNumbers e
26 showResults são as mesmas do Painel 4.2.
DIÁLOGO PROGRAMA-USUÁRIO
Painel 4.5 Comprando pizza (parte 1 de 3)
1 //Determina qual dos dois tamanhos de pizza é o melhor para comprar.
2 #include 
3 using namespace std;
4 void getData(int& smallDiameter, double& priceSmall, 
5 int& largeDiameter, double& priceLarge);
6 void giveResults(int smallDiameter, double priceSmall, 
7 int largeDiameter, double priceLarge);
8 double unitPrice(int diameter, double price);
9 //Fornece o preço por polegada quadrada de uma pizza.
10 //Pré-condição: O parâmetro diameter é o diâmetro da pizza 
11 //em polegadas. O parâmetro price é o preço da pizza.
12 int main( )
13 {
14 int diameterSmall, diameterLarge;
15 double priceSmall, priceLarge;
16 getData( ;
17 giveResults( ;
18 return 0;
19 }
20 void getData(int& smallDiameter, double& priceSmall, 
Painel 4.4 Descuidos com variáveis locais (parte 2 de 2)
variable1
variable2
Esqueça o & aqui.
Descuido com variáveis locais.
Forneça dois inteiros: 5 6
Em ordem inversa os números são: 5 6
Erro devido ao descuido
com variáveis locais.
diameterSmall, priceSmall, diameterLarge, priceLarge)
As variáveis diameterSmall, diameterLarge,
priceSmall e priceLarge são utilizadas para
transportar dados da função getData para a
função giveResults.
diameterSmall, priceSmall, diameterLarge, priceLarge)
Parâmetros 101
----
21 int& largeDiameter, double& priceLarge)
22 {
23 cout > smallDiameter;
26 cout > priceSmall;
28 cout > largeDiameter;
30 cout > priceLarge;
32 }
33
34 void giveResults(int smallDiameter, double priceSmall, 
35 int largeDiameter, double priceLarge)
36 {
37 double unitPriceSmall, unitPriceLarge;
38 unitPriceSmall = ;
39 unitPriceLarge = ;
40 cout.setf(ios::fixed);
41 cout.setf(ios::showpoint);
42 cout.precision(2);
43 cout(2); 
62 area = PI * radius * radius;
63 return (price/area);
64 }
DIÁLOGO PROGRAMA-USUÁRIO
Painel 4.5 Comprando pizza (parte 2 de 3)
unitPrice(smallDiameter, priceSmall)
Uma função chamada
dentro de outra função.
unitPrice(largeDiameter, priceLarge)
Bem-vindo à União dos Consumidores de Pizza.
Informe o diâmetro de uma pizza pequena (em polegadas): 10
Informe o preço de uma pizza pequena: $7.50
Informe o diâmetro de uma pizza grande (em polegadas): 13
Informe o preço de uma pizza grande: $14.75
Pizza pequena:
Diâmetro = 10 polegadas
Preço = $7.50 Por polegada quadrada = $0.10
Pizza grande:
102 Parâmetros e Sobrecarga
/ 
 
Sobrecarga e Argumentos-Padrão
— … e isso mostra que há trezentos e sessenta e quatro dias em que você poderia ganhar um presente de não-
aniversário…
— É verdade — reconheceu Alice.
— E apenas um para presentes de aniversário, você sabe. Isto é a glória para você!
— Não sei o que você quer dizer com “glória” — disse Alice.
Humpty Dumpty sorriu com desdém.
— Claro que você não sabe… até eu lhe contar. Quero dizer “este é um argumento arrasador para você!”
— Mas “glória” não quer dizer “um argumento arrasador” — objetou Alice.
— Quando eu uso uma palavra — disse Humpty Dumpty, em tom de desprezo —, ela quer dizer exatamente
o que eu quero que signifique. Nem mais nem menos.
— A questão — observou Alice — é se você pode fazer as palavras significarem tantas coisas diferentes.
— A questão é — disse Humpty Dumpty — quem é que manda. Só isso.
Lewis Carroll, Através do Espelho
O C++ permite que você dê duas ou mais definições diferentes para o mesmo nome de função, o que significa
que você pode reutilizar nomes com forte apelo intuitivo em uma grande variedade de situações. Por exemplo,
você poderia ter três funções chamadas max: uma que calcula o maior de dois números, outra que calcula o maior
de três números e ainda outra que calcula o maior de quatro números. Diz-se que dar duas (ou mais) definições
de função para o mesmo nome de função é sobrecarregar o nome da função.
■ INTRODUÇÃO À SOBRECARGA
Suponha que você escreva um programa que exija que se calcule a média de dois números. Você poderia usar
a seguinte definição de função:
double med(double n1, double n2)
{
return ((n1 + n2)/2.0);
}
Agora suponha que seu programa exija também uma função para calcular a média de três números. Você po-
deria definir uma nova função chamada med3 da seguinte forma:
double med3(double n1, double n2, double n3)
{
return ((n1 + n2 + n3)/3.0);
}
Painel 4.5 Comprando pizza (parte 3 de 3)
7. Qual seria a saída do programa no Painel 4.3 se você alterasse a declaração da função efetueIsso para
a seguinte linha e alterasse o cabeçalho da função para combinar, de modo que o parâmetro formal
par2Ref fosse alterado para um parâmetro chamado por valor?
void efetueIsso(int par1Valor, int par2Valor);
4.2
Diâmetro = 13 polegadas
Preço = $14.75 Por polegada quadrada = $0.11
É melhor comprar a pequena.
Buon Appetito!
Sobrecarga e Argumentos-Padrão 103
1 Exercícios de Autoteste 1 
1 
Isto funcionará, e em muitas linguagens de programação você não tem escolha exceto fazer algo assim. Entretanto,
o C++ permite uma solução mais elegante. Em C++ você pode simplesmente utilizar o mesmo nome de função med
para ambas as funções. Em C++, você faz a seguinte definição de função em lugar da definição de função med3:
double med(double n1, double n2, double n3)
{
return ((n1 + n2 + n3)/3.0);
}
de modo que o nome de função med possua duas definições. Este é um exemplo de sobrecarga. Nesse caso, sobrecarre-
gamos o nome de função med. O Painel 4.6 contém essas duas definições de função para med dentro de um programa-
amostra completo. Não deixe de observar que cada definição de função possui sua própria declaração (protótipo).
O compilador pode dizer que definição de função utilizar verificando o número e o tipo dos argumentos em
uma chamada de função. No programa do Painel 4.6, uma das funções chamadas med possui dois argumentos, e
a outra, três. Quando há dois argumentos em uma chamada de função, aplica-se a primeira definição. Quando há
três, aplica-se a segunda definição.
Sempre que são dadas duas ou mais definições para o mesmo nome de função, as várias definições de função
devem ter diferentes especificações para seus argumentos; ou seja, quaisquer duas definições de função que pos-
suam o mesmo nome de função devem usar números diferentes de parâmetros formais ou possuir um ou mais pa-
râmetros de tipos diferentes (ou ambos). Observe que, quando se sobrecarrega um nome de função, as declarações
para as duas definições diferentes devem diferir em seus parâmetros formais. Não se pode sobrecarregar uma função
dando duas definições que diferem apenas no tipo do valor fornecido. Também não se pode sobrecarregar com base
em qualquer diferença que não seja a da quantidade ou dos tipos de parâmetros. Não se pode sobrecarregar com base
apenas em const ou em uma diferença de parâmetro chamado por valor versus parâmetro chamado por referência.1
Painel 4.6 Sobrecarregando um nome de função (parte 1 de 2)
1 //Ilustra a sobrecarga da função med.
2 #include 
3 using namespace std;
4 double ave(double n1, double n2);
5 //Retorna a média de dois números n1 e n2.
6
7 double ave(double n1, double n2, double n3);
8 //Retorna a média de três números n1, n2 e n3.
9 int main( )
10 {
11 coutoperandos de tipos diferentes. A úni-
ca diferença entre sobrecarregar o / e sobrecarregar nomes de funções está em que os criadores da linguagem C++
já fizeram a sobrecarga de /, enquanto a sobrecarga dos seus nomes de função deve ser programada por você mes-
mo. O Capítulo 8 discute como sobrecarregar operadores como +, -, e assim por diante.
 
Painel 4.6 Sobrecarregando um nome de função (parte 2 de 2)
Três argumentos
Dois argumentos
A média de 2.0, 2.5 e 3.0 é 2.5
A média de 4.5 e 5.5 é 5.0
ASSINATURA
A assinatura de uma função é o nome da função com a seqüência de tipos na lista de parâmetros, não incluindo a palavra-chave
const nem o “e” comercial, &. Quando você sobrecarrega um nome de função, as duas definições do nome de função devem ter as-
sinaturas diferentes, utilizando essa definição de assinatura. (Alguns especialistas incluem const e/ou o “e” comercial como parte da
assinatura, mas queríamos uma definição que funcionasse para explicar a sobrecarga.)
CONVERSÃO AUTOMÁTICA DE TIPO E SOBRECARGA
Suponha que a seguinte definição de função ocorra em seu programa e que você não tenha sobrecarregado
o nome de função mpg (então esta é a única definição de uma função chamada mpg).
double mpg(double milhas, double galoes)
//Retorna milhas por galão.
{
return (milhas/galoes);
}
Se você chamar a função mpg com argumentos de tipo int, então o C++ converterá automaticamente qual-
quer argumento de tipo int em um valor de tipo double. Dessa forma, a linha seguinte apresentará como
saída 22.5 milhas por galão:
cout 
3 using namespace std;
4 double unitPrice(int diameter, double price)
5 //Retorna o preço por polegada quadrada de uma pizza redonda.
6 //O parâmetro formal chamado diameter é o diâmetro da pizza
7 //em polegadas. O parâmetro formal chamado price é o preço da pizza.
8 double unitPrice(int length, int width, double price)
9 //Retorna o preço por polegada quadrada de uma pizza retangular
10 //com dimensões de comprimento e largura em polegadas.
11 //O parâmetro formal price é o preço de pizza.
12 int main( )
13 {
14 int diameter, length, width;
15 double priceRound, unitPriceRound,
16 priceRectangular, unitPriceRectangular;
17 cout > diameter;
21 coutcaractere de sublinhado.
Embora seja legal começar um identificador com um sublinhado, você deveria evitar fazer isso, porque os identificado-
res que começam com um sublinhado são reservados informalmente para identificadores do sistema e bibliotecas-padrão.
C++ é uma linguagem que percebe a diferença entre maiúsculas e minúsculas nos identificadores. Assim, os
três identificadores a seguir são diferentes e poderiam ser usados para nomear três variáveis diferentes.
taxa TAXA Taxa
Entretanto, não é uma boa idéia usar duas variantes desse tipo no mesmo programa, já que isso poderia criar
confusão. Embora não seja exigido pelo C++, as variáveis normalmente são escritas com a primeira letra em mi-
núscula. Os identificadores predefinidos, como main, cin, cout e outros, devem ser escritos apenas com letras mi-
núsculas. A convenção que agora está se tornando universal na programação orientada a objetos é escrever nomes
de variáveis com uma mistura de letras maiúsculas e minúsculas (e dígitos), começando sempre o nome da variável
com letra minúscula e indicando os limites das "palavras" com uma letra maiúscula, como ilustrado nos seguintes
nomes de variáveis:
 velMax, taxaBanco1, taxaBanco2, horaDeChegada
Essa convenção não é tão comum em C++ quanto em algumas outras linguagens orientadas a objetos, mas
está sendo usada mais amplamente e é uma boa convenção a seguir.
Um identificador C++ pode ter qualquer comprimento, embora alguns compiladores ignorem todos os carac-
teres excedentes, caso a quantidade de caracteres seja maior que um número especificado. 
IDENTIFICADORES
Um identificador C++ deve começar com uma letra ou com um caractere de sublinhado, e os caracteres restantes devem ser
apenas letras, dígitos, ou o caractere de sublinhado. Os identificadores C++ fazem diferença entre maiúsculas e minúsculas e
não têm limite de comprimento.
Há uma classe especial de identificadores, chamados de palavras-chave ou palavras reservadas, que possuem um signi-
ficado predefinido em C++ e não podem ser usados como nomes de variáveis ou qualquer outra coisa. Neste livro, as pa-
lavras-chave aparecem destacadas no texto. Uma lista completa das palavras-chave é fornecida no Apêndice 1.
Algumas palavras predefinidas, como cin e cout, não são palavras-chave. Essas palavras predefinidas não fazem
parte do núcleo da linguagem C++, e você não é autorizado a redefini-las. Embora essas palavras predefinidas não
sejam palavras-chave, são definidas em bibliotecas exigidas pela linguagem C++ padrão. Não é preciso dizer que
usar um identificador predefinido para algo diferente do padrão pode criar confusão e perigo; assim, isso deve ser evi-
tado. A prática mais segura e fácil é tratar todos os identificadores predefinidos como se fossem palavras-chave.
■ VARIÁVEIS
Cada variável em um programa em C++ deve ser declarada antes de ser usada. Quando você declara uma va-
riável, está dizendo ao compilador — e, em última análise, ao computador — que tipo de dados serão armazena-
dos na variável. Por exemplo, aqui estão duas definições que podem ocorrer em um programa C++:
int numeroDeFeijoes;
double umPeso, totalPeso;
A primeira define a variável numeroDeFeijoes de forma a conter um valor do tipo int, ou seja, um número
inteiro. O nome int é uma abreviação de "integer" (inteiro). O tipo int é um dos tipos para números inteiros. A
segunda definição declara umPeso e totalPeso como variáveis de tipo double, que é um dos tipos para números
com um ponto decimal (conhecidos como números de ponto flutuante). Como ilustrado aqui, quando há mais
de uma variável em uma definição, as variáveis são separadas por vírgulas. Observe também que cada definição
termina com um ponto-e-vírgula.
Variáveis, Expressões e Declarações de Atribuição 5
Cada variável deve ser declarada antes de ser usada; obedecida essa regra, podem-se declarar variáveis em qualquer
lugar. É óbvio que elas devem sempre ser declaradas em um local que torne o programa mais fácil de ser lido. Normal-
mente, as variáveis são declaradas logo antes de serem usadas ou no início de um bloco (indicado por uma chave de
abertura, { ). Qualquer identificador legal, exceto as palavras reservadas, pode ser usado para um nome de variável.*
O C++ possui tipos básicos para caracteres, números inteiros e números de ponto de flutuação (números com
um ponto decimal). O Painel 1.2 lista os tipos básicos de C++. O tipo comumente usado para intervalos é int. O
tipo char é o tipo para caracteres únicos e pode ser tratado como um tipo inteiro, mas nós não o aconselhamos a
fazer isso. O tipo comumente usado para números de ponto flutuante é double e, assim, você deve usar double
para números de ponto flutuante, a não ser que tenha alguma razão específica para usar um dos outros tipos de
ponto flutuante. O tipo bool (abreviação de booleano) possui os valores true e false. Não é um tipo inteiro, mas,
para se adaptar a códigos antigos, você pode converter bool em qualquer outro dos tipos inteiros e vice-versa.
Além disso, a biblioteca-padrão chamada string fornece o tipo string, que é usado para strings de caracteres. O
programador pode definir tipos para vetores, classes e apontadores, o que será discutido em capítulos posteriores
deste livro.
Painel 1.2 Tipos simples
NOME DO TIPO MEMÓRIA UTILIZADA INTERVALO PRECISÃO
short
(também chamado
short int)
2 bytes –32.767 a 32.767 Não aplicável
int 4 bytes –2.147.483.647 a
2.147.483.647
Não aplicável
long
(também chamado
long int)
4 bytes –2.147.483.647 a
2.147.483.647
Não aplicável
float 4 bytes aproximadamente
10–38 a 1038
7 dígitos
double 8 bytes aproximadamente
10–308 a 10308
15 dígitos
long double 10 bytes aproximadamente
10–4932 a 104932
19 dígitos
char 1 byte Todos os caracteres ASCII (Também
pode ser usado como um tipo integer,
embora não o recomendemos.)
Não aplicável
bool 1 byte true, false Não aplicável
Os valores listados aqui são apenas valores experimentais para lhe dar uma idéia geral de como os tipos diferem. Os valores
para cada um desses registros podem ser diferentes em seu sistema. Precisão refere-se ao número de dígitos significativos,
incluindo dígitos na frente do ponto decimal. Os intervalos para os tipos float, double e long double são os intervalos
para os números positivos. Os números negativos possuem um alcance similar, mas com um sinal negativo diante de cada
número.
DECLARAÇÕES DE VARIÁVEIS
Todas as variáveis devem ser declaradas antes de serem usadas. A sintaxe para declarações de variável é a seguinte:
SINTAXE
Tipo_Nome Variavel_Nome_1, Variavel_Nome_2, . . . ;
EXEMPLO
int count, numeroDeDragoes, numeroDeTrolls;
double distancia;
6 Fundamentos do C++
* O C++ faz uma distinção entre declarar e definir um identificador. Quando um identificador é declarado, o nome é
introduzido. Quando é definido, aloca-se espaço para o item nomeado. Para o tipo de variáveis que discutimos neste
capítulo e para várias outras partes do livro, o que estamos chamando de declaração de variável declara a variável e a
define ao mesmo tempo, ou seja, aloca espaço para a variável. Muitos autores fazem distinção entre definição de variável
e declaração de variável. A diferença entre declarar e definir um identificador é mais importante para outros tipos de
identificadores, o que encontraremos em outros capítulos. (N. do R.T.)
Cada um dos tipos inteiros possui uma versão sem sinal que inclui apenas valores não-negativos. Esses tipos
são unsigned short, unsigned int e unsigned long. Seus intervalos não correspondem exatamente aos intervalos
dos valores positivos dos tipos short, int e long, mas tendem a ser maiores (já que usam o mesmo espaço de ar-
mazenamento que seus tipos correspondentes short, int ou long, mas não precisam se lembrar do sinal). Dificil-
mente você precisará desses tipos, mas pode encontrá-los em especificações para funções predefinidas em algumas
das bibliotecas de C++, como discutiremos no Capítulo 3.
■ DECLARAÇÕES DE ATRIBUIÇÃO
A forma mais direta de se mudar o valor dedo programa que escrevemos para ela no Painel 4.5.
Agora todos querem comprar a pizza proporcionalmente mais barata. Uma pizzaria desonesta costumava
ganhar dinheiro enganando os consumidores, fazendo-os comprar a pizza mais cara, mas nosso programa
pôs um fim nessa prática maléfica. Entretanto, os proprietários quiseram continuar com esse comportamen-
to desprezível e inventaram um novo jeito de enganar os consumidores. Eles agora oferecem tanto pizzas
redondas como retangulares. Eles sabem que o programa que escrevemos não consegue lidar com pizzas re-
tangulares, e esperam poder confundir mais uma vez os consumidores. O Painel 4.7 é outra versão de nos-
so programa que compara uma pizza redonda e uma pizza retangular. Observe que o nome de função
precoUnidade foi sobrecarregado para podermos aplicá-lo tanto a pizzas redondas quanto a retangulares.
;
;
Sobrecarga e Argumentos-Padrão 107
22 cin >> priceRound;
23 cout > length >> width;
26 cout > priceRectangular;
28 unitPriceRectangular = 
29 unitPrice(length, width, priceRectangular);
30 unitPriceRound = unitPrice(diameter, priceRound);
31 cout.setf(ios::fixed);
32 cout.setf(ios::showpoint);
33 cout.precision(2);
34 cout 
3 using namespace std;
4 void showVolume(int length, 
5 //Retorna o volume da caixa. 
6 //Se a altura não for dada, presume-se que ela seja 1.
7 //Se nem a altura nem a largura forem dadas, presume-se que ambas sejam 1.
8 int main( )
9 {
10 showVolume(4, 6, 2);
11 showVolume(4, 6);
12 showVolume(4);
13 return 0;
14 }
15 void showVolume(int length, 
16 {
17 cout= 1
e Altura = 1 é 4
10. Esta pergunta tem a ver com o exemplo de programação intitulado Programa “Comprando Pizza” Re-
visado. Suponha que a pizzaria desonesta que está sempre tentando enganar os consumidores crie uma
pizza quadrada. Será que você pode sobrecarregar a função precoUnidade para que esta possa calcular o
preço por polegada quadrada de uma pizza quadrada, além do preço por polegada quadrada de uma
pizza redonda? Por que sim ou por que não?
4.3
110 Parâmetros e Sobrecarga
1 Exercícios de Autoteste 1 
1 
//Pós-condição: numero fixado como igual ao número máximo
//de moedas de denominação valorDaMoeda centavos que possa ser obtido
//a partir de quantiaRestante centavos. quantiaRestante diminui conforme
//o valor das moedas, ou seja, diminui de numero*valorDaMoeda.
Você pode verificar se essa pré-condição se sustenta para uma invocação de função, como mostra o seguinte exemplo:
assert((0 
Uma vantagem de utilizar assert é que você pode desativar invocações a assert. Você pode utilizar as invo-
cações a assert em seu programa para depurá-lo e, depois, desativá-las para que os usuários não recebam mensa-
gens de erro que talvez não entendam. Isso reduz os gastos de memória do seu programa. Para desativar todas as
asserções #define NDEBUG em seu programa, acrescente #define NDEBUG antes da instrução de include, da se-
guinte forma:
#define NDEBUG
#include 
Assim, se você inserir #define NDEBUG em seu programa depois de este estar totalmente depurado, todas as invoca-
ções a assert em seu programa serão desativadas. Se depois você alterar seu programa e precisar depurá-lo outra vez,
pode ativar as invocações novamente apagando a linha #define NDEBUG (ou transformando-a em comentário).
Nem todas as asserções de comentários podem ser facilmente traduzidas em expressões booleanas em C++. É
mais provável que as pré-condições sejam mais facilmente traduzidas que as pós-condições. Assim, a macro assert
não é uma panacéia para a depuração de suas funções, mas pode ser muito útil.
■ STUBS E DRIVERS 
Cada função deveria ser projetada, codificada e testada como uma unidade separada do resto do programa.
Quando se trata cada função como uma unidade à parte, transforma-se uma tarefa grande em várias menores,
mais facilmente tratáveis. Mas como se testa uma função fora do programa para o qual foi projetada? Uma forma
é escrever um programa especial para fazer os testes. Por exemplo, o Painel 4.9 mostra um programa para testar a
função precoUnidade que foi usada no programa do Painel 4.5. Programas como esses são chamados de progra-
mas driver. Esses programas driver são ferramentas temporárias e podem ser bem pequenos. Não precisam ter ro-
tinas de entrada muito complexas. Não precisam executar todos os cálculos que o programa final executará. Tudo
o que precisam fazer é obter valores razoáveis para os argumentos da função da maneira mais simples possível
— normalmente do usuário — e então executar a função e mostrar o resultado. Um loop, como no pro-
grama mostrado no Painel 4.9, permitirá que se teste novamente a função com diferentes argumentos
sem ter de executar de novo o programa.
Painel 4.9 Programa driver (parte 1 de 2)
1
2 //Programa driver para a função unitPrice.
3 #include 
4 using namespace std;
5 double unitPrice(int diameter, double price);
6 //Retorna o preço por polegada quadrada de uma pizza.
7 //Pré-condição: O parâmetro diameter é o diâmetro da pizza 
8 //em polegadas. O parâmetro price é o preço da pizza.
9 int main( )
Testando e Depurando Funções 111
10 {
11 double diameter, price;
12 char ans;
13 do
14 {
15 cout > diameter >> price;
17 cout > ans;
21 cout (2); 
31 area = PI * radius * radius;
32 return (price/area);
33 }
DIÁLOGO PROGRAMA-USUÁRIO
Se você testar cada função separadamente, descobrirá a maioria dos erros em seu programa. Além disso, descobrirá que
funções contêm os erros. Se você fosse testar apenas o programa inteiro, provavelmente descobriria que existe um erro, mas
talvez não tivesse a menor idéia de onde ele estaria. Pior ainda, poderia pensar que sabe onde está e se enganar.
Uma vez que tenha testado completamente uma função, você pode usá-la no programa driver para alguma ou-
tra função. Cada função deve ser testada em um programa no qual é a única função ainda não testada. Entretan-
to, é bom usar uma função já testada quando se testa alguma outra função. Se um erro for encontrado, você
saberá que o erro está na função ainda não testada.
Às vezes é impossível ou inconveniente testar uma função sem utilizar alguma outra função que não tenha ain-
da sido escrita ou testada. Nesse caso, você pode usar uma versão simplificada da função que falta ou que não foi
testada. Essas funções simplificadas são chamadas de stubs. Os stubs não precisam, necessariamente, efetuar os cál-
culos corretos, e sim fornecer valores suficientes para o teste, e são tão simples que você pode ter confiança em
seu desempenho. Por exemplo, eis aqui um possível stub para a função precoUnidade:
//Um stub. A função final precisa ser escrita.
double precoUnidade(int diametro, double preco)
Painel 4.9 Programa driver (parte 2 de 2)
(Um parâmetro chamado por valor é indicado pela au-
sência do “e” comercial.)
■ Um argumento correspondente a um parâmetro chamado por valor não pode ser alterado por uma chama-
da de função. Um argumento correspondente a um parâmetro chamado por referência pode ser alterado
por uma chamada de função. Se você quiser que uma função altere o valor de uma variável, é necessário
usar um parâmetro chamado por referência.
■ Podem-se dar múltiplas definições ao mesmo nome de função, desde que as diferentes funções com o mes-
mo nome possuam diferentes números de parâmetros ou algumas posições de parâmetro com tipos diferen-
tes, ou ambos. Isso se chama sobrecarga do nome de função.
■ Pode-se especificar um argumento-padrão para um ou mais parâmetros chamados por valor em uma fun-
ção. Argumentos-padrão são sempre as posições de argumento mais à direita.
Resumo do Capítulo 113
REGRA FUNDAMENTAL PARA O TESTE DE FUNÇÕES
Cada função deve ser testada em um programa em que todas as outras funções já foram totalmente testadas e depuradas.
11. Qual é a regra fundamental para o teste de funções? Por que esta é uma boa forma de se testar fun-
ções?
12. O que é um programa driver?
13. O que é um stub?
14. Escreva um stub para a função cuja declaração é dada abaixo. Não escreva um programa inteiro, apenas
o stub que entraria em um programa. (Dica: o stub fica bem curto.)
double chuvaProb(double pressao, double umidade, double temp);
//Pré-condição: pressao é a pressão barométrica em polegadas de mercúrio.
//umidade é a umidade relativa como porcentagem, e
//temp é a temperatura em graus Fahrenheit.
//Retorna a probabilidade de chuva, que é um número entre 0 e 1.
//0 significa nenhuma probabilidade de chuva. 1 significa chuva com 100% de probabilidade.
1 Exercícios de Autoteste 1 
Resumo do Capítulo 
■ A macro assert auxilia a depuração de seus programas, verificando se as asserções se sustentam ou não.
■ Toda função deve ser testada em um programa em que todas as outras funções já foram completamente
testadas e depuradas.
RESPOSTAS DOS EXERCÍCIOS DE AUTOTESTE
1. Um parâmetro chamado por valor é uma variável local. Quando a função é invocada, o valor do argu-
mento chamado por valor é calculado e o correspondente parâmetro chamado por valor (que é uma variá-
vel local) é inicializado com esse valor.
2. A função atuará bem. Essa resposta é completa e suficiente, mas queremos apresentar uma informação adi-
cional: o parâmetro formal polegadas é um parâmetro chamado por valor, e portanto, como foi discuti-
do, é uma variável local. Assim, o valor do argumento não será alterado.
3. 10 20 30
1 2 3
1 20 3
4. Forneça dois inteiros: 5 10
Em ordem inversa os números são: 5 5
5. void zeroAmbos(int& n1, int& n2)
{
n1 = 0;
n2 = 0;
}
6. void somaImposto(double taxaImposto, double& custo)
{
custo = custo + (taxaImposto/100.0)*custo;
}
A divisão por 100 é para converter a porcentagem em uma fração. Por exemplo, 10% é 10/100.0, ou um
décimo do custo.
7. par1Valor na chamada de função = 111
par2Ref na chamada de função = 222
n1 depois da chamada de função = 1
n2 depois da chamada de função = 2
8. Seria usada a definição de função com um parâmetro, porque a chamada de função tem apenas um parâ-
metro.
9. A primeira seria usada porque é uma identidade perfeita, já que há dois parâmetros de tipo double.
10. Isso não pode ser feito (pelo menos não de um jeito aceitável). O jeito natural de se representar uma
pizza quadrada e redonda é o mesmo. Cada uma é naturalmente representada como um número, que,
para a pizza redonda, é o raio e, para a pizza quadrada, é o comprimento de um lado. Em ambos os ca-
sos, a função precoUnidade precisa ter um parâmetro formal de tipo double para o preço e um parâmetro
formal de tipo int para o tamanho (raio ou lado). Assim, as duas declarações de função teriam o mesmo
número de tipos de parâmetros formais. (Especificamente, ambas teriam um parâmetro formal de tipo
double e um parâmetro formal de tipo int.) Logo, o compilador não seria capaz de decidir que definição
usar. Você ainda pode derrotar a estratégia da pizzaria desonesta definindo duas funções, mas elas precisa-
riam ter nomes diferentes.
11. A regra fundamental para testar funções é que cada função deve ser testada em um programa em que to-
das as outras funções já foram totalmente testadas e depuradas. Esta é uma boa forma de se testar uma
função porque, se você seguir essa regra, quando encontrar um erro, saberá qual função o contém.
12. Um programa driver é um programa escrito com o único propósito de testar uma função.
13. Um stub é uma versão simplificada de uma função usada no lugar da função para que outras funções pos-
sam ser testadas.
14. //ISTO É APENAS UM STUB
double chuvaProb(double pressao,
 double umidade, double temp)
{
Diferente
114 Parâmetros e Sobrecarga
return 0.25; //Não é correto,
//mas serve para fazer o teste.
}
PROJETOS DE PROGRAMAÇÃO
1. Escreva um programa que converta da notação de 24 horas para a notação de 12 horas. Por exemplo, o
programa deve converter 14:25 em 2:25 P.M. A entrada é dada em dois inteiros. Deve haver pelo menos
três funções: uma para a entrada, uma para fazer a conversão e uma para a saída. Registre a informação
A.M./P.M. como um valor de tipo char, ’A’ para A.M. e ’P’ para P.M. Assim, a função para efetuar as
conversões terá um parâmetro formal chamado por referência de tipo char para registrar se é A.M. ou
P.M. (A função terá outros parâmetros também.) Inclua um loop que permita que o usuário repita esse
cálculo para novos valores de entrada todas as vezes que desejar, até o usuário dizer que deseja encerrar o
programa.
2. A área de um triângulo arbitrário pode ser calculada por meio da fórmula
area = √s(s − a)(s − b)(s − c)
onde a, b e c são as medidas dos lados e s é o semiperímetro.
s = (a + b + c) /2
Escreva uma função void que utilize cinco parâmetros: três parâmetros chamados por valor que forneçam
a medida dos lados e dois parâmetros chamados por referência que calculem a área e o perímetro (não o
semiperímetro). Torne sua função robusta. Observe que nem todas as combinações de a, b e c produzem
um triângulo. Sua função deve corrigir resultados para dados legais e resultados coerentes para combina-
ções ilegais.
3. Escreva um programa que diga quantas moedas retornar para qualquer quantia de 1 a 99 centavos. Por
exemplo, se a quantia é 86 centavos, a saída deve ser algo parecido com:
86 centavos podem ser fornecidos como
3 de 25 centavo(s), 1 de 10 centavo(s) e 1 de 1 centavo(s)
Utilize denominações para moedas de 25 centavos, 10 centavos e 1 centavo. Não utilize as moedas de 50
centavos nem de 5 centavos.
Seu programa utilizará a seguinte função (entre outras):
void calculaMoedas(int valorDaMoeda, int& numero, int& quantiaRestante);
//Pré-condição: 0em um pé, 100 centímetros
em um metro e 12 polegadas em um pé.
5. Escreva um programa como o do exercício anterior que converta metros e centímetros em pés e polega-
das. Utilize funções para as subtarefas.
6. (Você deve fazer os dois projetos de programação anteriores antes de fazer este.) Escreva um programa
que combine as funções dos dois projetos de programação anteriores. O programa pergunta ao usuário se
deseja converter pés e polegadas em metros e centímetros ou metros e centímetros em pés e polegadas.
Projetos de Programação 115
Então, o programa efetua a conversão desejada. Faça com que o usuário responda digitando o inteiro 1
para um tipo de conversão e 2 para o outro. O programa lê a resposta do usuário e executa o comando
if-else. Cada ramificação do comando if-else será uma chamada de função. As duas funções chamadas
no comando if-else terão definições de função bastante similares às dos programas dos dois projetos de
programação anteriores. Assim, serão definições de função bastante complexas que chamam outras fun-
ções. Inclua um loop que permita ao usuário repetir esse cálculo para novos dados de entrada até o usuá-
rio dizer que deseja encerrar o programa.
7. Escreva um programa que leia o peso em libras (1 libra = 453,59 gramas) e onças (1 onça = 28,34 gra-
mas) e apresente como saída o equivalente em quilogramas e gramas. Use pelo menos três funções: uma
para entrada, uma ou mais para o cálculo e uma para a saída. Inclua um loop que permita ao usuário re-
petir esse cálculo para novos dados de entrada até o usuário dizer que deseja encerrar o programa. Existem
2.2046 libras em um quilograma, 1.000 gramas em um quilograma e 16 onças em uma libra.
8. Escreva um programa como o do exercício anterior que converta quilogramas e gramas em libras e onças.
Utilize funções para as subtarefas.
9. (Você deve fazer os dois projetos de programação anteriores antes de fazer este.) Escreva um programa
que combine as funções dos dois projetos de programação anteriores. O programa pergunta ao usuário se
deseja converter libras e onças em quilogramas e gramas ou quilogramas e gramas em libras e onças. En-
tão o programa efetua a conversão desejada. Faça com que o usuário responda digitando o inteiro 1 para
um tipo de conversão e 2 para o outro. O programa lê a resposta do usuário e executa o comando if-
else. Cada ramificação do comando if-else será uma chamada de função. As duas funções chamadas no
comando if-else terão definições de função bastante similares às dos programas dos dois projetos de pro-
gramação anteriores. Assim, serão definições de função bastante complexas que chamam outras funções.
Inclua um loop que permita ao usuário repetir esse cálculo para novos dados de entrada até o usuário di-
zer que deseja encerrar o programa.
10. (Você deve fazer os Projetos de Programação 6 e 9 antes de fazer este.) Escreva um programa que combi-
ne as funções dos dois Projetos de Programação 6 e 9. O programa pergunta ao usuário se deseja conver-
ter comprimentos ou pesos. Se o usuário escolher comprimentos, o programa pergunta ao usuário se
deseja converter pés (1 pé = 30,5 cm) e polegadas (1 polegada = 2,54 cm) em metros e centímetros ou
metros e centímetros em pés e polegadas. Se o usuário escolher peso, uma pergunta similar é feita a res-
peito de libras, onças, quilogramas e gramas. Assim, o programa efetua a conversão desejada. Faça com
que o usuário responda digitando o inteiro 1 para um tipo de conversão e 2 para o outro. O programa lê
a resposta do usuário e executa o comando if-else. Cada ramificação do comando if-else será uma
chamada de função. As duas funções chamadas no comando if-else terão definições de função bastante
similares às dos programas dos Projetos de Programação 6 e 9. Observe que seu programa terá comandos
if-else inseridos dentro de comandos if-else, mas apenas de maneira indireta. O comando if-else ex-
terior incluirá duas chamadas de função, como suas duas ramificações. Essas duas chamadas de função,
por sua vez, incluirão um comando if-else, mas você não precisa pensar nisso. São apenas chamadas de
função e os detalhes estão na caixa preta que você cria quando define essas funções. Se você tentar criar
uma ramificação de quatro caminhos, provavelmente está na pista errada. Você só precisa pensar em rami-
ficações de dois caminhos (embora o programa inteiro se ramifique, no fim das contas, em quatro casos).
Inclua um loop que permita ao usuário repetir esse cálculo para novos dados de entrada, até o usuário di-
zer que deseja encerrar o programa.
116 Parâmetros e Sobrecarga
Vetores
Vetores
Capítulo 5Vetores
É um erro capital teorizar antes de ter os dados.
Sir Arthur Conan Doyle, Escândalo na Boêmia (Sherlock Holmes)
INTRODUÇÃO
Um vetor é usado para processar uma coleção de dados de mesmo tipo, como uma lista
de temperaturas ou uma lista de nomes. Este capítulo aborda os princípios básicos de de-
finição e utilização de vetores em C++ e apresenta muitas das técnicas básicas para proje-
tar algoritmos e programas que empregam vetores.
Se quiser, pode ler o Capítulo 6 e quase todo o Capítulo 7, que trata de classes, antes
de ler este capítulo. A única seção daqueles capítulos que utiliza conceitos deste é a Seção
7.3, que apresenta os vectors.
Introdução aos Vetores
Suponha que desejemos escrever um programa que leia cinco notas de provas e execu-
te algumas manipulações sobre essas notas. Por exemplo, o programa poderia calcular a
maior nota de prova e depois apresentar como saída a quantidade que faltou para cada
uma das outras provas se igualar à nota mais alta. Esta não é conhecida até que todas as
cinco notas sejam lidas. Dessa forma, todas as cinco notas devem ser armazenadas para
que, depois que a mais alta seja calculada, cada nota possa ser comparada com ela. Para
conservar as cinco notas, precisaremos de algo equivalente a cinco variáveis de tipo int.
Poderíamos usar cinco variáveis individuais de tipo int, mas cinco variáveis são difíceis de
controlar e depois poderemos querer mudar nosso programa para lidar com 100 notas;
com certeza, 100 variáveis é algo impraticável. Um vetor é a solução ideal. Um vetor
comporta-se como uma lista de variáveis com um mecanismo uniforme de nomeação que
pode ser declarado em uma única linha de código simples. Por exemplo, os nomes para as
cinco variáveis individuais que precisamos poderiam ser nota[0], nota[1], nota[2],
nota[3] e nota[4]. A parte que não muda, nesse caso, nota, é o nome do vetor. A parte
que pode mudar é o inteiro entre colchetes, [ ].
■ DECLARANDO E REFERENCIANDO VETORES
Em C++, um vetor que consiste em cinco variáveis de tipo int pode ser declarado da
seguinte forma:
int nota[5];
É como declarar as cinco variáveis seguintes como sendo todas de tipo int:
nota[0], nota[1], nota[2], nota[3], nota[4]
5.1
CAPÍTULO 
É possível se referir de diversas formas a essas variáveis individuais que juntas constituem o vetor. Nós as cha-
maremos de variáveis indexadas, embora muitas vezes também sejam chamadas variáveis subscritas ou elementos
do vetor. O número entre colchetes é chamado índice ou subscrito. Em C++, os índices são numerados a começar
do 0, não do 1 nem de outro número que não seja o 0. O número de variáveis indexadas em um vetor é chamado
de tamanho declarado do vetor, ou às vezes simplesmente de tamanho do vetor. Quando um vetor é declarado, o
tamanho do vetor é dado entre colchetes depois do nome do vetor. As variáveis indexadas são, então, numeradas
(também utilizando colchetes), começando do 0 e terminando com um inteiro que seja um número inferior ao ta-
manho do vetor.
Em nosso exemplo, as variáveis indexadas eram do tipo int, mas um vetor pode ter variáveis indexadas de qualquer
tipo. Por exemplo, para declarar um vetor com variáveis indexadas de tipo double, é só usar o nome de tipo double
em vez de int na declaração do vetor. Todas as variáveis indexadas para um vetor, contudo, são de mesmo tipo. Esse
tipo é chamado de tipo-base de um vetor. Assim, em nossoexemplo do vetor nota, o tipo-base é int.
Podem-se declarar vetores e variáveis regulares juntos. Por exemplo, a linha seguinte declara as duas variáveis
int proximo e max, além do vetor nota:
int proximo, nota[5], max;
Uma variável indexada como nota[3] pode ser usada em qualquer lugar em que uma variável ordinária de
tipo int possa ser usada.
Não confunda as duas formas de se utilizar os colchetes, [ ], com um nome de vetor. Em uma declaração, como
int nota[5];
o número entre colchetes especifica quantas variáveis indexadas o vetor possui. Quando usado em qualquer outro
lugar, o número entre colchetes especifica a que variável indexada se refere. Por exemplo, nota[0] até nota[4] são
variáveis indexadas do vetor declarado acima.
O índice dentro dos colchetes não precisa ser fornecido como uma constante inteira. Pode-se usar qualquer
expressão entre colchetes, desde que essa expressão seja avaliada como um dos inteiros de 0 até o inteiro um nú-
mero inferior ao tamanho do vetor. Por exemplo, o trecho seguinte estabelecerá o valor de nota[3] como igual a
99:
int n = 2;
nota[n + 1] = 99;
Embora possam parecer diferentes, nota[n + 1] e nota[3] são a mesma variável indexada no código acima,
porque n + 1 é calculado como 3.
A identidade de uma variável indexada, como nota[i], é determinada pelo valor de seu índice, que, neste
exemplo, é i. Assim, você pode escrever programas que dizem algo como “faça isso e aquilo com a iésima variável
indexada”, em que o valor de i é calculado pelo programa. Por exemplo, o programa no Painel 5.1 lê notas e as
processa da forma descrita no início deste capítulo.
Painel 5.1 Programa utilizando um vetor (parte 1 de 2)
1 //Lê as cinco notas e mostra como cada
2 //uma difere da nota mais alta.
3 #include 
4 using namespace std;
5 int main( )
6 {
7 int i, , max;
8 cout > score[0];
10 max = score[0];
11 for (i = 1; i > score[i];
score[5]
118 Vetores
14 if (score[i] > max) 
15 max = score[i]; 
16 //max é o maior entre
17 } 
18 cout > numero;
int nota[numero]; //ILEGAL EM MUITOS COMPILADORES!
Alguns compiladores, mas não todos, permitirão que você especifique um tamanho de vetor com uma variá-
vel desta forma. Entretanto, em nome da portabilidade, você não deve fazer isso, mesmo que o seu compi-
lador o permita. (No Capítulo 10, discutiremos um tipo diferente de vetor cujo tamanho pode ser
determinado quando o programa é executado.)
DECLARAÇÃO DE VETOR
SINTAXE
Nome_Tipo Nome_Vetor[Tamanho_Declarado];
EXEMPLOS
int grandeVetor[100];
double a[3];
double b[5];
char serie[10], serieUm;
Uma declaração de vetor da forma mostrada acima definirá Tamanho_Declarado variáveis indexadas, ou seja, as variáveis indexa-
das de Nome_Vetor[0] até Nome_Vetor[Tamanho_Declarado-1]. Cada variável indexada é uma variável de tipo Nome_Tipo.
O vetor a consiste nas variáveis indexadas a[0], a[1] e a[2], todas de tipo double. O vetor b consiste nas variáveis indexadas
b[0], b[1], b[2], b[3] e b[4], todas também de tipo double. Você pode combinar declarações de vetor com declarações de sim-
ples variáveis, como na variável serieUm acima.
120 Vetores
1. Um byte consiste em oito bits, mas o tamanho exato de um byte não é importante para esta discussão.
IDica (continuação) 
Então, o computador adiciona o númerode bytes necessário para abrigar três variáveis de tipo int ao número do
endereço de a[0]. O resultado é o endereço de a[3]. Essa implementação é apresentada em diagrama no Painel
5.2. Muitas das peculiaridades dos vetores em C++ só podem ser entendidas em relação a esses detalhes sobre a
memória. Por exemplo, na próxima seção "Armadilha", utilizaremos esses detalhes para explicar o que acontece
quando seu programa utiliza um índice ilegal.
 
Painel 5.2 Vetor na memória
ÍNDICE DE VETOR FORA DO INTERVALO
O erro mais comum de programação é feito quando se usam vetores tentando referenciar um índice não
existente. Por exemplo, considere a seguinte declaração de vetor:
int a[6];
Quando se usa o vetor a, toda expressão de índices deve ter como resultado um dos inteiros de 0 a 5. Por
exemplo, se seu programa contém a variável indexada a[i], o i deve ser avaliado como um dos seis inteiros
0, 1, 2, 3, 4 ou 5. Se i é avaliado como qualquer outra coisa, é um erro. Quando uma expressão de índice
é avaliada como algum valor além daqueles permitidos pela declaração de vetor, diz-se que o índice está
fora do intervalo ou simplesmente que é ilegal. Na maioria dos sistemas, o resultado de um índice ilegal
é que seu programa simplesmente fará algo errado, às vezes desastrosamente errado, e fará isso sem lhe dar
qualquer aviso.
Por exemplo, suponha que seu sistema seja típico, o vetor a seja declarado como acima e seu programa
contenha a seguinte declaração:
a[i] = 238;
Agora suponha que o valor de i, infelizmente, seja 7. O computador procede como se a[7] fosse uma va-
riável indexada legal. O computador calcula o endereço onde a[7] deveria estar (se existir um a[7]) e colo-
ca o valor 238 nessa posição de memória. Entretanto, não existe a variável indexada a[7] e a memória que
recebe esse 238 provavelmente pertence a alguma outra variável, talvez uma variável chamada outraCoisa.
Assim, o valor de outraCoisa é alterado inadvertidamente. Essa situação é ilustrada no Painel 5.2.
Índices de vetor geralmente saem do intervalo na primeira ou última iteração de um loop que percorre o ve-
tor. Desse modo, é preciso verificar cuidadosamente todos os loops que percorrem vetores para ter certeza
de que iniciem e terminem em índices legais.
Endereço de a [0]
Nesse computador cada
variável indexada utiliza
2 bytes, então a[3]
começa 2 x 3 = 6 bytes
depois do início de a [0]
Não existe a variável
indexada a[6], mas, se
houvesse uma, ficaria aqui.
Não existe a variável
indexada a[7], mas, se
houvesse uma, ficaria aqui.
Introdução aos Vetores 121
int a[6]; 
~:m 
1024 
1025 
1026 
1027 
1028 
1029 
1030 >a[4] 1031 
1032 >a[5] 1033 
1034 > Variável ---- Variável ------
for (int indice = 0; indice a[indice + 1])
 coutINTEIROS COMO ARGUMENTOS DE FUNÇÃO
Uma função pode ter um parâmetro formal para um vetor completo de modo que, quando a função é chama-
da, o argumento conectado a esse parâmetro formal seja um vetor completo. Entretanto, um parâmetro formal de
um vetor completo não é um parâmetro chamado por valor nem por referência, é um novo tipo de parâmetro
formal que se chama parâmetro vetorial. Vamos começar com um exemplo.
A função definida no Painel 5.3 possui um parâmetro vetorial, a, que será substituído por um vetor completo
quando a função for chamada. Possui também um parâmetro comum chamado por valor (tamanho) que se presu-
me ser um valor inteiro igual ao tamanho do vetor. A função preenche seu argumento de vetor (ou seja, preenche
todas as variáveis indexadas do vetor) com valores digitados no teclado; então, a função envia uma mensagem para
a tela com o índice do último índice de vetor usado.
Painel 5.3 Função com um parâmetro vetorial
DECLARAÇÃO DE FUNÇÃO
void preenche(int a[], int tamanho);
//Pré-condição: tamanho é o tamanho declarado do vetor a.
//O usuário digitará os inteiros da variável tamanho.
//Pós-condição: O vetor a é preenchido com inteiros da variável tamanho
//a partir do teclado.
DEFINIÇÃO DE FUNÇÃO
void preenche(int a[], int tamanho);
{
cout > a[i];
cout > nota[i];
 coutusar a mesma função para argumentos vetoriais de diferentes tamanhos, porque o tamanho é um
argumento separado.
■ PARÂMETRO MODIFICADOR const
Quando você usa um argumento vetorial em uma chamada de função, a função pode alterar os valores arma-
zenados no vetor. Isso normalmente é bom. Entretanto, em uma definição de função complicada, você pode que-
rer escrever um código que altere inadvertidamente um ou mais valores armazenados em um vetor, apesar de o
vetor não dever ser alterado. Como precaução, você pode dizer ao compilador que não pretende alterar o argu-
mento do vetor, e o computador verificará que seu código não altere inadvertidamente qualquer dos valores no
vetor. Para dizer ao compilador que um argumento vetorial não deve ser alterado pela sua função, insira o modi-
ficador const antes do parâmetro vetorial para aquela posição de argumento. Um parâmetro vetorial que é modificado
por um const é chamado de parâmetro vetorial constante.
PARÂMETROS FORMAIS E ARGUMENTOS VETORIAIS
Um argumento de uma função pode ser um vetor completo, mas um argumento para um vetor completo não é um argumento
chamado por valor nem um argumento chamado por referência. É um novo tipo de argumento conhecido como argumento veto-
rial. Quando um argumento vetorial é conectado a um parâmetro vetorial, tudo o que é fornecido para a função é o endereço
na memória da primeira variável indexada do argumento vetorial (aquele indexado por 0). O argumento vetorial não diz à fun-
ção o tamanho do vetor. Portanto, quando se tem um parâmetro vetorial de uma função, normalmente é preciso ter outro pa-
râmetro formal de tipo int que forneça o tamanho do vetor (como no exemplo abaixo).
Um argumento vetorial é como um argumento chamado por referência da seguinte forma: se o corpo da função altera o parâ-
metro vetorial, então, quando a função é chamada, essa alteração é, na verdade, feita no argumento vetorial. Assim, uma fun-
ção pode alterar os valores de um argumento vetorial (ou seja, pode mudar os valores de suas variáveis indexadas).
A sintaxe para uma declaração de função com um parâmetro vetorial é a seguinte:
SINTAXE
Tipo_Retornado Nome_Da_Funcao(..., Tipo_Base Nome_Do_Vetor[],...);
EXEMPLO
void somaVetor(double& soma, double a[], int tamanho);
126 Vetores
2. Se você já ouviu falar em ponteiros, isso soará como se fossem ponteiros e, com efeito, um argumento vetorial é
transmitido passando-se um ponteiro para sua primeira variável indexada (a de número 0). Trataremos disso no Capítulo
10. Se você nunca ouviu falar de ponteiros, pode ignorar esta nota.
Por exemplo, a seguinte função apresenta como saída os valores em um vetor, mas não altera os valores no vetor:
void mostreAoMundo(int a[], int tamanhoDea)
//Pré-condição: tamanhoDea é o tamanho declarado do vetor a.
//Todas as variáveis indexadas de a receberam valores.
//Pós-condição: Os valores em a foram escritos na tela.
{
coutalguns parâmetros vetoriais. Esse programa para a
Companhia Clímax de Fabricação de Colheres de Plástico apresenta um gráfico de barras exibindo a produti-
vidade de cada uma de suas quatro fábricas em uma dada semana. As fábricas mantêm cifras de produção
separadas para cada departamento, como o departamento de colheres de chá, departamento de colheres de
sopa, departamento de colheres de coquetel simples, departamento de colheres de coquetel coloridas, e as-
sim por diante. Além disso, cada uma das quatro fábricas possui um número diferente de departamentos.
Como você pode ver pelo diálogo programa-usuário no Painel 5.4, o gráfico utiliza um asterisco para cada
100 unidades de produção. Como a saída é em unidades de 1000, deve ser colocada em escala sendo divi-
dida por 1000. Isso representa um problema, porque o computador precisa exibir um número inteiro de as-
teriscos. Não pode exibir 1,6 asteriscos para 1600 unidades. Por isso, fazemos um arredondamento para o
milhar mais próximo. Assim, 1600 será o mesmo que 2000 e se transformará em dois asteriscos.
O vetor producao contém a produção total para cada uma das quatro fábricas. Em C++, os índices de ve-
tor sempre começam no 0. Mas como as fábricas são numeradas de 1 a 4 e não de 0 a 3, colocamos a pro-
dução total para a fábrica número n na variável indexada producao[n - 1]. A saída total para a fábrica
número 1 estará contida na producao[0], as cifras para a fábrica 2 estarão contidas na producao[1], e assim
por diante.
Como a saída é em milhares de unidades, o programa colocará em escala os valores dos elementos do ve-
tor. Se a saída total da fábrica número 3 é 4040 unidades, o valor de producao[2] será inicialmente fixado
como 4040. Esse valor de 4040 será, então, escalado como 4, de forma que o valor de producao[2] seja al-
terado para 4 e quatro asteriscos sejam apresentados para representar a saída da fábrica número 3. Essa
operação é realizada pela função escala, que toma todo o vetor producao como um argumento e altera os
valores armazenados no vetor.
A função arredonda efetua o arredondamento do seu argumento para o inteiro mais próximo. Por exemplo,
arredonda(2.3) apresenta como resultado 2, e arredonda(2.6) apresenta como resultado 3. A função arre-
donda foi discutida no Capítulo 3, no exemplo de programação intitulado "Uma Função Arredondadora".
128 Vetores
(continuação) 
Painel 5.4 Programa gráfico de produção (parte 1 de 3)
1 //Lê dados e exibe um gráfico de barras mostrando a produtividade de cada fábrica.
2 #include 
3 #include 
4 using namespace std;
5 const int NUMBER_OF_PLANTS = 4;
6 void inputData(
7 //Pré-condição: lastPlantNumber é o tamanho declarado do vetor a.
8 //Pós-condição: Para plantNumber = 1 até lastPlantNumber:
9 //a[plantNumber-1] é igual à produção total da fábrica de número plantNumber.
10 void scale( );
11 //Pré-condição: a[0] até a[size-1] tem todos valor não-negativo.
12 //Pós-condição: a[i] foi alterado para o número de milhares (arredondado para
13 //um inteiro) que estava originalmente em a[i], para todo i, tal que 0 = 0. 
24 //Retorna número arredondado para o inteiro mais próximo.
25 void printAsterisks(int n);
26 //Imprime n asteriscos na tela.
27 int main( )
28 {
29 
30 cout > next;
55 while (next >= 0)
56 {
57 sum = sum + next;
58 cin >> next;
59 }
60 cout (floor(number + 0.5));
71 }
72 void graph(const int asteriskCount[], int lastPlantNumber)
73 {
74 coutfunção chamada foraDeOrdem que tome como parâmetros um vetor de double e um parâ-
metro int chamado tamanho e retorne um valor de tipo int. Essa função testará esse vetor para ver se
está fora de ordem, o que significa que o vetor viola a seguinte condição:
a[0] 
3 using namespace std;
4 const int MAX_NUMBER_SCORES = 10;
5 void fillArray(int a[], int size, int& numberUsed);
6 //Pré-condição: size é o tamanho declarado do vetor a.
7 //Pós-condição: numberUsed é o número de valores armazenado em a.
8 //a[0] até a[numberUsed-1] foi preenchido com
9 //inteiros não-negativos lidos a partir do teclado.
10 double computeAverage(const int a[], 
11 //Pré-condição: a[0] até a[numberUsed-1] tem valores; numberUsed > 0.
12 //Retorna a média dos números a[0] até a[numberUsed-1].
13 void showDifference(const int a[], 
14 //Pré-condição: As primeiras variáveis indexadas numberUsed de a possuem valores.
15 //Pós-condição: Mostra na tela em quanto os primeiros 
16 //numberUsed elementos do vetor a diferem de sua média.
17 int main( )
18 {
19 int score[MAX_NUMBER_SCORES], 
20 cout > next;
33 while ((next >= 0) && (index > next;
38 }
39 numberUsed = index;
40 }
41 double computeAverage(const int a[], int numberUsed)
42 {
43 double total = 0;
44 for (int index = 0; index 0)
47 {
48 return (total/numberUsed);
49 }
50 else
51 {
52 coutuma variável é usar uma declaração de atribuição. Em C++, o sinal
de igual é utilizado como um operador de atribuição. Uma declaração de atribuição sempre consiste em uma va-
riável no lado esquerdo do sinal de igual e uma expressão no lado direito. Uma declaração de atribuição termina
com um ponto-e-vírgula. A expressão no lado direito de um sinal de igual pode ser uma variável, números, opera-
dores e invocações a funções. Uma declaração de atribuição instrui o computador a avaliar a (ou seja, a calcular o
valor da) expressão do lado direito do sinal de igual e fixar o valor da variável do lado esquerdo como igual ao da
expressão. Aqui estão alguns exemplos de declarações de atribuição em C++:
totalPeso = umPeso * numeroDeFeijoes;
temperatura = 98.6;
contagem = contagem + 2;
A primeira declaração de atribuição fixa o valor de totalPeso como igual ao número na variável umPeso multi-
plicado pelo número em numeroDeFeijoes. (A multiplicação é expressa por meio do asterisco, *, em C++.) A se-
gunda declaração de atribuição fixa o valor de temperatura como 98,6. A terceira declaração de atribuição
aumenta o valor da variável contagem em 2.
Em C++, as declarações de atribuição podem ser usadas como expressões. Quando usadas como expressão,
uma declaração de atribuição fornece o valor atribuído à variável. Por exemplo, considere
n = (m = 2);
A subexpressão (m = 2) tanto altera o valor de m para 2 quanto fornece o valor 2. Assim, fixa tanto n quanto
m como igual a 2. Como você verá quando discutirmos em detalhe a precedência de operadores, no Capítulo 2,
podem-se omitir os parênteses; assim, a declaração de atribuição em questão pode ser escrita como
n = m = 2;
Nós o aconselhamos a não utilizar uma declaração de atribuição como uma expressão, mas você deve conhecer
esse comportamento, porque isso o ajudará a entender certos tipos de erro de código. Por exemplo, isso explicará
por que você não receberá uma mensagem de erro quando escrever, erroneamente
n = m = 2;
quando queria escrever
n = m + 2;
(Este é um erro comum, já que os caracteres = e + ficam na mesma tecla.)
DECLARAÇÕES DE ATRIBUIÇÃO
Em uma declaração de atribuição, primeiro a expressão do lado direito do sinal de igual é avaliada e depois a variável do lado
esquerdo do sinal de igual é fixada como igual a esse valor.
SINTAXE
Variavel = Expressao; 
EXEMPLOS
distancia = velocidade * tempo;
contagem = contagem + 2;
Variáveis, Expressões e Declarações de Atribuição 7
LVALUES E RVALUES
Os autores se referem muitas vezes a lvalue e rvalue em livros sobre C++. Um lvalue é qualquer coisa que possa aparecer
do lado esquerdo de um operador de atribuição (=), o que significa qualquer tipo de variável. Um rvalue é qualquer coisa que
possa aparecer do lado direito de um operador de atribuição, o que significa qualquer expressão que calcule um valor.
Armadilha VARIÁVEIS NÃO-INICIALIZADAS
Uma variável não possui valor com significado até que um programa lhe atribua um. Por exemplo, se a
variável numeroMinimo não recebeu um valor nem como lado esquerdo de uma declaração de atribuição nem
de outra forma (como a de receber um valor de entrada através de um comando cin), então a linha seguinte
está errada:
numeroDesejado = numeroMinimo + 10;
Isto porque numeroMinimo não possui um valor com significado e, assim, toda a expressão do lado direito do
sinal de igual não possui valor com significado. Uma variável como numeroMinimo, que não recebeu um valor, é
chamada de não-inicializada. Essa situação é, na verdade, pior do que se numeroMinimo não tivesse nenhum
valor. Uma variável não-inicializada, como numeroMinimo, simplesmente assumirá um valor qualquer. O valor de
uma variável não-inicializada é determinado pelo padrão de zeros e uns deixado em sua porção na memória
pelo último programa que utilizou aquela porção.
Uma forma de evitar uma variável não-inicializada é inicializar as variáveis ao mesmo tempo em que são
declaradas. Isso pode ser feito acrescentando-se um sinal de igual e um valor, desta forma:
int numeroMinimo = 3;
Esta linha tanto declara numeroMinimo como uma variável do tipo int como fixa o valor da variável
numeroMinimo como igual a 3. Você pode usar uma expressão mais complicada envolvendo operações como
adição ou multiplicação quando inicializa uma variável dentro da declaração assim. Os seguintes exemplos
declaram três variáveis e inicializam duas delas:
double velocidade = 0.07, tempo, saldo = 0.00;
O C++ permite uma notação alternativa para inicializar variáveis quando estas são declaradas. Essa notação
alternativa é ilustrada a seguir, como uma declaração equivalente à anterior:
double velocidade(0.07), tempo, saldo(0.00);
INICIALIZANDO VARIÁVEIS EM DECLARAÇÕES
Você pode inicializar uma variável (ou seja, atribuir-lhe um valor) no momento em que a declara.
SINTAXE
Tipo_Nome Variavel_Nome_1 = Expressao_para_Valor_1,
 Variavel_Nome_2 = Expressao_para_Valor_2, ... ;
EXEMPLOS
int contagem = 0, limite = 10, fatorBobo = 2;
double distancia = 999.99;
SINTAXE
Sintaxe alternativa para inicializar em declarações:
Tipo_Nome Variavel_Nome_1 (Expressao_para_Valor_1),
 Variavel_Nome_2 (Expressao_para_Valor_2), ... ;
EXEMPLOS
int contagem(0), limite(10), fatorBobo(2);
double distancia (999.99);
Dica
Nomes de variáveis e outros nomes em um programa devem pelo menos aludir ao significado ou ao uso da
coisa que estão nomeando. É muito mais fácil entender um programa se as variáveis possuem nomes com
significado. Compare
x = y * z;
Com os nomes mais descritivos
8 Fundamentos do C++
-
Dica
distancia = velocidade * tempo;
As duas declarações efetuam a mesma coisa, mas a segunda é muito mais fácil de entender.
■ MAIS DECLARAÇÕES DE ATRIBUIÇÃO
Existe uma notação abreviada que combina o operador de atribuição (=) e o operador aritmético de forma que
uma dada variável possa ter seu valor alterado por meio de adição ou subtração a um dado valor, multiplicação ou
divisão por um dado valor. A forma geral é
VariavelOperador = Expressao
que é equivalente a
Variavel = VariavelOperador (Expressao)
A Expressao pode ser outra variável, uma constante ou uma expressão aritmética mais complicada. A lista se-
guinte fornece exemplos:
EXEMPLO EQUIVALENTE A
contagem += 2; contagem = contagem + 2;
total –= desconto; total = total – desconto;
bônus *= 2; bônus = bônus * 2;
tempo /= fatorPressa; tempo = tempo / fatorPressa;
troco %= 100; troco = troco % 100;
quantia *= cnt1 + cnt2; quantia = quantia * (cnt1 + cnt2);
Exercícios de Autoteste
1. Escreva a declaração para duas variáveis chamadas pés* e polegadas.** Ambas as variáveis são do tipo
int e devem ser inicializadas com o valor zero na declaração. Forneça as alternativas de inicialização.
2. Escreva a declaração para duas variáveis chamadas contagem e distancia. contagem é do tipo int e
inicializada com o valor zero. distancia é do tipo double e inicializada com o valor 1.5. Forneça as
alternativas de inicialização.
3. Escreva um programa que contenha declarações que apresentem como saída os valores de cinco ou seis
variáveis que tenham sido definidas, mas não inicializadas. Compile e execute o programa. Qual é a saída?
Explique.
* **
■ COMPATIBILIDADE DE ATRIBUIÇÃO
Como regra geral, não se pode armazenar um valor de um tipo em uma variável de outro tipo. Por exemplo, a maioria
dos compiladores não aceitará as seguintes linhas:
int intVariavel;
intVariavel = 2.99;
O problema é uma má combinação de tipos. A constante 2.99 é do tipo double, e a variável intVariavel é do
tipo int. Infelizmente, nem todos os compiladores reagirão da mesma forma à declaração de atribuição acima. Al-
guns emitirão uma mensagem de erro, outros, apenas uma mensagem de alerta, e alguns não apresentarão nenhu-
ma forma de erro. Mesmo se o compilador permitir que você use a atribuição acima, ele dará a intVariavel o
valor int 2, não o valor 3. Como você não pode contar com a aceitação do seu compilador à atribuição acima,
não deve atribuir um valor double a uma variávelé buscar um determinado valor em um vetor. Por exemplo, o vetor
pode conter os números de identificação escolar de todos os estudantes de um determinado curso. Para di-
zer se um estudante em particular está matriculado, efetua-se uma busca no vetor para verificar se este
contém o número do estudante. O programa simples no Painel 5.6 preenche um vetor e depois procura
neste os valores especificados pelo usuário. Um programa de aplicação real seria bem mais elaborado, mas
este mostra tudo o que é essencial em um algoritmo de busca seqüencial. A busca seqüencial é o algorit-
mo de busca mais simples que se possa imaginar. O programa procura pelos elementos do vetor em ordem,
do primeiro ao último, para ver se o número procurado é igual a algum dos elementos do vetor.
No Painel 5.6 a função busca é utilizada para efetuar a busca no vetor. Quando se efetua uma busca em
um vetor, muitas vezes se deseja saber mais do que apenas se o valor procurado está ou não no vetor. Se
o valor procurado está no vetor, em geral se quer saber o índice da variável indexada que abriga o valor
procurado, já que o índice pode servir como guia para alguma informação adicional sobre o valor procurado.
Desta forma, projetamos a função busca para retornar um índice dando a localização no vetor do valor pro-
curado, desde que o valor procurado esteja, de fato, no vetor. Se o valor procurado não estiver no vetor,
busca apresenta como saída -1. Vamos estudar a função busca com mais atenção.
A função busca utiliza um loop while para verificar os elementos do vetor um após o outro a fim de verifi-
car se algum deles é igual ao valor procurado. A variável encontrado é utilizada como uma sinalização para
registrar se o elemento procurado foi ou não encontrado. Se o elemento procurado foi encontrado no vetor,
encontrado é true, o que encerra o loop while.
134 Vetores
Painel 5.6 Efetuando uma busca em um vetor (parte 1 de 2)
1 //Efetua uma busca em um vetor parcialmente preenchido de inteiros não-negativos.
2 #include 
3 using namespace std;
4 const int DECLARED_SIZE = 20;
5 void fillArray(int a[], int size, int& numberUsed);
6 //Pré-condição: size é o tamanho declarado do vetor a.
7 //Pós-condição: numberUsed é o número de valores armazenado em a.
8 //a[0] até a[numberUsed-1] foi preenchido com
9 //inteiros não-negativos a partir do teclado.
10 int search(const int a[], int numberUsed, int target);
11 //Pré-condição: numberUsed é > target;
25 result = search(arr, listSize, target);
26 if (result == -1)
27 cout > ans;
34 } while ((ans != ’n’) && (ans != ’N’));
35 cout 
40 int search(const int a[], int numberUsed, int target)
41 {
42 int index = 0; 
43 bool found = false;
44 while ((!found) && (index 
3 using namespace std;
4 void fillArray(int a[], int size, int& numberUsed);
5 //Pré-condição: size é o tamanho declarado do vetor a.
6 //Pós-condição: numberUsed é o número de valores armazenado em a.
7 //a[0] até a[numberUsed - 1] foi preenchido com
8 //inteiros não-negativos lidos a partir do teclado.
9 void sort(int a[], int numberUsed);
10 //Pré-condição: numberUsed éde tipo int.
Variáveis, Expressões e Declarações de Atribuição 9
* Um pé equivale a 30,5 cm no Sistema Internacional de Unidades. (N. do R.T.)
** Uma polegada equivale a 2,54 cm no Sistema Internacional de Unidades. (N. do R.T.) 
(continuação) 
Mesmo se o compilador permitir que você misture tipos em uma declaração de atribuição, na maioria dos ca-
sos isso não é aconselhável, pois torna seu programa menos portátil, além de causar confusões.
Existem alguns casos especiais em que é permitido atribuir um valor de um tipo a uma variável de outro tipo.
É aceitável atribuir um valor de um tipo inteiro, como int, a uma variável de tipo ponto flutuante, como o tipo
double. Por exemplo, o seguinte estilo é ao mesmo tempo legal e aceitável:
double doubleVariavel;
doubleVariavel = 2;
Isto fixará o valor de uma variável chamada doubleVariavel como igual a 2.0.
Embora em geral essa seja uma má idéia, você pode armazenar um valor int, como 65, em uma variável de
tipo char, e armazenar uma letra como ’Z’ em uma variável de tipo int. Para muitas finalidades, a linguagem C
considera os caracteres como pequenos inteiros e, talvez infelizmente, o C++ herdou isso do C. A razão para per-
mitir isso é que as variáveis de tipo char consomem menos memória do que as variáveis de tipo int. Assim, fazer
operações aritméticas com variáveis do tipo char pode economizar um pouco de memória. Entretanto, é mais cor-
reto utilizar o tipo int quando se lida com inteiros e o tipo char quando se lida com caracteres.
A regra geral é que não se pode colocar um valor de um tipo em uma variável de outro tipo — embora possa parecer
que há mais exceções à regra do que casos que obedeçam a ela. Mesmo que o compilador não imponha essa regra com
muito rigor, é uma boa prática segui-la. Colocar dados de um tipo em uma variável de outro tipo pode causar problemas
porque o valor deve ser alterado para um valor do tipo apropriado e esse valor pode não ser aquele esperado.
Valores de tipo bool podem ser atribuídos a variáveis de um tipo inteiro (short, int, long), e inteiros podem ser atri-
buídos a variáveis do tipo bool. Entretanto, ao fazer isso você prejudica seu estilo. Para maior coerência e para conseguir ler
o código de outras pessoas, é bom você saber: quando atribuído a uma variável de tipo bool, qualquer inteiro diferente de
zero será armazenado como o valor true. O zero será armazenado como o valor false. Quando se atribui a um va-
lor bool uma variável inteira, true será armazenado como 1, e false será armazenado como 0.
■ LITERAIS
Literal é um nome para um valor específico. Os literais muitas vezes são chamados de constantes, para se contra-
por às variáveis. Literais ou constantes não mudam de valor; variáveis podem mudar de valor. Constantes inteiras
são escritas do modo como se costuma escrever números. Constantes de tipo int (ou qualquer outro tipo inteiro)
não devem conter um ponto decimal. Constantes de tipo double podem ser escritas em qualquer das duas formas.
A forma simples para constantes double é o jeito normal de escrever frações decimais. Quando escrita desta forma,
uma constante double deve conter um ponto decimal. Nenhuma constante numérica (inteira ou de ponto flutuan-
te) em C++ pode conter uma vírgula.
Uma notação mais complicada para constantes do tipo double é chamada notação científica ou notação de
ponto flutuante e é particularmente útil para escrever números muito extensos e frações reduzidas. Por exemplo,
3.67 x 1017que é o mesmo que
367000000000000000.00
é mais bem expresso em C++ pela constante 3.67e17. O número 5.89 x 10-6, que é o mesmo que 0.00000589, é mais
bem expresso em C++ pela constante 5.89e-6. E é o símbolo para expoente e significa "multiplicado por 10 na po-
tência que se segue". O e pode ser escrito em letra maiúscula ou minúscula.
Pense no número após o e como aquele que lhe diz a direção e o número de dígitos para mover o ponto de-
cimal. Por exemplo, para mudar 3.49e4 para um número sem um e, mova o ponto decimal quatro casas para a
direita para obter 34900.0, que é outra forma de se escrever o mesmo número. Se o número após o e é negativo,
mova o ponto decimal pelo mesmo número indicado de casas para a esquerda, inserindo zeros extras se necessário.
Assim, 3.49e-2 é o mesmo que 0.0349.
O número antes do e pode conter um ponto decimal, embora isso não seja necessário. Entretanto, o expoente
depois do e não deve, de modo algum, conter um ponto decimal.
10 Fundamentos do C++
O QUE É DOUBLE?
Por que o tipo de números com uma parte fracional é chamado de double? Existe um tipo chamado "single" ("único") que
possua a metade do tamanho do double ("duplo")? Não, mas há algo de verdade nisso. Muitas linguagens de programação
utilizavam tradicionalmente dois tipos para números com uma parte fracional. Um tipo ocupava menos espaço e era bastante
impreciso (ou seja, não permitia muitos dígitos significativos). O segundo tipo ocupava o dobro do espaço na memória e,
assim, era bem mais preciso; também permitia números maiores (embora os programadores tendam a se preocupar mais com a
precisão do que com o tamanho). Os tipos de números que utilizavam o dobro do espaço eram chamados de números de
precisão dupla; os que utilizavam menos espaço eram chamados de números de precisão simples. Seguindo essa tradição, o tipo
que corresponde (mais ou menos) a esse tipo de precisão dupla foi denominado double em C++. O tipo que corresponde à
precisão simples em C++ foi denominado float. C++ possui também um terceiro tipo para números com uma parte
fracional, que é chamado de long double.
Constantes do tipo char são expressas colocando-se o caractere entre aspas simples, como ilustrado aqui:
char symbol = ’Z’;
Observe que a aspa da direita é o mesmo símbolo que a da esquerda.
Constantes para strings de caracteres são dadas entre aspas duplas, como ilustrado pela seguinte linha, retirada
do Painel 1.1:
coutsignifica que um compilador pode
fazer qualquer coisa que seu autor achar conveniente. A conseqüência é que o código que usa seqüências de escape
não-definidas não é portátil. Você não deve utilizar seqüências de escape além daquelas fornecidas pelo padrão
C++. Esses caracteres de controle estão listados no Painel 1.3.
■ DANDO NOMES A CONSTANTES
Números em um computador criam dois problemas. O primeiro é que eles não carregam nenhum valor mnemô-
nico. Por exemplo, quando o número 10 é encontrado em um programa, ele não fornece nenhuma pista do seu
significado. Se o programa é um programa bancário, pode ser o número de filiais ou o número de caixas na cen-
tral. Para entender o programa, você precisa conhecer o significado de cada constante. O segundo problema é que,
quando é preciso alterar alguns números em um programa, a alteração tende a produzir erros. Suponha que 10
Variáveis, Expressões e Declarações de Atribuição 11
ocorra doze vezes em um programa bancário — quatro vezes ele representa o número de filiais e oito vezes ele re-
presenta o número de caixas na central. Quando o banco abrir uma nova filial e o programa precisar ser atualiza-
do, há uma boa possibilidade de que alguns dos 10 que deveriam ser alterados para 11 não sejam, ou que alguns
que não deveriam ser alterados sejam. A maneira de evitar esses problemas é dar nome a cada número e utilizar o
nome em vez do número dentro do seu programa. Por exemplo, um programa bancário poderia ter duas constan-
tes com os nomes CONTAGEM_DE_FILIAIS e CONTAGEM_DE_CAIXAS. Ambos os números poderiam ter
o valor 10, mas, quando o banco abrir uma nova filial, tudo o que você precisa fazer para atualizar o programa é
mudar a definição de CONTAGEM_DE_FILIAIS.
Painel 1.3 Algumas seqüências de escape
SEQÜÊNCIA SIGNIFICADO
\n Nova linha
\r Sinal de retorno (Posiciona o cursor no início da linha atual. Provavelmente você não o utilizará muito.)
\t (Horizontal) Tabulação (Avança o cursor até a próxima tabulação.)
\a Alerta (Soa o sinal de alerta, em geral uma campainha.)
\\ Contrabarra (Permite que você coloque uma contrabarra em uma expressão citada.)
\’ Aspas simples (Em geral usada para colocar aspas simples dentro de uma citação de um caractere.)
\” spas duplas (Em geral usada para colocar aspas duplas dentro de uma citação em string.)
As seqüências seguintes não costumam ser usadas, mas nós as incluímos para fornecer um quadro completo.
\v Tabulação vertical
\b Retrocesso
\f Suprimento de folha (comando que faz a impressora retirar a folha atual)
\? Interrogação
Como se dá nome a um número em um programa C++? Uma das formas é inicializar uma variável com o va-
lor daquele número, como no seguinte exemplo:
int CONTAGEM_DE_FILIAIS = 10;
int CONTAGEM_DE_CAIXAS = 10;
Existe, porém, um problema com esse método de nomear constantes-número: você poderia, inadvertidamente,
trocar o valor de uma dessas variáveis. O C++ fornece uma forma de marcar uma variável inicializada de modo
que esta não possa ser alterada. Se o seu programa tentar mudar uma dessas variáveis, um erro será produzido.
Para marcar uma declaração de variável de modo que o valor da variável não possa ser alterado, coloque antes da
declaração a palavra const (que é uma abreviação de constante). Por exemplo,
const int CONTAGEM_DE_FILIAIS = 10;
const int CONTAGEM_DE_CAIXAS = 10;
Se as variáveis são do mesmo tipo, é possível combinar as linhas acima em uma declaração, como se segue:
const int CONTAGEM_DE_FILIAIS = 10, CONTAGEM_DE_CAIXAS = 10;
Entretanto, a maioria dos programadores pensa que colocar cada definição de nome em uma linha separada
torna o programa mais claro. A palavra const geralmente é chamada de modificador, porque modifica (restringe)
as variáveis declaradas.
Uma variável declarada utilizando o modificador const é, em geral, chamada de constante declarada. Escrever
constantes declaradas com todas as letras em maiúscula não é uma exigência da linguagem C++, mas é uma práti-
ca comum entre os programadores de C++.
Uma vez que um número tenha sido nomeado dessa forma, o nome pode então ser usado em qualquer lugar em
que o número seja permitido, e terá exatamente o mesmo significado que o número que nomeia. Para alterar uma
constante nomeada, você precisa apenas mudar o valor de inicialização na declaração da variável const. O significado
de todas as ocorrências de CONTAGEM_DE_FILIAIS, por exemplo, pode ser mudado de 10 para 11 simplesmente
alterando-se o valor de inicialização 10 na declaração de CONTAGEM_DE_FILIAIS.
O Painel 1.4 contém um programa simples que ilustra o uso do modificador de declaração const.
12 Fundamentos do C++
■ OPERADORES ARITMÉTICOS E EXPRESSÕES 
Como a maioria das outras linguagens, o C++ permite que você forme expressões utilizando variáveis, constantes e
os operadores aritméticos: + (adição), – (subtração), * (multiplicação), / (divisão) e % (módulo, resto). Essas ex-
pressões podem ser usadas em qualquer lugar em que seja legal utilizar um valor do tipo produzido pela expressão.
Todos os operadores aritméticos podem ser usados com números de tipo int, números de tipo double e até
mesmo com um número de cada tipo. Entretanto, o tipo do valor produzido e o valor exato do resultado depen-
dem dos tipos de números que estão sendo combinados. Se ambos os operandos (ou seja, ambos os números) são
de tipo int, então o resultado de combiná-los com um operador aritmético é do tipo int. Se um ou ambos os
operandos for do tipo double, então o resultado é do tipo double. Por exemplo, se as variáveis quantiaBase e ju-
ros são do tipo int, o número produzido pela expressão seguinte é do tipo int:
quantiaBase + juros
Painel 1.4 Constante nomeada
1 #include 
2 using namespace std;
3
4 int main( )
5 {
6 
7 double deposito;
8 cout > deposito;
10 double novoBalanco;
11 novoBalanco = deposito + deposito* ( /100);
12 coutuma variável dentro de uma declaração, pode-se marcar a variável de modo que o programa não tenha a
permissão de alterar o seu valor. Para fazer isso, coloque a palavra const na frente da declaração, como descrito abaixo:
SINTAXE
const Tipo_Nome Variavel_Nome = Constante;
EXEMPLOS
const int MAX = 3;
const double PI = 3.14159;
■ DIVISÃO DE INTEIROS E DE PONTO FLUTUANTE
Quando usado com um ou ambos os operadores do tipo double, o operador de divisão, /, comporta-se como es-
perado. Entretanto, quando usado com dois operadores do tipo int, o operador de divisão fornece a parte inteira
resultante da divisão. Em outras palavras, a divisão inteira descarta a parte depois do ponto decimal. Assim, 10/3
é 3 (não 3.3333...), 5/2 é 2 (não 2.5) e 11/3 é 3 (não 3.6666...). Observe que o número não é arredondado; a parte
depois do ponto decimal é descartada, não importa quão grande seja.
O operador % pode ser usado com operadores de tipo int para recuperar a informação perdida quando se usa
/ para fazer a divisão com números do tipo int. Usado com valores do tipo int, os dois operadores / e % forne-
cem os dois números produzidos quando se efetua o algoritmo longo da divisão, que você aprendeu na escola. Por
exemplo, 17 dividido por 5 dá 3 com resto 2. O operador / fornece o número de vezes que um número "cabe"
dentro de outro. O operador % fornece o resto. Por exemplo, os comandos
cout (m);
Variáveis, Expressões e Declarações de Atribuição 15
- (continuação) 
A expressão
static_cast(m)
é um conversor de tipos. A expressão static_cast é como uma função que toma um argumento int (na
realidade, um argumento de praticamente qualquer tipo) e fornece um valor "equivalente" do tipo double. Assim,
se o valor de m é 2, a expressão static_cast(m) fornece o valor double 2.0.
Observe que static_cast(n) não altera o valor da variável n. Se n possuía o valor 2 antes de a expres-
são ser calculada, então n ainda possuirá o valor 2 depois de a expressão ser calculada. (Se você sabe o que é uma
função em matemática ou em alguma linguagem de programação, pode pensar em static_cast como
uma função que fornece um valor "equivalente" de tipo double.)
Você pode usar qualquer nome de tipo em lugar de double para obter um conversor de um tipo para o outro.
Dissemos que isso produz um valor "equivalente" do tipo-alvo. A palavra equivalente está entre aspas porque não
existe uma noção clara de equivalente aplicável entre dois tipos quaisquer. No caso de um conversor de tipo de
inteiro para ponto flutuante, o efeito é acrescentar um ponto decimal e um zero. O conversor de tipo na outra di-
reção, de ponto flutuante a inteiro, simplesmente apaga o ponto decimal e todos os dígitos depois dele. Observe
que quando a conversão de tipos é de tipo ponto flutuante para inteiro, o número é truncado, não arredondado.
static_cast(2.9)é 2, e não 3.
Esse static_cast é o tipo mais comum de conversor de tipos e o único que usaremos por algum tempo. Para você
ter uma idéia geral e como fonte de referência, listamos todas as quatro formas de conversores de tipo. Algumas podem
não fazer sentido até que você chegue aos tópicos relevantes. Se alguma ou todas as outras três formas não fizerem sen-
tido para você a esta altura, não se preocupe. As quatro formas de conversores de tipos são as seguintes:
static_cast(Expressao)
const_cast(Expressao)
dynamic_cast(Expressao)
reinterpret_cast(Expressao)
Já falamos sobre static_cast. É um conversor de finalidade geral que se aplica às situações mais "comuns". O
const_cast é usado para se desfazer de constantes. O dynamic_cast é usado para descer de um tipo a um tipo in-
ferior em uma hierarquia de herança. O reinterpret_cast é um conversor que depende da implementação, que
não discutiremos neste livro e de que dificilmente você necessitará. (Essas descrições podem não fazer sentido para
você até que se estudem os tópicos apropriados, nos quais a discussão será mais aprofundada. Por enquanto, usa-
remos apenas static_cast.)
A forma antiga de conversores de tipo é aproximadamente equivalente ao tipo static_cast, mas utiliza uma
notação diferente. Uma das duas notações utiliza um nome de tipo como se fosse um nome de função. Por exem-
plo, int(9.3) fornece o valor int 9; double(42) fornece o valor 42.0. Na segunda notação, equivalente, para a for-
ma antiga de conversor de tipo, escreveríamos (double)42 em vez de double(42). Qualquer das notações pode ser
usada com variáveis e expressões mais complicadas e não só com constantes.
Embora o C++ conserve esta forma antiga de conversor de tipo, nós o aconselhamos a utilizar as formas mais novas.
(Algum dia, a forma antiga desaparecerá, ainda que não haja, por enquanto, nenhum plano para sua eliminação.)
Como observamos antes, você sempre pode atribuir um valor de tipo inteiro para uma variável de tipo ponto
flutuante, como em
double d = 5;
Nesses casos, o C++ efetua uma conversão automática de tipos, convertendo 5 em 5.0 e colocando 5.0 na variável
d. Você não pode armazenar o 5 como o valor de d sem uma conversão de tipos, mas às vezes o C++ faz a conversão
de tipos para você. Uma conversão automática como essa geralmente é chamada de coerção de tipo.
■ OPERADORES DE INCREMENTO E DECREMENTO
O ++ no nome da linguagem C++ vem do operador de incremento, ++. O operador de incremento acrescenta 1
ao valor de uma variável. O operador de decremento subtrai 1 do valor de uma variável. Normalmente eles são
usados com variáveis de tipo int, mas podem ser usados com qualquer tipo numérico. Se n é uma variável de um
tipo numérico, então n++ aumenta o valor de n em 1 e n-- diminui o valor de n em 1. Assim, n++ e n-- (quando
seguidos por um ponto-e-vírgula) são comandos executáveis. Por exemplo, as linhas
16 Fundamentos do C++
int n = 1, m = 7;
n++;
cout 2)
Suponha que n possua o valor 2 antes de a expressão ser executada. Nesse caso, você sabe que a
subexpressão (n

Mais conteúdos dessa disciplina