Você está na página 1de 93

Programar em C++

Contedo

1 Objetivo 1

2 Por que C++? 2

3 Diferenas entre C e C++ 3

4 Introduo 4
4.1 Pensando no cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
4.2 Dois modos de programar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
4.3 Um pouco sobre orientao a objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
4.3.1 Paradigmas da Programao: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
4.4 Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

5 Al, Mundo! 7
5.1 Ol mundo! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
5.2 Entrada de dados e comentrios no cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
5.2.1 Comentrios no programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
5.2.2 Incluindo cabealhos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
5.2.3 Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
5.2.4 Funo main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
5.2.5 Entrada e sada (cin/cout) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
5.2.6 funo system(pause) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
5.2.7 Retornando valor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

6 Variveis e constantes 11
6.1 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
6.1.1 Simblicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
6.1.2 Literais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
6.1.3 Enumeraes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
6.2 Variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
6.2.1 Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
6.2.2 Modicadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
6.2.3 Nomeando tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

7 Ponteiros 15

i
ii CONTEDO

8 Ponteiros 16
8.1 O operador * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
8.2 O operador & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
8.3 O ponteiro this . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

9 Vetores 18

10 Vetores e Matrizes 19
10.1 Vetores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
10.2 Matrizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
10.3 Declarando arranjo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
10.4 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
10.5 Declarar constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
10.6 Iniciao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
10.7 Caracter array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
10.8 Arrays de vrias dimenses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
10.9 Iniciando . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
10.10Const Constant arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
10.11Atribuir valores ao array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
10.12Arrays como statements de funes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
10.13Arrays como argumentos de funes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

11 Estruturas 23
11.1 Breve reviso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
11.1.1 Conceito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
11.1.2 Implementao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
11.1.3 Acessando dados internos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
11.2 Estruturas em C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
11.3 Construtores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

12 Operadores 26
12.1 Compatibilidade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
12.2 Como C++ interpreta os operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
12.2.1 Entendendo o operador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
12.2.2 Os argumentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
12.3 Operadores aritmticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
12.3.1 Tipo de retorno . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
12.3.2 Diviso inteira e diviso real . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

13 Deciso e controle de uxo 28

14 Controle de uxo em C++ 29


14.1 Deciso em C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
14.1.1 if-else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
CONTEDO iii

14.1.2 switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
14.1.3 Operador condicional "?" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
14.2 O Comando goto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
14.3 Terminando o programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

15 Estruturas de repetio 32
15.1 While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
15.1.1 Sintaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
15.2 Do-While . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
15.2.1 Sintaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
15.3 For . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
15.3.1 Sintaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
15.4 Dicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
15.4.1 Bloco de Comandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
15.4.2 O Comando break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
15.4.3 O Comando continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
15.4.4 Incrementar/decrementar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
15.5 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

16 Funes 35
16.1 Sobrecarga de funes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
16.2 Parmetros default (padro) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

17 Referncias de dados 37
17.1 Variveis de referncia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
17.2 Passagem de parmetros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
17.3 Exemplo: alterando o valor da varivel usando referncia . . . . . . . . . . . . . . . . . . . . . . 38
17.4 Exemplo: Swap . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
17.5 Comparao entre passagem por referncia e ponteiros . . . . . . . . . . . . . . . . . . . . . . . 38

18 Entrada e sada de dados 39


18.1 Entrada e sada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
18.1.1 Buer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
18.2 cout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
18.2.1 Escape Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
18.3 cin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
18.3.1 Lendo um caractere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
18.3.2 A funo cin.get() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
18.3.3 cin.ignore() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
18.3.4 cin, cin.get(), cin.getline() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
18.4 Entrada de valores para variveis mltiplas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

19 Entrada e sada de dados 2 44


iv CONTEDO

19.1 Entrada/Sada em cheiros (arquivos) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44


19.2 Gravar (Salvar) os dados para um cheiro(arquivo) . . . . . . . . . . . . . . . . . . . . . . . . . . 44
19.3 O que um cheiro(arquivo)? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
19.4 Ficheiros(Arquivos) binrios e tipo texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
19.5 biblioteca padro fstream . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
19.6 Abrir um cheiro(arquivo) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
19.7 Usando o Construtor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
19.8 Usando a funo membro open . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
19.9 Comparando os dois mtodos (pela funo membro e pelo construtor) . . . . . . . . . . . . . . . . 45
19.10Abrir um arquivo para leitura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
19.11Vericar se o cheiro (arquivo) foi aberto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
19.12Fechar um cheiro (arquivo) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
19.13Looping pelo cheiro (arquivo). . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
19.14Manipuladores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
19.14.1 Ajustando a largura da entrada/sada . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
19.14.2 Preenchimento de espaos em branco . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
19.14.3 Ajustando a preciso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
19.15Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

20 Manipulando strings 49
20.1 Char strings e Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
20.2 Funes de caracteres teis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
20.3 Strings em C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
20.3.1 Exemplos de como manipular strings em C++ . . . . . . . . . . . . . . . . . . . . . . . . 50
20.4 Comparando formas de operar strings em C e C++ . . . . . . . . . . . . . . . . . . . . . . . . . 50
20.4.1 Funes uteis para o uso de strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
20.4.2 Copiando strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
20.4.3 Unir strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
20.4.4 comparar frases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
20.4.5 Convertendo C-string e nmero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

21 Classes 53
21.1 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
21.1.1 Origem (atributos) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
21.1.2 Funes membro (Mtodos) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
21.1.3 Conceituao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
21.2 Declarando classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
21.3 Instanciando objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
21.4 Denio de classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
21.5 Especicadores de acesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
21.6 Construtores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
21.6.1 Conceito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
CONTEDO v

21.6.2 Declarao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
21.7 Destrutores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
21.7.1 Conceito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
21.7.2 Declarao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
21.8 copy constructors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
21.9 Ver tambm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

22 Encapsulamento 59
22.1 Conceito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
22.2 Atributos de restrio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
22.2.1 Classes derivadas (pequena introduo) . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
22.2.2 Denindo acessos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
22.3 Escopos globais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

23 Herana 61
23.1 Conceito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
23.2 Sintaxe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
23.3 Controle de acesso classe base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
23.4 Heranas mltiplas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
23.5 Construtores e destrutores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
23.6 Passando parmetros para construtores da classe base . . . . . . . . . . . . . . . . . . . . . . . . 64
23.7 Superposio de funes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
23.8 Acessando funes superpostas da classe base . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
23.9 Ver tambm . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

24 Polimorsmo 66
24.1 Conceito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
24.2 Funes virtuais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
24.3 Chamando mltiplas funes virtuais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
24.4 Funes virtuais e passagem por valor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
24.5 Construtor de cpia virtual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
24.6 Classe base virtual . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

25 Friend 68
25.1 Friend functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
25.2 O que . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
25.3 Declarar funes friend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
25.4 Friend classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68

26 Classes internas 70
26.1 Conceituao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

27 Sobrecarga de operadores 71
27.1 Modicando operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
vi CONTEDO

27.2 Denindo novas operaes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

28 Alocao dinmica de memria 72


28.1 Alocao dinmica de memria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
28.2 Operador new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
28.3 Operador Delete - Memory Leak . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
28.4 Retornando um ponteiro para uma varivel local . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
28.5 Retornando um Ponteiro a uma Varivel Local Esttica . . . . . . . . . . . . . . . . . . . . . . . 73
28.6 Retornando um Ponteiro a uma Varivel Criada Dinamicamente . . . . . . . . . . . . . . . . . . . 73
28.7 Alocar dinamicamente Arrays (Vetores) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
28.8 Dangling Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
28.9 Vericar a existncia de memria para dinmica . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

29 Excees 75
29.1 Standard Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

30 Namespace 76

31 Templates 77
31.1 Funes genricas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
31.2 Sobrecarregando explicitamente uma funo genrica . . . . . . . . . . . . . . . . . . . . . . . . 77

32 Containers 78

33 Compilao 79
33.1 A traduo do cdigo para o computador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
33.2 Pr-processador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
33.3 Compilador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
33.4 Linker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
33.5 Processo de compilao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

34 Lista de Palavras Reservadas do C++ 81

35 Lista de Sequncias de Escape 82

36 Tabela ASCII 83
36.1 Programa 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
36.2 Programa 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

37 C++11 84
37.1 Fontes dos textos e imagens, contribuidores e licenas . . . . . . . . . . . . . . . . . . . . . . . . 85
37.1.1 Texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
37.1.2 Imagens . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
37.1.3 Licena . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Captulo 1

Objetivo

O livro Programar em C++ tem por objetivo apresen-


tar os fundamentos desta linguagem, de modo que o estu-
dante possa desenvolver diferentes tipos de softwares em
alto e baixo nvel para os diversos ambientes existentes,
desde aplicaes para GNU/Linux ou Windows at pro-
gramas para microcontroladores, alm de fornecer a base
para os estudos avanados de C++.
Por ser um livro especco sobre a linguagem C++, al-
tamente recomendvel que o leitor tenha conhecimentos
prvios sobre a linguagem C.
Espera-se que este livro aborde:

Aspectos tericos
Aspectos prticos

Os erros comuns

Para tanto cada tpico dever ter uma explicao terica,


citar os erros mais comuns e exerccios.

1
Captulo 2

Por que C++?

Imagine que voc deve fazer um programa para fazer a Compiladores;


mquina de um pequeno relgio de pulso funcionar, ento
voc pensa: Editores;
Ferramentas de programao;
Bom, isso pode ser feito com Assembly...
Jogos;
Porm, pensando melhor, voc decide mudar de lin-
guagem quando voc pondera. Programas de redes.

O problema maior que se eu tiver que mudar o pro-


At ao momento foram realizadas 3 grandes revises
cessador do relgio, vou ter que refazer o programa.
linguagem:
melhor usar linguagem C.
Depois voc termina por avaliar outra possibilidade: 1 em 1985;
Bem, se eu j estou pensando em C melhor usar 2 em 1990;
C++", depois vai ser mais fcil de entender o c-
digo, reaproveitar em outras coisas e ainda vai ser 3 em 1998 a que deu origem ao ANSI \ ISO stan-
mais fcil de expandir para outros modelos de rel- dard a que cou comummente denominada de Stan-
gio. dard C++. Esta verso suportada por todos os
compiladores C++ famosos incluindo Microsofts
E assim o que podemos perceber como C++ poderosa, Visual C++, Borlands C++ Builder e GCC. Esta foi
exvel e abrangente. Ela pode ser usada para programar revista em 2003.
qualquer tipo de hardware, desde os mais simples at os
mais complexos. Alm disso, C++ uma linguagem que C++ considerada uma linguagem que est entre
gera programas em cdigo de mquina, que funcionam linguagem de alto nvel (em ingls, high level language)
com ou sem a participao de sistemas operacionais no e linguagem de baixo nvel (em ingls, low level lan-
dispositivo. guage). Dito de outra forma, uma linguagem que est
prxima da linguagem humana (linguagem de alto nvel),
Alguns prossionais armam que C++ a linguagem
mas ao mesmo tempo permite estar prximo da maneira
mais poderosa que existe, veja algumas caractersticas
como o computador processa, prximo do Assembly
dela:
(uma linguagem de baixo nvel).

um superconjunto da linguagem C, e contm v-


rios melhoramentos;
Deu origem a grandes linguagens como Java e D;
a porta para a programao orientada a objetos;
C++ pode virtualmente ser efetivamente aplicado a
qualquer tarefa de programao;
H vrios compiladores para diversas plataformas
tornando a linguagem uma opo para programas
multiplataforma.

A linguagem C++ utilizada em projetos como:

2
Captulo 3

Diferenas entre C e C++

Quem sabe programar em C++, capaz de programar C, deixar claro que os dois modos so diferentes. Usar es-
devido semelhana entre as linguagens e o fato do C++ tes dois modos de programar ao mesmo tempo uma das
ser uma extenso do C. Contudo o C no completa- facilidades que o C++ permite, enquanto que outras lin-
mente um subconjunto do C++. Grande parte de cdigo guagens orientadas a objetos como Java, Eifel, etc, no
C pode ser perfeitamente compilado em C++, mas exis- permitem.
tem algumas pequenas diferenas sintticas e semnticas
entre as linguagens que tornam alguns trechos de cdigo
C vlidos em cdigo C++ invlido, ou cdigos que exi-
bem comportamentos diferentes em cada linguagem.
Algumas diferenas bsicas:

O C permite a converso implcita entre o tipo de


dado void* para ponteiros para outros tipos, algo
que o C++ no permite.

O C permite que constantes de caracteres sejam in-


seridas em chamadas de funes com parmetros
tipo char*, em C++ preciso declarar o parme-
tro como const char *;

Alm destas pequenas diferenas, C++ tem um conjunto


de caractersticas que a torna fundamentalmente diferente
de C. Esse conjunto, torna possvel programar em C++
de um modo totalmente diferente do modo de programar
da linguagem C. O que traz a diferena o modo da
orientao na montagem do cdigo.
Chamamos o modo de programar em C de orientado
a procedimentos e chamamos o modo do C++" de ori-
entado a objetos. Muitas pessoas confundem as coisas
quando comeam a programar usando um compilador
C++, pois esta linguagem permite programar nos dois
modos. Essa uma das caractersticas que a torna mais
exvel.
Apesar de C++ permitir programar em modo orientado
a procedimentos, podemos dizer que nestes casos esta-
mos programando em C, usando um compilador C++.
Quando usamos C++ programamos em modo orientado
a objetos. Devido a estas caractersticas, o C++ permite
programar em modo misto, ou seja, escrevendo partes do
cdigo orientadas a procedimentos e outras orientadas a
objetos.
As diferenas entre os dois modos de programar sero es-
clarecidas nos captulos subsequentes. Por hora nos basta

3
Captulo 4

Introduo

4.1 Pensando no cdigo em dois modos: um orientado a procedimentos e outro


orientado a objetos. Os dois podem ser confundidos por
Considerando o conjunto de operaes e eventos que quem no tem muita experincia, mas o uso de um ou do
nosso programa deve executar temos diversas maneiras outro implica em caractersticas prprias para cada caso.
de criar o cdigo, porm o mais difcil criar um cdigo Logo, preciso entender bem os conceitos antes de de-
eciente, rpido e compacto. Na verdade, diversos fato- nir se um cdigo procedural ou orientado a objetos.
res podem interferir nestes aspectos da programao, en- O modelo sequenciado procedural bem simples de im-
tre eles, a escolha do compilador, o mtodo de estruturar plementar, porm, aumenta a complexidade para tare-
o cdigo, a orientao do mesmo, etc... Em termos ge- fas mais bem trabalhadas e sosticadas. Isto ocorre de-
rais, um cdigo torna-se mais prximo do ideal a medida vido a estrutura do modelo, que exige rotinas cada vez
que suas partes tornam-se mais simples de se analisar e mais extensas. No raramente possvel encontrar roti-
quando todos os processos esto bem denidos e espe- nas que, em alguns casos, tornam-se comparveis a pro-
cializados. Quando temos um cdigo que contm muito gramas completos, usando como referncia o nmero de
mais excees do que regras, este precisa de uma rees- linhas de instrues. O uso deste modelo, muitas vezes
truturao. diculta a manuteno e expanso do cdigo, caso isto
Podemos denir C++ como um superconjunto da no seja feito de maneira muito bem organizada.
linguagem C, ou seja, uma linguagem com mais funci- O segundo modelo o orientado a objetos. O que sig-
onalidades que a linguagem C. Embora este seja o ponto nica isso e o que muda no modo de programar, caso o
de vista de quem j tem um conhecimento da linguagem adotemos em vez do modelo anterior?
C, ela muito mais que isto. Podemos mudar completa-
A orientao dene o modo de abordar o problema para
mente a forma de criar o programa quando usamos os re-
tentar solucion-lo:
cursos avanados da linguagem, as estruturas de deciso
(por exemplo, if-else ou switch) podem ser simplicadas
e a organizao do cdigo pode ser bem mais globalizada O modelo de orientao a procedimentos se preo-
e genrica, possibilitando a reutilizao do cdigo em di- cupa em fornecer meios para resolver o problema
versas situaes diferentes. sem contabilizar, a princpio, os dados que sero
Vejamos como as funcionalidades da linguagem C++ po- usados durante o processo.
dem ajudar a redenir os meios de programao que
aprendemos com o bom e velho estilo C. O modelo de orientao a objetos se preocupa com
os elementos que so necessrios para a soluo de
um problema. Sob este ngulo, os dados so os ele-
4.2 Dois modos de programar mentos principais na anlise do problema.

Observando o modo de programar que as linguagens ofe-Este livro traz uma viso dos problemas sob a ptica da
recem desde os primrdios da computao, podemos no- orientao a objetos, enquanto que o livro "Programar
tar vrios mtodos que foram sendo superados e outrosem C" traz a anlise sob a ptica da orientao a proce-
que se estabelecem por um momento. O modo de progra- dimentos. Isto no quer dizer que devamos escolher a
mar mais usual e bem mais difundido conhecido como orientao a objetos como o modo mandatrio de pro-
modelo estruturado sequencial. Em sntese, refere-se gramao, mas que podemos contar com seus recursos
a forma de programar onde uma instruo segue a outrasempre que esta escolha facilite a resoluo do problema.
numa sequncia que inicia e termina em um uxo parci-Portanto, cabe sempre uma anlise para denir se o pro-
almente previsvel. blema melhor tratado por uma abordagem orientada a
A programao estruturada ainda pode ser classicada objetos ou a procedimentos.

4
4.4. OBJETOS 5

4.3 Um pouco sobre orientao a 4.3.1 Paradigmas da Programao:


objetos Desde o incio da programao, j passamos pelos se-
guintes paradigmas:
A programao orientada a objetos um paradigma
de programao que visa organizao, produtividade e No estruturada - exemplos: COBOL,
sustentabilidade. FORTRAN, BASIC (anos 50-60)
A apresentao dos conceitos de orientao a objetos
Procedimental ou Procedural - exemplos: C,
bastante abrangente, o que implica na abordagem de
Pascal (anos 70)
diversos aspectos, como modelagem, estudo de perfor-
mance de modelos, aplicabilidade de tcnicas, estrutura- Modular - exemplo: Modula II (anos 80)
o de objetos, otimizao, manuteno do cdigo, entre
outros. Por este motivo, nosso objetivo aqui no apre- Abstrao de tipos de dados - exemplo: Ada (anos
sentar a orientao a objetos em sua totalidade. Para um 80)
estudo mais detalhado do tema sugerimos o livro POO, Programao Orientada a Objetos - exemplos:
que trata especicamente deste tema. O objetivo aqui C++, Java, Delphi (Object Pascal) entre outras. (d-
apresentar como a orientao a objetos se aplica na lin- cadas 80-90-2000)
guagem C++, porm os conceitos aqui apresentados de-
vem ser sucientes para a estruturao de programas de
bom nvel.
4.4 Objetos
A ideia principal por traz do modelo de programao
orientado a objetos est em transformar entidades do Objeto , genericamente, uma entidade de armazena-
mundo real em identicadores dentro do programa (ob- mento e manipulao de dados. O mesmo deve ser criado
jetos), trabalhando-os como entidades da linguagem que para processar os dados que armazena e recebe, sendo
possuem caractersticas e operaes prprias. Esta abor- sensvel a entradas do programa principal para fornecer as
dagem transforma o programa em um meio de simula- sadas esperadas pelo mesmo. Por estes motivos o objeto
o de situaes virtuais por meio de entidades de cdigo deve ser pensado como uma entidade de dados autnoma,
que tem comportamento predenido. Esta abstrao encarregada de processar todos os dados que mantm.
uma aliada do programador por permitir idealizar siste-
mas mais sosticados de uma maneira bastante intuitiva. Da mesma forma que podemos usar tipos de dados nati-
vos da linguagem podemos criar nossos tipos de dados.
Todas as linguagens orientadas a objetos contm os prin- Na linguagem C podemos criar tipos de dados compos-
cpios de: tos que chamamos de estruturas, estes so criados com
a palavra chave struct. C++ possibilita o uso de estrutu-
Encapsulamento ras de dados e introduz um novo tipo chamado de classe.
Como o nome sugere, uma classe refere-se a um conjunto
um mecanismo para esconder os detalhes en-
de caractersticas dadas a um grupo de indivduos, ou
volvidos no processamento de uma ao. Por
seja, grupo de objetos. Por este motivo, classe a deni-
exemplo, quando usamos um telefone, no pre-
o de tipo de objeto.
cisamos lidar diretamente com o circuito in-
terno; a interface do telefone cuida desse pro- Em C++ as classes de objetos so criadas atravs da pala-
blema. vra chave class. Esta nomenclatura usada por muitas ou-
tras linguagens de programao mais caracteristicamente
Polimorsmo restritas a orientao a objetos. Estes aspectos facilitam
um pouco o aprendizado por programadores j familiari-
Isso permite o uso de uma nica interface zados com estas linguagens quando iniciam a programa-
uma nica forma de uso para objetos de ti- o em C++.
pos diferentes; em particular, a mesma inter-
O processo de criao de um objeto segue a sequncia:
face para objetos de uma classe e objetos de
classes derivadas dessa.
Denir os dados e procedimentos que a classe deve
Herana conter;
Criar a classe de objetos;
Como o nome sugere, isso permite que uma
classe herde de outra suas caractersticas, po- Declarar (instanciar) o objeto.
dendo tambm introduzir suas prprias ou al-
terar as caractersticas herdadas. O uso de he- A denio de uma classe de objetos deve ser feita de
rana acaba poupando trabalho e melhorando forma a tornar, preferencialmente, todos os dados pro-
a organizao do cdigo. tegidos de interferncias de cdigos externos ao objeto.
6 CAPTULO 4. INTRODUO

Por este motivo um objeto deve ser uma parte do cdigo


do programa com uma certa autonomia. Este deve ter
controle sobre seus dados e ser capaz de prov-los e lidar
com eventos a eles relacionados. Dentro de seu escopo
de responsabilidades, a entidade deve essencialmente ter
vida prpria.
Captulo 5

Al, Mundo!

5.1 Ol mundo! MSDOS. Este comando deve ser evitado, pois diminui a
portabilidade do programa, j que pause s existe nos sis-
comum, no aprendizado de uma linguagem de pro- temas Microsoft. No entanto, se est usando Windows
gramao, que seu primeiro programa faa com que o necessrio adicionar esta linha, caso contrrio o computa-
computador exiba "Ol mundo!". Na linguagem C++ dor escreveria Ol mundo!" e fecharia o programa antes
este primeiro programa j introduz muitos conceitos so- que pudssemos ler qualquer coisa. Uma forma elegante
bre a linguagem. Veja o cdigo do nosso primeiro pro- de lidar com estas peculiaridades do Windows usar pre-
grama: denies, de forma que o programa seja portvel para
qualquer sistema operacional:
#include <iostream> using namespace std; int main () {
cout << Ol mundo!"; return 0; } #if dened(_MSC_VER) // estas linhas sero executadas
apenas quando o programa // for compilado por alguma
verso do Microsoft Visual C system(pause); #endif
Assim como para comear a dirigir no necessrio saber
toda a mecnica do carro, para programar no precisamos
logo de incio nos prender a todos os detalhes. Em sistemas parecidos com UNIX, como GNU/Linux ou
FreeBSD, pode-se usar um terminal de linha de comando
No programa acima, vamos dar ateno apenas ao con- facilmente, pois os mesmos possuem o recurso facilmente
tedo que se encontra entre as chaves: acessvel, mesmo quando o usurio est usando a inter-
{ cout << Ol mundo!"; return 0; } face grca. Por isso, para esses sistemas um comando
para solicitar pausa ao sistema no necessrio.

cout << Ol mundo!";

A palavra cout vem de Console OUT (sada do console),


onde geralmente temos a sada no monitor. O cout se-
guido do operador << e da frase que se quer informar
entre aspas: Ol mundo!", intuitivamente, isso nos leva 5.2 Entrada de dados e coment-
a ideia de que a sequncia de caracteres ser levada ao rios no cdigo
cout.

return 0; Comentrio um recurso muito til em programao.


Ele permite que o programador adicione texto ao pro-
Este comando termina o programa, o estudaremos melhor grama para facilitar o entendimento do programa por
no captulo sobre funes e retornos. parte de outros programadores, ou at dele mesmo. Os
comentrios so usados para explicar trechos de cdigo,
ATENO: adicionar clusulas e qualquer texto em geral.
Caso seu sistema operacional seja o Microsoft Windows, Vamos agora para um programa mais completo com en-
voc deve adicionar imediatamente antes de return 0; a trada de dados e comentrios dentro do cdigo:
seguinte linha:
// Este um comentrio de uma linha /* Este um
comentrio de vrias linhas */ #include <iostream> using
system (pause); namespace std; int main () { int x; cout << Digite um
nmero: "; cin >> x; cout << "\nVoc digitou o nmero:
A funo system() executa um comando do Windows. " << x << endl; return 0; }
como se o prprio usurio digitasse pause no prompt do

7
8 CAPTULO 5. AL, MUNDO!

5.2.1 Comentrios no programa 5.2.2 Incluindo cabealhos

Observemos esta linha: #include <iostream>


// Este um comentrio de uma linha O smbolo # uma chamada de ateno ao compilador
a dizer que aquela linha para o preprocessador, depois
temos o "include" (que basicamente diz para incluir c-
Esta uma linha de comando para o preprocessador (ou
digo). Incluir o qu?
precompilador).
Deve incluir o cheiro/arquivo iostream.
O que o preprocessador? Durante o processo de
(in+out+stream, uxo de entrada e sada, padro) (na
montagem do programa em formato binrio existem trs
maioria das vezes, como entrada padro temos o teclado
fases principais: O preprocessamento, a compilao e a
e como sada temos o monitor) (este cheiro/arquivo
fase de ligao (link). O preprocessador um programa
contm declaraes das funes e denies que o nosso
invocado pelo compilador para remover comentrios e
cdigo fonte ir necessitar)
substituir certas partes do programa conforme a neces-
sidade do cdigo criado pelo programador. Este cdigo que ser includo chamado de cabealho
devido a uma caracterstica evidente, o fato de ser cdigo
O preprocessador faz algumas alteraes no texto fonte,
de declarao inicial do programa, que deve estar no topo
que basicamente consistem em eliminar pedaos de c-
do arquivo/cheiro.
digo e/ou substitu-los por outros (copy-paste). Enm, o
mesmo altera o cdigo fonte contendo comandos inicia- Existem outros arquivos (cheiros cabealho), o iostream
dos com # e outros comandos especcos, por outro c- para uxos de entrada e sada, mas temos muitos mais
digo sem comandos de preprocessamento, puramente em para matemtica, manipulao de tempo, tratamento de
linguagem C++. caracteres, etc...
Ao analisar o cdigo, o preprocessador encontra a Na maioria das vezes, os arquivos de cabealho fazem
sequncia // e vai eliminar o texto que est a seguir at parte de uma biblioteca. Podemos ver na parte dos ane-
ao m da linha. xos, algumas bibliotecas que existem juntamente com as
funes de cada uma. Ns prprios podemos criar uma
Mais uma forma de adicionar comentrios:
biblioteca com cdigo e nosso prprio cabealho. E at
/* Este um comentrio de vrias linhas */ podemos comprar bibliotecas existentes comercialmente,
atravs de empresas especializadas em desenvolvimento,
A linguagem C++ permite tambm fazer comentrios por que tambm tero seus arquivos/cheiros de cabealhos.
mais do que uma linha. Chama-se comentrio por bloco e Mas, o que so bibliotecas? So arquivos com um con-
o que faz eliminar tudo o que encontrar entre a sequn- junto de cdigos que algum fez antes. As que enun-
cia inicial /* e o nal */. ciamos antes so as "standard", so aquelas que tm as
A vantagem de termos esta possibilidade poder comen- funcionalidades bsicas, pertencentes aos padres da lin-
tar o nosso cdigo. Existem algumas regras de boa con- guagem. Repare-se que precisamos da biblioteca at para
duta para comentrios que foram criadas por pessoas que escrever (no ecr)/(na tela) (stream + out) que nos permite
j tm muito tempo nisto: utilizar o cout.
O cheiro/arquivo iostream est envolvido em < >,
isto signica que o preprocessador deve procurar o -
Uma criar logo no topo um comentrio a dizer o cheiro/arquivo no stio/diretrio usual (que onde o com-
que o nosso programa, e o que faz numa forma pilador usa como padro para os includes). Se tivsse-
geral; mos o cheiro/arquivo iostream envolvido em "" signi-
caria que o preprocessador deveria procur-lo dentro de
Outra fazer comentrios a cada funo que aparece uma lista de diretrios de incluso, includes, iniciando
no cdigo a explicar; pelo diretrio atual.
As bibliotecas so compostas por 2 partes: um ndice de
Outra comentar uma linha mais obscura, mais di- todas as funes e denies e declaraes, o cabealho,
fcil de entender, que no bvia; e depois a denio de todas as funes existentes no n-
dice, arquivos de cdigo.
A outra no comentar tudo. O comentar deve ser As diretivas de preprocessamento no terminam com o
para sobressair. ponto e vrgula como nas instrues.

Esta ltima regra pode ser esquecida quando o programa 5.2.3 Namespace
didtico, neste caso pode-se usar o programa como
texto comentado. using namespace std;
5.2. ENTRADA DE DADOS E COMENTRIOS NO CDIGO 9

Observando esta linha, alguns tradicionais programado- O int signica que a funo vai retornar um inteiro. Exis-
res em linguagem C, tm uma novidade: namespaces so tem outros tipos de dados como, por exemplo, os seguin-
espaos de nomes dentro do cdigo, eles funcionam, en- tes:
tre outras coisas, como um meio de evitar duplicao
de nomes dentro de um projeto extenso, que geralmente
contam com inmeros arquivos. int que a abreviatura de inteiro;
O C++ usa os namespaces para organizar os diferentes
nomes usados nos programas. Cada nome usado no - char que a abreviatura de caratere;
cheiro/arquivo biblioteca "standard iostream" faz parte
do "namespace" chamado de std.
oat que a abreviatura de "oating point number",
O objeto de sada padro, cout, est denido dentro do ou seja, uma representao para nmero real.
namespace std, ele um objeto da classe ostream
"output stream", para acess-lo temos que referenci-lo
como "std::cout". Para evitar que tenhamos que infor- Vejamos um exemplo:
mar "std::" todas as vezes que precisarmos usar os recur- Quando criamos uma funo soma, obviamente s para
sos deste namespace, podemos informar que estamos ilustrao pois isso no necessrio, podemos fazer:
usando-o dentro do arquivo atual, conforme vemos na li-
nha declarada no incio deste tpico. int soma(int a, int b) { return a + b; }

O namespace permite que as variveis sejam localiza-


das em certas regies do cdigo. Declarar o namespace Agora imagine que tenhamos que somar 2 e 3, colocando
std permite que todos os objetos e funes da biblioteca o resultado em outra varivel chamada valor, para isto
"standard input-output" possam ser usados sem qualquer faremos:
qualicaes especcas, desta maneira, no mais ne- valor = soma(2, 3);
cessrio o uso de "std::".
Este um conceito avanado que podemos explorar mais, Primeiro analisamos qual o resultado e depois substitu-
vamos deix-lo para depois. mos a funo pelo valor que ela retorna:
valor = 5;

5.2.4 Funo main Simples, no?


int main(){} ; - Final de sequncia de instrues

Como na linguagem C, a funo principal de entrada do O ponto e vrgula funciona como ponto nal, separa as
programa a partir do sistema operacional a funo main. instrues e contextos. Repare que apenas as funes, ou
Por isso mesmo ela obrigatria em qualquer programa. melhor, as denies de funes e as diretivas de prepro-
Se no existisse uma "main function", no haveria entrada cessamento que no tm o ";"
para que o sistema iniciasse o programa. importante notar que o cdigo poderia ser todo escrito
Todas as funes so declaradas e usadas com o opera- quase numa linha tipo:
dor ( ), assim que o compilador reconhece que estas int main (){int a; cout << Hello world! Digite um
so funes. A ideia de ter funes permitir o encap- nmero:\n"; cin >> a;cout << Voc digitou o nmero: "
sulamento de uma ideia ou operao, dar um nome a isso << a<<"\n";return 0;}
e depois chamar essa operao de vrias partes do pro-
grama simplesmente usando o seu nome. As funes de-
claradas como membros de uma classe de objetos podem realmente o ";" que faz a terminao das instrues.
ser chamadas de mtodos. Ao encontrar as chaves "{}", o compilador reconhece
Do ponto de vista funcional, um cdigo dentro de uma como um delimitador de bloco, ou "body", corpo. O
funo executa operaes em outra parte do programa, corpo de uma funo ou bloco de cdigo comea com
que no aquela de onde foi chamada, por este motivo "{" e termina com "}", como temos as instrues agrupa-
as mesmas contam com um mecanismo de passagem de das, j no h necessidade de colocar o ";" no nal para
dados, ao declarar uma funo indicamos quais os dados indicar onde o m do bloco.
que entram e o que ela deve fornecer a quem lhe cha- No nosso exemplo existem 2 instrues no corpo da fun-
mou. Pode-se dizer que, tal qual uma funo matem- o. As instrues so executadas por ordem: do topo at
tica, a funo em C/C++ poder ser substituda, depois ao m a menos que existam funes que alterem o uxo
de sua execuo, pelo valor que ela retorna, este valor da leitura ou que existam cdigos de controle de execu-
ser especicado antes do nome da funo na declarao o "execution control codes", que alteram o caminho de
da mesma, conforme vemos no incio deste tpico. execuo.
10 CAPTULO 5. AL, MUNDO!

5.2.5 Entrada e sada (cin/cout) descarrega os dados do stream logo aps a nalizao da
linha.

cout << Hello world! Digite um nmero:\n";


(c+out) Podemos utilizar este objeto porque pusemos o 5.2.6 funo system(pause)
header e o namespace std. As informaes sero dire-
cionadas atravs do iostream, um subsistema de entrada system (pause);
e sada da biblioteca padro. O que este objeto nos per- A maioria dos compiladores quando esto executando em
mite enviar o que temos entre aspas para a sada (out), modo grco fecha o console de sada assim que o pro-
que o monitor neste caso. grama naliza. Isto impede que possamos ver o que acon-
Quem j conhece a linguagem C, certamente est fami- teceu, principalmente quando o programa contm apenas
liarizado com os streams da biblioteca padro, o stdin, umas poucas instrues.
o stdout e o stderr... A linguagem C++ implementa os A funo system(), faz parte do padro da linguagem C,
mesmos dispositivos sob a forma de objetos. ela executa uma chamada de sistema, ou seja, ela passa
O cout envia dados para o "standard output device", que um comando para o sistema, que neste caso pause,
usualmente o monitor, a abstrao do elemento de sada como j informamos no incio deste captulo,
este co-
padro observada na presena de um objeto que repre- mando destinado a sistemas da Microsoft . Coloquei
senta a sada fsica de dados para o meio externo. esta linha para que o programa no nalizasse sem que
pudssemos ver uma janela com o resultado, se no o -
Observa-se que temos o operador <<, neste caso pode- zesse a janela abriria e fecharia sem que pudssemos ver
mos vericar mais uma das funcionalidades da lingua- o aconteceu durante a execuo do programa.
gem, pois este operador usado para deslocamento de
bits na sua funcionalidade padro, neste caso a sua funo Em sistemas como GNU/Linux, FreeBSD, Solaris ,
foi substituda por outra, transferir os dados a sua direita etc... temos acesso a terminais de console e compiladores
para o "output stream" do seu lado esquerdo. em linha de comando, assim basta compilar o programa
sem esta linha e depois execut-lo, para ver o resultado.
O cout um objeto da biblioteca "standard C++" que tem
como uma de suas funes imprimir strings no "standard
output" (que normalmente o/a ecr/tela). 5.2.7 Retornando valor
Da mesma forma que podemos formatar o texto enviado
a sada padro na linguagem C, tambm podemos faz-lo return 0
com os objetos do C++, por exemplo, se acrescentsse- Faz com que a funo retorne o valor zero, como esta
mos "<< hex <<" entre uma varivel e a sada: funo a principal do programa, por onde o sistema
cout<< hex << n; operativo/operacional iniciou a execuo do mesmo, este
retorno recebido pelo sistema, comum que valores di-
ferentes de zero sejam interpretados como erro do pro-
O resultado seria impresso em hexadecimal; grama.
Para entrada de dados temos: Esta instruo manda retornar o valor zero para o sistema
cin >> a; operativo/operacional (Windows, Unix, ...). Este zero re-
presenta a dizer que o programa nalizou normalmente.
Pode acontecer que o programa no nalize como seria de
O que esta linha faz colocar o valor que foi digitado esperar, ele tem um crash (ou porque cou com falta de
numa rea de memria que foi chamada de a. memria.). O sistema operativo/operacional necessita de
Da mesma forma que o cout existe para sada de dados, lidar com estas terminaes anormais de uma forma di-
temos outro objeto para entrada atravs do teclado, este ferente das normais. Por isso que o programa diz ao sis-
objeto chamado de Console IN - cin, seguindo a mesma tema operativo/operacional que terminou normalmente.
analogia. Observe que o operador >> usado para dar Questo: porque que o sistema operativo necessita de
ideia de que os dados esto vindo do cin para a varivel saber que o programa terminou bem?
a.
cout << Voc digitou o nmero: " << a << "\n";

Aqui voltamos a utilizar o objeto cout primeiro para im-


primir no/na ecr/tela a frase Voc digitou o nmero: ",
depois vai buscar o valor que est naquela rea de mem-
ria a que chamamos de a e por m coloca o m de linha
atravs de "\n, em C++ podemos usar um nalizador de
linha chamado endl, o uso do mesmo mais eciente pois
Captulo 6

Variveis e constantes

6.1 Constantes Para isso podemos colocar expresses com funcionalida-


des bem denidas substitudas por nomes que as identi-
Compatvel com a linguagem C, o C++ mantm as cons- quem. Por exemplo:
tantes bsicas e introduz algumas novas funcionalidades oat a[3]; #dene PRINT_VECTOR cout << a[0] << " , "
possibilitadas pelo modicador const. << a[1] << " , " << a[2] << endl ... ... PRINT_VECTOR;
O uso do modicador const tem duas funes principais:
Desta forma, todas as vezes que quisermos mostrar o va-
1. Resguarda da inviolabilidade de valores apontados lor do vetor de trs coordenadas podemos usar a constante
por ponteiros; PRINT_VECTOR.

2. Auxlio na compreenso das caractersticas de fun-


es, durante a implementao.
6.1.2 Literais
Constantes literais podem ser declaradas da mesma forma
que na linguagem C, ou seja, podemos denir valores -
6.1.1 Simblicas xos em qualquer parte do programa, expressando-os dire-
tamente no cdigo atravs de seu valor signicativo. Por
Constantes simblicas podem ser criadas com as direti-
exemplo, podemos denir nmeros:
vas do preprocessador #dene. Neste modo os valores, de
fato, no so interpretados imediatamente pelo compila- 256 //decimal 0400 //octal 0x100 //hexadecimal
dor, antes so identicados e substituidos pelo preproces-
sador no estgio anterior compilao. Por exemplo: Tambm podemos denir valores para caracteres ou ca-
#dene BUFFER_LENGTH 2048 ... ... ... char deias de caracteres, como segue:
data[BUFFER_LENGTH]; 'a' // um caractere abc // uma cadeia de caracteres
"\xF3\x23\x12 // uma cadeia de caracteres representada
Observe que o valor 2048 ser usado logo abaixo no c- por seus valores em hexadecimal
digo, depois que o preprocessador substituir a constante
simblica BUFFER_LENGTH pelo valor que lhe foi atri- Temos ainda a possibilidade de declarar constantes com-
budo. postas por valores e operadores:
Note que as constantes so escritas com todas as letras (4.23e14 * (12.75 + 12976.18/36)) // constante composta
maisculas, isso no uma regra, mas ajuda a identicar
o que constante simblica dentro do programa, sendo
adotado pela maioria dos desenvolvedores como uma boa
prtica de programao. 6.1.3 Enumeraes
Neste caso, podemos denir valores simblicos compos-
tos, por exemplo: Valores enumerados so muito recorrentes nos ambientes
de programao, por isso podemos contar com a decla-
#dene BUFFER_LENGTH 2048 #dene rao de enum em C++ tambm, o que segue a mesma
N_BUFFERS 100 #dene MASTER_LENGTH ( sintaxe que temos em C":
BUFFER_LENGTH * N_BUFFERS ) ... ... ... char
screen[MASTER_LENGTH]; enum seq {A,B,C,D}; seq x;

Os valores podem ser simblicos em formato de cdigo, ou ainda:


o que permite criar programas com melhor legibilidade. enum nomes {LANY=100,SANDRA=200,MARCIA=300,RODRIGO=40

11
12 CAPTULO 6. VARIVEIS E CONSTANTES

nomes x; linguagem C, porm seu tamanho na memria depende


da capacidade de otimizao do compilador usado. Tipi-
Porm, observamos uma diferena: a palavra enum pode camente os compiladores para computadores usam uma
ser dispensada na declarao da varivel, enquanto que varivel do tamanho de char para representar o valor, o
em C obrigatrio,apesar desta pequena diferena a fun- que poderia ser considerado um desperdcio, mas devido
cionalidade do recurso a mesma, ou seja, pode-se de- abundncia de memria no chega a ser inadequado.
nir variveis que assumem estritamente os valores pre- Porm em sistemas pequenos h compiladores que ar-
sentes na declarao de enumerao. mazenam o valor booleano em apenas um bit. Obvia-
mente, se o processador possuir recursos de manipulao
Este recurso torna-se til na padronizao de valores a se- de bits isso muito til e pode ser usado como um fator
rem usados como entrada de funes, por exemplo. Pode de melhoria da qualidade do software desenvolvido. Em
ser considerada como uma funcionalidade mnemnica, outros ambientes, onde a manipulao de bits traga pre-
seu uso no altera o cdigo nal caso modiquemos o juzo para o desempenho usa-se a estratgia padro de
programa para que use variveis inteiras ou strings de desperdiar um pouco de espao em favor de uma agili-
mesmo valor do enum. dade maior nas operaes. Portanto, embora as variaes
A seguinte sintaxe: de utilizao do espao sejam muitas, o compilador sem-
pre far a mais apropriada para cada ambiente de utiliza-
seq x = 3; o da linguagem.

No permitida, mesmo que o valor presente no enum


seja avaliado como 3 pelo compilador em tempo de com- 6.2.2 Modicadores
pilao. Isso pode parecer confuso, mas lembre-se de
O C++ conta com os modicadores de amplitude
que os valores sero atribuidos pelo compilador, logo isso
evita que o mesmo programa seja compilado em ambien- (short,long) presentes na linguagem C e modicado-
tes diferentes e tenha comportamento diferente. res de acesso, alguns exclusivos do C++, que esto dire-
tamente ligados a caractersticas da POO (programao
orientada a objetos). Desta forma descreveremos apenas
os tipos relevantes exclusivamente para a programao
6.2 Variveis na linguagem escopo do livro presente sem nos aprofun-
darmos na teoria por trs dos mesmos. A prtica do uso
As variveis no C++ podem ser usadas da mesma forma dos mesmos melhor indicada como meio de aprofunda-
que na linguagem C, porm algumas poucas diferenas mento do tema.
podem ser destacadas, principalmente aquelas que trazem
linguagem C++ caractersticas prprias da orientao a Assim contamos com os modicadores da linguagem
objetos. C":
static short long unsigned signed

6.2.1 Tipos
Como na linguagem C, os tipos nativos do compilador const
em uso so referenciados por:
char int oat double A linguagem C++ introduz um novo modicador cha-
mado const, que tem comportamento variado depen-
dendo do local onde est sendo declarado. Sua funo,
Que correspondem a nmeros com tamanho relativos, basicamente, estabelecer um vnculo entre declarao
com os signicados respectivos: caractere, inteiro, ponto e obrigatoriedade da coerncia no uso do smbolo decla-
utuante e ponto utuante de dupla preciso. De qual- rado.
quer forma a extenso dos mesmos depende da mquina
que se pretende programar. Considerando que nem sem- A princpio, quando declaramos uma constante com este
pre teremos que programar apenas computadores, pode- modicador fazemos com que seja obrigatrio o uso do
remos ter extenses bem distintas dependendo do hard- smbolo de forma que o mesmo no possa ter seu valor
ware a ser programado, por exemplo, computadores do- alterado. Assim, se zermos:
msticos tipicamente tem processadores de 32 ou 64 bits const int x = 4;
hoje em dia, enquanto que dispositivos embarcados po-
dem ter processadores de 8, 16 ou 32 bits. Portanto, o O inteiro x no poder deixar de ter valor igual a 4. Qual-
compilador para cada caso atribui faixas diferentes para quer tentativa de modicar o valor da constante ao longo
cada tipo em cada situao. do programa ser reportada como erro pelo compilador.
A linguagem C++ introduz o tipo bool, que representa o Porm podemos considerar esta funcionalidade como b-
valor booleano, falso ou verdadeiro, o que no existe na via e trivial, ainda temos o uso do modicador de uma
6.2. VARIVEIS 13

forma mais proveitosa, na passagem de parmetros para fazer alguma coisa } }


funes, por exemplo:
void inhibitX(const int *x) { ... ... BASEADDRESS = Poderemos ter uma otimizao gerada pelo compilador
z*((*x) - 23p*71); ... ... } como segue:
int x = 1265; void main_loop_optimized() { while( true
Neste caso, a funo acima recebe um valor inteiro atra- ) { // fazer alguma coisa } }
vs de um ponteiro, que no obrigatoriamente precisa
ser constante no escopo fora da funo, porm dentro da Considerando que em um programa que foi desenhado
mesma a varivel ser constante. Fazendo este simples para ambiente multitarefa isso no pode ser considerado
procedimento teremos como fazer com que um smbolo verdadeiro, pois o programa pode estar esperando que
seja varivel fora da funo e constante dentro da mesma, uma das tarefas modique o estado da varivel para pros-
de forma que dentro do escopo da mesma s faamos lei- seguir seu curso, a otimizao acima ser um desastre,
turas do seu valor. O artifcio cria duas consequncias uma vez que a funo acima jamais ser encerrada.
importantes: a primeira a melhor legibilidade do c-
digo, visto que ao usarmos uma funo teremos certeza Para evitar isso fazemos:
de que os valores no sero alterados dentro da funo; volatile int x = 1265; void main_loop() { while( x ==
a segunda que poderemos evitar erros inadvertidos de 1265) { // fazer alguma coisa } }
atribuio de valores varivel quando da construo da
funo.
E o compilador no poder mais avaliar que o valor de
x pode ser otimizado para o valor corrente, pois infor-
mamos na declarao que o valor da varivel pode ser
volatile
alterado sem seu conhecimento. Desta forma o mesmo
no alterar o algortmo e far o teste da varivel dentro
Uma varivel "voltil", como a prpria expresso sugere,
do while.
uma varivel que pode ser modicada sem o conhe-
cimento do programa principal, mesmo que esta ainda
esteja declarada dentro do escopo onde o programa est 6.2.3 Nomeando tipos
sendo executado. Isso est relacionado, principalmente a
processos concorrentes e threads, estes podem alterar o A linguagem C possui recursos de nomeao de tipos
contedo da varivel em eventos fora da previsibilidade simples e compostos atravs das palavras chaves typedef
do tempo de compilao. Em outras palavras, o compi- e struct. Adicionada a estas o C++ acrescenta a palavra
lador no pode prever com segurana se pode otimizar chave class. Vejamos como devemos denir um novo
trechos de programa onde esta varivel se encontra. tipo atravs desta palavra chave.
A palavra reservada volatile destinada as situaes onde
A palavra class atribui a um conjunto de tipos de dados o
uma varivel pode ter seu valor alterado por fatores di- estado de modelo de objeto. Este conceito fundamental
versos, e portanto, no pode ser otimizada. Usando-a o
para o modo avanado de programar usando o C++. Com
programador informa ao compilador que no deve inter- este identicador declaramos objetos, da mesma forma
ferir na forma com que o programa foi escrito para acesso que declaramos estruturas.
a esta varivel. Desta forma impede que erros inseridos
por otimizao estejam presentes na verso nal do exe- Uma classe pode ser denida em um cabealho header,
cutvel. da seguinte forma:
O uso desta palavra implica em mudana no comporta- class nome_da_classe { <tipo_1> variavel_1; <tipo_2>
mento do compilador durante a interpretao do cdigo. variavel_2; . . . <tipo_n> variavel_n; ----- <tipo_n>
As classes de objetos do tipo volteis s podero ser aces- nome_funcao ( <tipo_1> variavel_1, <tipo_2> varia-
sadas por rotinas que declarem aceitar como entrada da- vel_2, <tipo_3> variavel_3 ...); };
dos volteis, da mesma forma que apenas objetos volteis
podem acessar variveis volteis. Esta amarrao faz O mais interessante de observar a presena de uma fun-
com que o uso de tais variveis se torne mais seguro. o dentro da declarao acima. Ento poderamos per-
Podemos declarar variveis volteis da seguinte forma: guntar: Por que colocar uma funo dentro de um tipo?
A resposta simples: Para manipular os dados dentro do
volatile int x; tipo! No apenas por esta caracterstica, mas por vrias
outras que aboradaremos nos captulos seguintes, o tipo
Enquanto que para funes que acessam tais variveis te- class extremamente exvel e poderoso.
remos consequncias visveis na montagem do cdigo, importante ressaltar que em C++ a declarao do
por exemplo, se tivermos o seguinte trecho de programa: identicador: enum, struct, class, etc... dispensado
int x = 1265; void main_loop() { while( x == 1265) { // quando se declara uma varivel ou objeto para o referido
14 CAPTULO 6. VARIVEIS E CONSTANTES

tipo. Desta forma podemos ter tambm as seguintes de-


claraes como vlidas, alm do uso padro da linguagem
C":
struct data{ int a; int b; int c; }; class object{ int a; char
b; long w; oat p; void getData(); }; ... ... ... ... void
func() { data x; object y; ... ... y.getData(); }

Como podemos ver na funo acima se a varivel x for de-


clarada para uma estrutura data o uso da palavra struct
no obrigatrio, assim como tambm no o para ou-
tros tipos de dados compostos.
Captulo 7

Ponteiros

15
Captulo 8

Ponteiros

Em linguagem C, podemos denir variveis ponteiro, Exemplo:


ou seja, variveis que armazenam o endereo de outras
int *px;
variveis. Este recurso largamente explorado pela lin-
guagem, embora que deva ser usado com cautela por ini-
ciantes devido ao seu poder destrutivo. Como linguagem Muitas vezes, iniciantes podem se sentir confusos por-
"irm mais nova" o C++ tambm permite o uso de pon- que quando declaramos um ponteiro usamos o * e quando
teiros, o que a distingue de muitas outras linguagens ori- atribumos endereos a ele no usamos o *. A conceitu-
entadas a objeto. Embora seja muito difundida a idia da ao bsica a seguinte:
criao de linguagens que no suportem acesso a pontei-
ros, basicamente pressupondo que todos os programado- Declaramos o ponteiro com *, para que o compila-
res so inexperientes, a falta deste recurso limita as capa- dor identique que a varivel um ponteiro;
cidades de interao de programas com o hardware. Em
outras palavras, a falta de um meio de manipular pontei- Usamos o ponteiro sem *, para acessar o endereo
ros faz a linguagem limitada ou dependente de fabricantes que ele aponta na memria;
de bibliotecas que acessem o hardware. Usamos o ponteiro com *, para acessar o valor do
A disponibilidade do uso de ponteiros em C++ agrega um dado armazenado na posio de memria;
poder a mais ao conjunto da linguagem, porm implica
em necessidade de cautela na elaborao de programas
que usam deste recurso. Certamente, nem todos os pro- 8.2 O operador &
gramadores precisam ser considerados inaptos, a priori,
atravs da supresso ou insero de complicadores de re-
Na linguagem C, o operador & tem trs funes b-
cursos criados explicitamente para for-los a no usar
sicas, funciona como operador da funo lgica AND
dos recursos. Por isso, a linguagem C++ disponibiliza o
como operador binrio bit-a bit AND e como operador
recurso para quem deseja utiliz-lo e tambm apresenta
de leitura de endereos. Para operaes com vetores,
diversos outros recursos que so alternativas ao uso de
isso usado da seguinte forma:
ponteiros quando eles no so imprescindveis.
int a = 12; int *pa; ... ... pa = &a; ... ... *pa = 100;

8.1 O operador * Ou seja, declaramos a varivel a, depois declaramos um


ponteiro pa, atravs do operador & obtemos o endereo
O operador *, chamado de apontador, funciona em C++ de a e atribumos o valor 100 varivel usando o ponteiro
da mesma forma que em C. Considerando que tenhamos ao invs da varivel a. Desta forma alteramos o valor de
uma varivel ponteiro p: a indiretamente.
Um outro uso de & (que no tem similar em C) pode ser
Em p armazena-se o endereo de memria que quei- visto mais adiante, em Referncias de dados, mas, para
ramos manipular. Na maioria das vezes obtemos o isto, necessrio estudar o que so Funes.
endereo de outra varivel e colocamos em p;

Se p um ponteiro, *p o valor apontado por p, ou 8.3 O ponteiro this


seja, o valor que est armazenado no endereo de
memria que queremos ler ou alterar. Imagine que tenhamos criado um objeto qualquer de uma
classe X, se quisermos ter acesso ao ponteiro que contm
Na declarao de variveis, uma varivel declarada com a posio de memria onde est armazenado este objeto
* um ponteiro. basta chamar o ponteiro "this". O ponteiro this uma

16
8.3. O PONTEIRO THIS 17

das caractersticas dos objetos em C++ e algumas outras


linguagens que suportam orientao a objetos. Ele um
membro inerente a todos os objetos que instanciamos em
programas escritos em C++.
Faremos uma breve explanao a respeito de objetos para
esclarecer este tpico. Objeto so parecidos com estru-
turas, uma diferena bsica que estes possuem habi-
lidades especcas representadas por funes que esto
dentro do seu escopo. Vejamos um exemplo:
struct Data { int x,y; int get_x(){ return x;} int get_y(){
return y;} int set_x(int a){ return x=a;} int set_y(int b){
return y=b;} };

Observe que a estrutura acima apresenta dois inteiros e


duas funes para cada um deles, uma que atribui o valor
e outra que l o valor de uma das mesmas. Detalhes das
implicaes a respeito desse modo de operar os valores
sero dados nos captulos seguintes que tratam de obje-
tos. Por ora vamos nos ater a um conceito fundamental
importante para a noo de ponteiros em C++, a identi-
dade de um objeto.
Veja, temos uma estrutura de dados que est na memria,
os dados esto l (variveis x e y), porm as funes no
estaro l, pois se tivssemos que copiar uma funo para
cada estrutura que crissemos o programa tomaria um ta-
manho monstruoso. O que se faz apenas guardar o en-
dereo da estrutura em um ponteiro especial, o ponteiro
this. Assim, o compilador poder criar uma nica cpia
de funo para todas as estruturas que criarmos e depois
quando a funo quiser manipular os dados de uma es-
trutura em particular, o far atravs do ponteiro this.
Examinemos os detalhes mais de perto... Digamos que
instanciemos um objeto A da classe Data:
Data A; A.set_x(2); A.set_y(7);

Para acessar estas funes o compilador far:


Data A; A.set_x(2); // { Data *this = &A; // return
this->x = 2; // } A.set_y(7); // { Data *this = &A; //
return this->y = 7; // }

Desta forma podemos perceber como diferentes conjun-


tos de dados podem ser manipulados pela mesma funo.
Quando declaramos uma funo dentro de uma estrutura
de dados esta rotina recebe um ponteiro com o endereo
do conjunto de dados que deve tratar toda vez que for in-
vocada pelo programa. Assim, sempre acessar os dados
atravs deste ponteiro, o this. Como todos os objetos
precisam ser identicados por esse ponteiro, ele de-
nido para qualquer objeto com o mesmo nome: this.
Captulo 9

Vetores

18
Captulo 10

Vetores e Matrizes

Faamos uma pequena reviso de conceitos: 10.2 Matrizes

Vetores e matrizes so variveis compostas homog- Podemos imaginar que uma matriz um conjunto de ve-
neas, ou seja, so agrupamentos de dados que indi- tores que ocupam uma determinada rea de memria re-
vidualmente ocupam o mesmo tamanho na memria ferenciada por um nome comum. Matrizes de tipos pri-
e so referenciados pelo mesmo nome, geralmente mitivos so conseguidas atravs de associaes do opera-
so individualizadas usando-se ndices. dor [ ], como por exemplo:
char A[32][16]; int B[12][26][10];
Vetores distinguem-se das matrizes apenas pela ca-
racterstica de ter dimenso (1 x n) ou (n x 1), es- Denindo nossas classes de objetos poderemos declarar
sencialmente vetores so matrizes linha ou matrizes matrizes de objetos:
coluna.
class Record { int D; oat X,Y; char desc[12]; public:
Record(); void addFData(oat A, oat B); oat getFDa-
Em linguagem C vetores e matrizes so usados abun- taX(); oat getFDataY(); ... ... ... }; void function() {
dantemente para compor estruturas de dados necessrias Record A[32][16]; ... ... ...
para composio de diversos recursos. Esta usa, mais ex-
plicitamente, vetores de caracteres para denir cadeias de
Ou seja, podemos adotar a mesma sintaxe para criar ma-
texto, o que conhecido como o mais trivial uso de ve-
trizes de objetos. Este procedimento pode ser usado com
tores. Alm deste recurso, o C tambm dene meio de
o cuidado de se avaliar antes a quantidade de memria
criao de matrizes tipo (n x m), provendo, desta forma
disponvel para que a matriz no ultrapasse esse limite
os recursos necessrios para criao destes conjuntos de
fsico, muitas vezes delimitada pelo hardware ou pelo sis-
dados.
tema operacional. Lembremos que, um objeto precisa do
A linguagem C++" suporta os mesmos recursos e per- espao equivalente a soma de suas variveis internas para
mite a criao de matrizes de objetos. Uma vez que um ser alocado na memria.
objeto essencialmente um tipo de dado criado pelo pro-
gramador, todas as caractersticas bsicas legadas aos ti-
pos em geral so observados nos tipos criados (classes de 10.3 Declarando arranjo
objetos).

Os arrays permitem fazer o seguinte:


int a1, a2, a3,.a100; equivalente a ter int a[100];
10.1 Vetores
Ou seja permite declarar muitas variveis de uma forma
bem simples, poupa escrita e bastante compreensvel.
Os vetores em C++ seguem a mesma notao da lingua-
gem C, via de regra declara-se o tipo seguido de um as-
terisco. Para acessar o valor apontado pela varivel usa-se O nmero que est dentro de brackets [] o size de-
um asterisco de forma semelhante, como pode ser visto clarator. Ele que vai permitir ao computador di-
no trecho de cdigo abaixo: zer quantas variveis a serem geradas e logo quanta
memria dever ser reservada. A memria reser-
int *x; int a = 3; x = &a; cout <<" O valor do contedo vada para as variveis vo ser todas seguidas, um int
da posio 0x"; // O valor da posio 0x23A0209112 a seguir ao outro
cout << hex << x << de memria " << *x << endl; //
de memria 3 H uma forma para no dizer o valor deste size de-
clarator, mas isso apenas acontece antes da compi-

19
20 CAPTULO 10. VETORES E MATRIZES

lao, ou seja o compilador que vai fazer esse pre- o ndex comea no zero e no no 1. A razo disto tem
enchimento por ns, visualizando o nosso cdigo e a ver com oset que refere ao valor adicionado para o
contanto os membros que colocmos. Isto um au- endereo base para produzir a segunda address. Bem no
tomatismo dos compiladores recentes. chama-se a entendi bem! Eu explico de novo: O endereo (address)
isto iniciao implcita que vamos ver nesta seco. do primeiro elemento do array, o mesmo do que o en-
dereo base do prprio array. ah espera a, o que esto
As variveis geradas pelos arrays vo ser todos do a dizer que o endereo do array igual ao do primeiro
mesmo tipo. elemento do array. Assim o valor que teria de ser adi-
Reparem que o valor do size declarator um n- cionado, ao endereo base do array, para conseguirmos
mero. literal, ele no vai mudar quando o pro- o endereo do primeiro elemento seria zero. Agora sim,
grama estiver a correr. Por isso quando no souber- percebi!
mos o nmero de elementos o que fazemos? Erro: Um erro comum esquecer que o index comea no
zero, e portanto quando se querem referir ao ltimo ele-
Veja uma tentativa: mento, esquecem-se que tm de subtrair uma unidade. O
que advm desse esquecimento que podem estar a al-
#include <iostream> using namespace std; int main () {
terar memria pertencente a uma varivel, instruo,..de
int numTests; cout << Enter the number of test scores:";
um outro programa. Ou seja vai existir violao de da-
cin >> numTests; int testScore[numTests]; return 0; }
dos.
Se o array for declarado globalmente em vez de ser local-
Isto vai dar um erro de compilao, porque o array est
mente, ento cada elemento inicializado ao valor defaut
a espera de uma constante e no uma varivel. H uma
que zero.
maneira de contornar isto que atravs da memria di-
nmica que vamos dar mais tarde, num capitulo prprio,
pois isto vai envolver muitos conceitos.
10.6 Iniciao
10.4 Constantes
Iniciao, se bem se recordam atribuir um valor a uma
varivel ao mesmo tempo que declaramos a varivel. Po-
Reparem que h uma diferena entre literais e constan-
demos fazer a iniciao de um array de 2 maneiras:
tes, apesar de em ambos os casos o valor no alterado
durante a execuo do programa, a constant um nome 1) explicit array sizing
que representa o valor, o literal o valor. int testScore[3] = { 74, 87, 91 }; oat milesPerGallon[4]
= { 44.4, 22.3, 11.6, 33.3}; char grades[5] = {'A', 'B', 'C',
'D', 'F' }; string days[7] = {"Sunday, Monday, Tues-
10.5 Declarar constantes day, Wednesday,"Thursday, Friday, Saturday"};
Pergunta: O que que acontece se dermos mais valores
exatamente como declarar uma varivel com duas di- de atribuio do que elementos do array?
ferenas:
int a[3] = { 74, 87, 91, 45 };
1. A declarao comea com a palavra const. Isto vai Isto vai dar um erro de compilao too many initializers
dizer ao compilador que uma constante e no uma Pergunta: O que que acontece se tivermos menos va-
varivel lores do que os elementos?
2. Teremos de atribuir logo o valor na declarao, ou int a[3] = { 74 };
seja, fazer a iniciao
No acontece nada simplesmente no temos valores para
a[1] e a[2]. Porm em alguns compiladores os elemen-
Exemplo: tos no inicializados cam com os valores defaut, que no
const int numTests = 3; caso dos ints 0 no caso dos oats 0.0 e nos caracteres
o caractere nulo ("\0). No entanto se no inicializar-
Portanto se tentarmos colocar um outro valor ao numTest,
mos um dos elementos, os restantes elementos tero de
isso vai dar um erro de compilao ser no inicializados pois caso contrrio teremos um erro
Array index de compilao
a[100] composto por a[0], a[1], a[99] ( De a[0], 2) implicit array sizing
a[1], a[99] existe 100 posies) int testScore[ ] = { 74, 87, 91 }; oat milesPerGallon[ ]
Pergunta: Porque que o ndex comea em zero e no = { 44.4, 22.3, 11.6, 33.3}; char grades[ ] = {'A', 'B', 'C',
um? Ou seja temos as 100 posies que pedimos mas 'D', 'F' };
10.10. CONST CONSTANT ARRAYS 21

Aqui o compilador faz o trabalho por ns, conta os ele- 10.10 Const Constant arrays
mentos e preenche o nmero de elementos
const int daysInMonth [] = { 31, 28, 31, 30, 31, 30, 31,
31, 30, 31, 30, 31 };

10.7 Caracter array Recordar que temos de inicializar quando queremos fazer
uma constante array

char name[ ] = {'J', 'e', 'f', 'f', '\0' }; char name[ ] = Je";
Ambas as inicializaes so permitidas. Porm tomar 10.11 Atribuir valores ao array
ateno ultima iniciao! Quando colocmos as aspas
duplas o compilador acrescenta o "\0 na array que cria! #include <iostream> using namespace std; int main () {
No tem []!! Esta at costuma ser a preferida pelos pro- int testScore[3]; cout << Enter test score #1: "; cin >>
gramadores, ao estilo de strings (Na verdade as strings testScore[0]; cout << Enter test score #2: "; cin >> testS-
so arrays de char mas vamos falar disso num capitulo core[1]; cout << Enter test score #3: "; cin >> testS-
prprio) core[2]; cout << Test score #1: " << testScore[0] <<
O char "\0 o escape sequence para caracterer null. Este endl; cout << Test score #2: " << testScore[1] << endl;
escape sequence sinaliza ao cout o m do character array. cout << Test score #3: " << testScore[2] << endl; return
o ltimo elemento do array preenchido! Se no tivs- 0; }
semos este carcter apareceriam estranhos caracteres a Podemos atribuir o valor 1 a 1, mas para poupar escrita de
seguir ao je, chamados caracteres-lixo. (porqu?) programao melhor utilizar as funes anteriormente
Isto no signica que o ltimo elemento deva ser sempre revistas como o for
o null carcter
#include <iostream> using namespace std; int main () {
int testScore[3]; for (int i = 0; i < 3; i++) { cout << Enter
test score #" << i + 1 << ": "; cin >> testScore[i]; } for (i
10.8 Arrays de vrias dimenses = 0; i < 3; i++) { cout << Test score #" << i + 1 << ": "
<< testScore[i] << endl; } return 0; }

Podemos ter duas dimenses Ou melhor ainda podemos usar uma constante, para tor-
nar o nosso cdigo mais abstracto.
tipo_da_varivel nome_da_varivel [altura][largura];
#include <iostream> using namespace std; const int
como tambm poderamos ter innitas MAX = 3; int main () { int testScore[MAX]; for (int i
tipo_da_varivel nome_da_varivel [tam1][tam2] ... = 0; i < MAX; i++) { cout << Enter test score #" << i +
[tamN]; 1 << ": "; cin >> testScore[i]; } for (i = 0; i < MAX; i++)
{ cout << Test score #" << i + 1 << ": " << testScore[i]
<< endl; } return 0; }
Lembram-se da histria de termos o endereo do array
10.9 Iniciando igual ao endereo do 1 elemento do array?
#include <iostream> using namespace std; const int
oat vect [6] = { 1.3, 4.5, 2.7, 4.1, 0.0, 100.1 }; int matrx MAX = 3; int main () { int testScore[3] = { 74, 87, 91 };
[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; char str cout << testScore[0] <<"\n"; cout << testScore <<"\n";
[10] = { 'J', 'o', 'a', 'o', '\0' }; char str [10] = Joao"; char //array base e no um elemento particular do array return
str_vect [3][10] = { Joao, Maria, Jose }; 0; }
Peguemos no exemplo: Pois bem vemos que quando mandamos imprimir o array,
int a [2][3]={1,2,3,4,5,6,} ele d um endereo. Pois o valor do nome do array o
endereo do array.
Na memria teramos as coisas assim. ou seja os elemen-
tos so seguidos e do mesmo tipo
Portanto ter int a [2][3] equivalente a ter int a [6] o nome 10.12 Arrays como statements de
que se d que diferente.
funes
Pergunta: ser pedido espao par 6 ints ou antes um es-
pao com o tamanho de 6 ints? Como ns sabemos que
os arrays os elementos tm endereos de memoria con- Pegando no programa
secutivos, por isso, no podem ser pedidos 6 ints, pois se #include <iostream> using namespace std; const int
fosse esse o caso, poderia acontecer que eles no cassem MAX = 3; int main () { int testScore[MAX]; for (int i
juntos. = 0; i < MAX; i++) { cout << Enter test score #" << i +
22 CAPTULO 10. VETORES E MATRIZES

1 << ": "; cin >> testScore[i]; } for (i = 0; i < MAX; i++)
{ cout << Test score #" << i + 1 << ": " << testScore[i]
<< endl; } return 0; }
Vamos torn-lo mais modular, escrevendo uma funo
para atribuir valores ao array e outa funo para mostrar
os valores do array
#include <iostream> using namespace std; void assign-
Values(int[], int); void displayValues(int[], int); const int
MAX = 3; int main () { int testScore[MAX]; assignVa-
lues(testScore, MAX); displayValues(testScore, MAX);
return 0; } void assignValues(int tests[], int num) { for
(int i = 0; i < num; i++) { cout << Enter test score #" <<
i + 1 << ": "; cin >> tests[i]; } } void displayValues(int
scores[], int elems) { for (int i = 0; i < elems; i++) { cout
<< Test score #" << i + 1 << ": "<< scores[i] << endl; }
}

10.13 Arrays como argumentos de


funes
// arrays as parameters #include <iostream> using names-
pace std; void printarray (int array[], int length) /*funo
com 2 argumentos,um deles um array */ { for (int n=0;
n<length; n++) cout << array[n] << " "; cout << "\n"; }
int main () { int a[] = {5, 10, 15}; printarray (a,3); //passo
array como argumento return 0; }
Este exemplo por acaso est muito curioso
Pergunta: mas agora deveramos perguntar se neste caso
tnhamos uma passagem por valor ou referncia.
Quando um array passado para uma funo, a funo
recebe no a cpia do array mas invs disso o endereo,
address do primeiro elemento do array, que igual ao
valor do array (base).
Assim todas as modicaes que se efectuarem na funo
que foi chamada iro repercutir-se no array passado.
Vamos conrmar:
#include <iostream> using namespace std; void
doubleThem(int a[], int size); int main() { int
a; int myInts[10] = {1,2,3,4,5,6,7,8,9,10}; dou-
bleThem(myInts, 10); //passei o array base for (a=0;
a<10; a++) { cout << myInts[a] <<\t; } return 0; }
void doubleThem(int a[], int size) { int i; for (i = 0; i <
size; i++) { a[i] = 2 * a[i]; } }
Captulo 11

Estruturas

11.1 Breve reviso apropriado, geralmente, dentro de algum bloco de c-


digo onde venha a ser usado. Podemos ver logo abaixo, o
exemplo de uma declarao de estrutura:
11.1.1 Conceito
struct Estrutura { int Inteiro; double PontoFlutuante;
Da linguagem C tambm temos o conceito de estrutura, char Caracteres[10]; }; int main() { Estrutura MinhaVa-
do qual faremos uma pequena reviso agora. Como todos riavelComposta; ... ... ... return 0; }
sabemos, nem todos os dados que precisamos usar podem
ser agrupados em matrizes. Frequentemente usamos da-
dos de diversos tipos diferentes, com tamanhos diferen-
tes. Para tipos de dados de diferentes tamanhos existem 11.1.3 Acessando dados internos
estruturas de armazenamento de dados heterogneos.
O modo de acesso a variveis internas de uma estrutura
O especicador struct usado para esta nalidade. Com feito atravs do operador ponto "., porm, quando usa-
ele podemos criar tipos que armazenam dados compostos mos ponteiros para guardar o endereo de uma estrutura
por agrupamentos de outros tipos primitivos da lingua- usamos o operador seta "->". Vejamos um pequeno tre-
gem. Geralmente, os dados so armazenados de forma cho de cdigo:
a facilitar a identicao de cada campo de dados que
pretende-se manter, para isso usamos nomes para cada Estrutura st; Estrutura *pst; st.Inteiro = 200; pst = &st;
campo dentro da estrutura de dados, de forma a ter um pst->PontoFlutuante = 23.976;
meio de acess-la depois.
Estruturas so blocos bsicos de informao e so mani-
pulados de maneira primitiva. Basicamente o compila- 11.2 Estruturas em C++
dor instrui a montagem de um cdigo que manipula-as
de forma a copiar, referenciar e obter posio na mem-
ria. Todas as outras formas de tratar os dados devem ser As estruturas em C++ funcionam de modo anlogo ao
providas pelo cdigo do programa. apresentado em linguagem C. A diferena, a princpio,
notvel entre elas nas duas linguagens que em C++" o
especicador struct no precisa ser escrito quando cria-
mos a estrutura:
11.1.2 Implementao
Em C, para criar uma estrutura de dados chamada st, de-
Para criar um tipo de dados composto heterogneo, basi- claramos:
camente, cria-se uma lista de tipos e nomes de variveis struct Estrutura st;
separadas por ponto e vrgula. Podemos imaginar esta
lista como um bloco de cdigo, em linguagem C, onde
esto presentes apenas as declaraes de variveis. Para Para fazer o mesmo em C++, declaramos:
isso temos a seguinte sintaxe: Estrutura st;
struct Estrutura { <Tipo A> NomeVariavelA; <Tipo A>
NomeVariavelA2; <Tipo A> NomeVariavelA3; <Tipo Este simples detalhe revela uma caracterstica importante
B> NomeVariavelB; <Tipo C> NomeVariavelC; <Tipo das estruturas em C++: Nesta linguagem as estruturas
D> NomeVariavelD; ... ... <Tipo Z> NomeVariavelZ; } so tratadas como tipos primitivos de objetos. Elas tm
[<NomeVariavelComposta>]; caractersticas semelhantes s classes, que veremos nos
captulos subsequentes.
O nome da varivel composta pode ser omitido na de- As estruturas em C++ tambm podem conter funes
clarao da estrutura e depois denido onde for mais alm de dados. Este fato vem da ideia de modelo de ob-

23
24 CAPTULO 11. ESTRUTURAS

jeto que as estruturas mantm nesta linguagem. Objetos Repare que demos valores defaut s variveis. Agora no
devem ter propriedades (variveis) e mtodos (funes estamos no caso de ter p1.name=??? Por mais instncias
membro), por isso temos a possibilidade de criar funes que criemos eles vo ter sempre valores padro.
dentro do corpo das estruturas, com a nalidade de lidar
com os dados que elas mantm. Constructor com argumentos

Termos um constructor sem argumentos um melhora-


11.3 Construtores mento face ao defaut constructor pois agora temos valores
defaut para as variveis membro. Porm seria melhor se
Os construtores so funes que so criadas automatica- consegussemos inicializar as variveis membro com va-
mente sempre que tentamos criar um objeto. Eles funci- lores dados pelo utilizador enquanto o programa estivesse
onam da mesma maneira que construtores de classe. A e a correr. E realmente podemos fazer se passarmos ar-
esses que so criados automaticamente so os chamados gumentos.
de defaut. #include <iostream> #include <string> using namespace
Se escrevermos o cdigo: std; const int MAX = 3; struct Person { string name; int
height; Person() //constructor sem argumentos { name
#include <iostream> #include <string> using namespace
= No name assigned"; height = 1; } Person(string
std; const int MAX = 3; struct Person { string name; int
s, int h) //constructor com 2 argumentos { name = s;
height; }; int main () { Person p1; cout << The persons
height = h; } }; int main () { int metro; string strName;
name is " << p1.name << " and height is " << p1.height
cout << Entre com o nome da pessoa: "; getline(cin,
<< endl; system (pause); return 0; }
strName); cout << Enter height in metro: "; cin >>
metro; cin.ignore(); Person p1(strName,metro); cout <<
O resultado : The persons name is " << p1.name << " and height is "
The persons name is and height is 858993460 << p1.height << endl; system (pause); return 0; }

Aqui criado um defaut constructor no momento em que


criamos a instncia p1 ie com a linha Person p1; Repare que os argumentos do construtor tm de estar na
ordem esperada
Como as variveis membro no foram iniciadas, o valor
de name est vazio e o na varivel height est um valor
qualquer que lixo! Separar o construtor prototype da implementao

Constructor sem argumentos #include <iostream> #include <string> using namespace


std; const int MAX = 3; struct Person { string name;
int height; Person(); //construtor sem argumento Per-
Podemos ter um construtor sem argumentos que ao con- son(string, int); //construtor com dois parmetros, apenas
trrio do defaut constructor designa valores defaut s va- necessrio dizer o tipo dos parmetros o nome no
riveis membro. necessrio) }; Person::Person() { name = No name
struct Person { string name; int height; Person() //cons- assigned"; height = 1; } Person::Person(string s, int h)
trutor sem argumentos { name = No name assigned"; { name = s; height = h; } int main () { int metro; string
height = 1; } }; strName; cout << Enter persons name: "; getline(cin,
strName); cout << Enter height in inches: "; cin >>
metro; cin.ignore(); Person p1(strName, inches); cout
<< The persons name is " << p1.name << " and height
O nome do construtor sempre igual ao nome da
is " << p1.height << endl; system (pause); return 0; }
estrutura, sem exceo.

O construtor no retorna qualquer valor, sem exce-


o Vamos ver a funo main(): declarmos 2 variveis
uma int e outra string. Pedimos para a pessoa escre-
ver o nome e colocmos o valor na varivel string,
Refazendo o nosso exemplo
depois pedimos a altura e colocmos na varivel int.
#include <iostream> #include <string> using namespace Depois chammos o construtor com dois argumen-
std; const int MAX = 3; struct Person { string name; int tos e passamos as variveis anteriores como argu-
height; Person() { name = No name assigned"; height = mentos. Por m mandmos imprimir os valores das
1; } }; int main () { Person p1; cout << The persons variveis membro da estrutura.
name is "<< p1.name << " and height is " << p1.height
<< endl; system (pause); return 0; } Repare que para denirmos fora o construtor recor-
remos ao operador scope ::
11.3. CONSTRUTORES 25

Person::Person() Person::Person(string s, int h)

Repare que no prototype dos construtor apenas ti-


vemos de dizer o tipo dos parmetros
Captulo 12

Operadores

Os operadores realizam, como o nome sugere, operaes 12.2.1 Entendendo o operador


entre dois tipos de dados. Existem muitos operadores,
mas citaremos aqui os fundamentais e, conforme as ne- Basicamente, temos dois tipos de implementao para
cessidades dos tpicos posteriores, citaremos todos os de- operadores, o tipo global e o tipo membro de classe. Os
mais. dois tipos so usados regularmente nas implementaes
mais comuns. Analisaremos o tipo global, uma vez que
ainda no temos uma noo de classes suciente para
abordar o tipo membro de classe.
12.1 Compatibilidade
Digamos que temos uma estrutura ponto, como denida
abaixo:
Os operadores padres da linguagem C podem ser usa-
dos de forma semelhante na linguagem C++. Aliadas s struct Ponto { int x; int y; };
funcionalidades tradicionais do C podemos criar opera-
es diferentes para os operadores. Esta funcionalidade Uma vez que tenhamos denido um ponto, nada mais na-
conhecida como sobrecarga de operadores e ser descrita tural que queiramos somar, subtrair, enm operar, pon-
em captulo posterior. tos diferentes de acordo com nossas necessidades. Para
isso podemos criar operadores para fazer isso, da seguinte
forma:

12.2 Como C++ interpreta os ope-


radores Observamos a quantidade de parmetros, o retorno
e a forma de chamar o operador que queiramos de-
nir e criamos uma funo que execute a operao
Para dar uma base de entendimento para a sobrecarga de desejada;
operadores iremos introduzir o modo como o compilador
C++ entende os operadores. Este modo de interpretar os
operadores implementado para dar suporte aos recursos Inserimos o cdigo da referida funo dentro de uma
de POO da linguagem. O entendimento do modo de fun- chamada de operador, usando a palavra reservada
cionamento do mecanismo de compilao pode diminuir operator seguida do operador que desejamos de-
as dvidas que surgem no estudo de operadores em C++. nir:
importante entender que a linguagem deve servir de
base para a criao de entidades de dados autnomas e
operveis. Logo, o compilador deve ser generalista ao Ponto operator+ ( Ponto a, Ponto b ) { Ponto soma;
enxergar operaes com tipos primitivos e tipos criados soma.x = a.x + b.x; soma.y = a.y + b.y; return soma; }
pelo programador (classes). Por estes fatores, o compila-
dor utiliza-se de uma interface funcional para implemen- E assim, o operador entendido como uma funo, sendo
tao dos recursos de operadores. a sobrecarga um processo de denio da operao a
Os operadores so tratados como funes, de forma a ser executada. Recebe esse nome porque todo operador
possibilitar a alterao do seu comportamento em deter- j existe e a denio de uma nova funcionalidade ape-
minados casos. Os operandos so tratados como argu- nas adiciona (sobrecarrega) as habilidades anteriores do
mentos de funes, enquanto que o resultado da operao operador. Embora isto seja comum, bom lembrar que
tratado como retorno da funo do operador. Esta inter- operaes de tipos primitivos no podero ser modica-
face faz com que possamos programar o comportamento das, restando apenas a funcionalidade de criar operadores
das operaes e alter-las quando nos seja conveniente. para nossos tipos (classes).

26
12.3. OPERADORES ARITMTICOS 27

12.2.2 Os argumentos os nmeros reais (em ponto utuante) dos deles, ento
sim obter 1.5.
Agora vejamos como os argumentos so vistos pelo com- O motivo que h 2 tipos de diviso: a inteira e a decimal.
pilador durante a chamada ao operador. Essa sintaxe,
muitas vezes, confunde iniciantes, mas bastante intui-
tiva. Veja: Diviso inteira e o operador mdulo
c = a + b;
A diviso inteira retorna o quociente da diviso sem a
Consideremos que a,b,c so pontos. Em termos gerais, parte fracionria. Isso ocorre porque a linguagem efetua
qualquer operador binrio (com dois argumentos) de- a diviso enquanto o resto for maior que o divisor (logo,
nido em escopo global, receber a e b como primeiro e a diviso nunca apresentar parte fracionria).
segundo argumento da funo que dene o operador.
Para obter o resto da diviso, voc pode usar o operador
Podemos ver a chamada da seguinte forma: mdulo (%). Esse operador retorna, em vez do quociente,
c = operator+( a, b ); o resto da diviso inteira. por isso que no nosso exemplo
51 % 5 resultou em 1, pois 5x10 + 1 = 51, onde 5 o
divisor, 10 o quociente, 1 o resto e 51 o dividendo.

12.3 Operadores aritmticos Diviso real

Operadores aritmticos so utilizados para efetuar ope- A diviso real aquela efetuada entre tipos ponto utu-
raes matemticas entre dados. So 5 operadores arit- ante ou entre ponto utuante e inteiros/caracteres. Isso
mticos em C++: efetuar a diviso at que o resto seja zero, ou quando o
resto repetir-se indenidamente (no caso de dzimas pe-
#include <iostream> using namespace std; int main() { ridicas como, por exemplo, 10/3).
int soma = 5 + 5; // o operador '+' realiza somas. double
subtracao = 5 - 5; // o operador '-' efetua subtrao. Se quisermos que a diviso entre inteiros retorne a di-
oat multiplicacao = 5.1 * 0.5; // o operador '*' efetua viso real, deveremos efetuar uma converso explcita,
multiplicao. char divisao = 100 / 2; // o operador '/' conforme o exemplo:
efetua diviso. int modulo = 51 % 5; // retorna o resto da int num = 3; int num2 = 2; cout << Resultado: " <<
diviso inteira. cout << Resultados: " << soma << ", " (oat) num/num2 << endl; // o resultado foi convertido
<< subtracao << ", " << multiplicacao << ", " << divisao para ponto utuante explicitamente.
<< ", " << modulo << endl; }

A sada desse programa gera no console o seguinte:


Resultados: 10, 0, 2.55, 2, 1.
O quarto resultado '2' pois 50 o cdigo decimal deste
caracter.

12.3.1 Tipo de retorno

Voc pode realizar operaes aritmticas, obviamente,


entre nmeros. Como dito no tpico anterior, voc tam-
bm pode realizar operaes aritmticas com os tipos
char e wchar_t.
O retorno da operao ser tambm um nmero (real, in-
teiro ou at mesmo um caracter, conforme os tipos dos
operandos).

12.3.2 Diviso inteira e diviso real

Existe, para a linguagem, diferena entre uma diviso en-


tre nmeros inteiros e entre nmeros reais (ponto utu-
ante). Se voc zer a diviso entre os inteiros 3 e 2, o
resultado no ser 1.5, ser 1. J se zer a diviso entre
Captulo 13

Deciso e controle de uxo

28
Captulo 14

Controle de uxo em C++

Aqui vamos criar funes que nos permitam alterar a lei- variavel; if(variavel == 5) cout << A varivel igual a
tura de execuo do cdigo. Ou seja, j dissemos que a 5"; return 0; }
leitura de execuo do cdigo de cima para baixo (l a
primeira linha de cdigo executa, l a 2 linha --- exe- Pode-se usar valores booleanos:
cuta,..e por a adiante)
bool variavel; if(variavel) //if ser executado se booleano
O que agora vamos fazer e criar mecanismos para alterar for verdadeiro, como no lhe foi atribudo valor, falso
esse leitura sequencial e permitir: cout << varivel verdadeira!";

Execuo de cdigo de acordo com a condio


Ou, se booleano tiver que ser falso para ocorrer a execu-
Repetio de execuo de cdigo sujeito a condio o:
if(!variavel) // O ! faz com que s haja execuo da pr-
Saltar linhas de cdigo
xima linha se varivel for falsa cout << varivel falsa!";

Mas se voc quiser que o computador execute vrias li-


14.1 Deciso em C++ nhas aps o if se este for verdadeiro? Basta usar chaves:

Em C++ os mtodos de tomada de deciso presentes na if(variavel) { cout << A varivel verdadeira...\n"; cout
linguagem C esto disponveis para as tarefas mais corri- << E continua executando << at que seja fechado o
queiras que o programa deve executar. Alm desta forma if << " com o }"; }
de controle de decises, C++ prov certas funcionalida-
des relacionadas a objetos que modicam a forma como o
cdigo estruturado e, por consequncia, decidem como
o programa deve se comportar em determinadas situa- else
es. Examinemos os mtodos bsicos e analisemos de
forma simples as estruturas de deciso presentes no mo- tambm possvel usar o bloco else para o computador
delo de programao orientado a objetos, para entender executar vrias linhas de cdigo caso uma condio tenha
como isso poder nos ajudar a tornar o cdigo mais bem o valor booleano falso. Por exemplo:
construdo.
if(temperatura < 20) { cout << Est frio"; } else { cout
De modo geral, a maioria das linguagens de programao << Est calor"; }
existentes utiliza-se das estruturas if-else ou switch-case.
Assumindo que a varivel temperatura tem tipo inteiro
(int), se esta contiver um valor, por exemplo, 20, ser
14.1.1 if-else
apresentada na tela a mensagem Est calor, uma vez
que 20 < 20 uma expresso contradio, logo tem o
if
valor booleano falso.
Se voc quer que o software execute um determinado co- Podemos ainda encadear vrios else, e obter ainda mais
mando somente em certas situaes, utilize if para deter- possibilidades:
minar isto. O programa vai, ento, executar a primeira if(deposito < 20) { cout << Depsito de gasleo inferior
linha de cdigo aps o if, se a declarao entre parnte-
a 20%"; } else if(deposito < 50) { cout << Tem menos
ses for verdadeira. Exemplo: de metade do depsito"; } else { cout << Ainda tem
#include <iostream> using namespace std; int main(void) meio depsito ou mais"; }
{ int variavel; cout << Escreva um numero: "; cin >>

29
30 CAPTULO 14. CONTROLE DE FLUXO EM C++

Desta forma, conseguimos distinguir o nvel de depsito 14.1.3 Operador condicional "?"
de gasleo de um carro em 3 nveis diferentes. Para dis-
tinguir por mais nveis, bastaria acrescentar mais } else A sintaxe :
if(...condio...) { para distinguir os diferentes patama-
res. [Relational expression] ? [statement if true] : [sta-
De notar que, cada caso avaliado individualmente, por tement if false]
ordem. Isto , primeiro seria vericado se o depsito tem
menos de 20% de gasleo; apenas se esta condio for Ou seja, este operador testa a expresso relacional e se o
falsa que o computador avalia a segunda condio, para resultado for verdadeiro executa logo a 1 armao caso
vericar se o depsito tem menos de 50% de gasleo, e contrrio executa a segunda.
por ainda adiante.
ou seja isto no mais do que um if-else.
H quem goste de usar este operador porque poupa es-
14.1.2 switch crita, mas acho que no vale a pena!

O switch muito parecido com o if-else. Apenas a sintaxe #include <iostream> using namespace std; int main(void)
e construo diferente { int num; cout << Enter a whole number: "; cin >>
num; cout << The number is " << (num % 2 == 0 ?
#include <iostream> using namespace std; int main(void) even : odd) << endl; return 0; }
{ char grade; cout << Enter your grade (A to F): ";
cin >> grade; switch (grade) { case 'A': cout << Your
average must be between 90 - 100"<< endl; break; case Notar que o operador condicional exige 3 operandos.
'B': cout << Your average must be between 80 - 89"<< vamos fazer uns exerccios:
endl; break; case 'C': cout << Your average must be
between 70 - 79"<< endl; break; case 'D': cout << Your 7==5 ? 4 : 3 // returns 3, since 7 is not equal to 5.
average must be between 60 - 69"<< endl; break; default:
cout << Your average must be below 60 << endl; } 7==5+2 ? 4 : 3 // returns 4, since 7 is equal to 5+2.
return 0; }
5>3 ? a : b // returns the value of a, since 5 is greater
than 3.
Cada um dos casos tem de ser uma constante (no a>b ? a : b // returns whichever is greater, a or b.
pode alterar durante a vida do programa), neste
exemplo A, B,

O defaut serve para a condio de todas as avaliaes 14.2 O Comando goto


dos casos anteriores der falsa. ( tipo o else)
O goto realiza um salto para um local especicado. Este
O break serve para terminar o switch, caso contr-
local determinado por um rtulo. Portanto pode ser em
rio se num dado case fosse verdadeiro, iria executar
qualquer parte do programa.
todos os statementes mesmo de outros cases at ter-
minar o switch. nome_do_rtulo: .... goto nome_do_rtulo; ....
// goto loop example #include <iostream> using names-
Aqui para cada caso no necessitamos de {} se ti- pace std; int main () { int n=10; loop: cout << n << ", ";
vermos mais do que 2 statements. n--; if (n>0) goto loop; cout << FIRE!"; return 0; }
o if-else mais forte do que o switch por que permite
fazer coisas como: Repare no rtulo.
Nota: Evite o uso de goto quando for possvel usar es-
if (apples == oranges) do this; else if (sales >= 5000) do truturas principais, porque pode tornar o cdigo ilegvel.
that; Esse comando deve ser usado em ltimo caso, como sair
de loops aninhados.
Para alm do ponto j dito de os casos serem obri-
gatoriamente constantes, no switch

Tambm posso utilizar operadores lgicos no switch 14.3 Terminando o programa


switch (age >= 18 && citizen == true) { case true: cout Esta funo denida com a biblioteca cstdlib
<< You are eligible to vote"; break; case false: cout << (c+std+lib) O propsito da funo terminar com
You are not eligible to vote"; } o programa com um especco cdigo de sada O
prottipo :
14.3. TERMINANDO O PROGRAMA 31

int exit (int exitcode);

Esta funo usada por alguns sistemas operativos e po-


dem ser usadas para chamar programas. Por conveno
o cdigo 0 se sada signica que o programa terminou
normalmente, como previsto, se vier com outro nmero
signica que houve um erro e algo de inesperado sucedeu.
Captulo 15

Estruturas de repetio

Laos (loops em ingls), ou estruturas de repetio, so 15.2 Do-While


comandos existentes nas linguagens de programao des-
tinados a executar uma ou mais instrues quantas ve- O lao do-while um while invertido, onde voc coloca
zes forem necessrias. Cada ciclo de um loop chamado as instrues a serem repetidas antes da vericao da
de iterao. Podemos ter tambm loops dentro de outro condio de execuo. Isso signica que os comandos do
loop. lao sero executados ao menos uma vez.

15.2.1 Sintaxe

15.1 While do { comando; } while (condio);

O while, enquanto em ingls, um lao que ordena o Onde condio a condio de execuo do lao do-
computador a executar determinadas instrues enquanto while. Os comandos pertencentes ao lao somente dei-
uma condio for verdadeira. Isso faz com que um co- xaro de se repetir quando a condio for falsa.
mando seja executado uma vez a cada vericao da con- O algoritmo abaixo mostra como seria o algoritmo exem-
dio. De modo geral o comando sempre deve ser elabo- plo usado na seo do lao while convertido para o uso
rado de forma que se leve a condio de execuo a ser do lao do-while.
falsa em algum momento, de forma a interromper o lao
#include <iostream> using namespace std; int main() {
para que o resto do programa entre em execuo.
int contador; // Declara a varivel contador. contador=1;
// contador recebe o valor 1. do { cout << contador <<
endl; // Imprime contador. contador++; // Incrementa
contador em uma unidade. } while (contador<=10); //
15.1.1 Sintaxe Enquanto contador for menor ou igual a 10. return 0; }

while (condio) comando;


15.3 For
Onde condio a condio de execuo do lao while.
O cdigo abaixo mostra o uso do lao while para imprimir Como o uso de uma varivel como contador nos laos
na tela do nmero 1 ao nmero 10. Perceba o uso de algo frequente, foi criado um outro lao que traz em sua
uma varivel inteira intitulada contador. Esta varivel estrutura campos para abrigar os comandos de atribuio
utilizada para armazenar um valor a ser impresso bem de valor inicial e incremento/decremento do contador. O
como participar da condio de execuo do lao. Assim nome deste lao for, para em ingls.
que a varivel atingir o valor 11 o programa segue para o
comando logo aps o lao.
15.3.1 Sintaxe
#include <iostream> using namespace std; int main() {
int contador; // Declara a varivel contador. contador=1; for ([iniciao]; [condio]; [incremento]) comando;
// contador recebe o valor 1. while (contador<=10) //
Enquanto contador for menor ou igual a 10. { cout <<
contador << endl; // Imprime contador. contador++; // Onde:
Incrementa contador em uma unidade. } return 0; }
iniciao: campo destinado para qualquer comando

32
15.4. DICAS 33

que deve ser executado, uma nica vez, logo no in- em seguida, ele assumir que o comando imediatamente
cio do lao. abaixo o nico que deve ser repetido.

condio: campo destinado para a condio de pa- Exemplo 1:


rada. Esta condio vericada logo no incio do while (condio) comando1; // Este comando faz parte
lao, imediatamente aps a concluso do parme- do lao. comando2; // Este comando no faz parte do
tro1 e a cada passo quando o <comando> execu- lao.
tado.

incremento: campo destinado para qualquer co- Exemplo 2:


mando que deve ser executado todas as vezes em while (condio) { comando1; // Este comando faz parte
que o lao nalizar seu ltimo comando, em todas do lao. comando2; // Este comando faz parte do lao. }
as suas repeties.

O algoritmo abaixo mostra o uso do lao for manipulando


15.4.2 O Comando break
a varivel inteira contador de maneira imprimir uma con-
tagem de 1 at 10. Esse uso do lao for o mais comum
O que o break faz quebrar a execuo para fora do bloco
pois possibilita uma repetio de comandos de nmero
de cdigo onde ela est presente
xo, dez no algoritmo em questo.
#include <iostream> using namespace std; int main(void)
#include <iostream> using namespace std; int main()
{ int num; char choice; bool quit = false; while (true)
{ int contador; // Declara a varivel contador. for
{ cout << Enter a positive number: "; cin >> num;
(contador=1; contador<=10; contador++) // Inicia o
if (num > 0) break; else { cout << Number must be
lao. cout << contador << endl; // Imprime contador.
positive; try again (Y/N): "; cin >> choice; if (choice !=
return 0; }
'Y') { quit = true; break; } } } if (quit == false) cout
<< The number you entered is " << num << " "; else
importante deixar claro que nenhum dos trs parme- cout << You did not enter a positive number"; return 0; }
tros utilizados no lao for obrigatrio. Caso no haja
necessidade de utilizar um ou mais deles, basta deixar seu
O break faz com que a execuo do programa continue
espao em branco. Como exemplo temos o algoritmo a
na primeira linha seguinte ao loop ou bloco
seguir, que demonstra um lao innito usando for:
#include <iostream> using namespace std; int main() {
for (;;) cout << Eu sou um lao innito. << endl; return 15.4.3 O Comando continue
0; }
Esta instruo bem parecida com o break, mas algo di-
ferente. Pois em vez de mandar a execuo para fora do
A ausncia do 2 parmetro signica loop innito: bloco manda-a para a avaliao do loop. Ou seja faz sal-
for (int num =1; ; num++) { cout << num << " "; } tar uma determinada iterao do loop, enquanto o break
faz acabar o loop
Isto vai colocar um valor a mais no num indenidamente.
#include <iostream> using namespace std; int main(void)
Ausncia do 3 parmetro:
{ int num, counter = 0, total = 0; cout << How many
for (int num=1; num <= 10; ) { cout << num << " "; items do you want to buy: "; cin >> num; while (coun-
num++; } ter++ < num) { if (counter % 13 == 0) continue; total
+= 3; } cout << Total for " << num << " items is $" <<
total; return 0; }
15.4 Dicas
Neste exemplo quando o conter for mltiplo de 13, a ins-
15.4.1 Bloco de Comandos truo seguinte saltada total+=3

Em muitos casos, os laos devem repetir dois ou mais


15.4.4 Incrementar/decrementar
comandos. Para isso, necessitamos criar um bloco de co-
mandos contendo todas as instrues a serem repetidas. Aqui vamos voltar a um tpico anterior que foi abordado
A criao de um bloco de comandos simples, basta co- nos operadores Temos
locar todos os comandos entre chaves { }. Os algoritmos
de exemplo dos laos while e do-while fazem uso de um a=a+1 equivalente a ter a+=1 e ainda a ter a++
bloco de comandos.
Caso o lao no encontre a abertura de um bloco logo Mas isto tudo s no caso do incremento ser 1.
34 CAPTULO 15. ESTRUTURAS DE REPETIO

Podemos ter ++a ou ainda a++. Eles so parecidos mas


diferentes, a questo do prexo e ps-xo. A diferena
que

O prexo, faz o incremento ainda durante a instru-


o
O ps-xo faz o incremento quando se passa para a
instruo seguinte.

#include <iostream> using namespace std; int main(void)


{ int num = 2; cout << num << \n; cout << ++num
<< \n; cout << num++ <<\n; cout << num << \n;
return 0; }

Portanto

int num = 5;

cout << (++num == 5);

15.5 Exerccios
Crie um programa que d o fatorial de um nmero:
#include <iostream> using namespace std; int main(void)
{ int num, counter, total = 1; cout << Enter a number:
"; cin >> num; cout << The factorial of " << num << "
is "; for (int counter = 1; counter <= num; counter++)
total *= counter; cout << total; return 0; }

Crie um programa para o utilizador adivinhar um nmero


de 0 a 3. D 3 hipteses para adivinhar. No caso de
acertar antes de chegar ao m das 3 hipteses termine.
#include <iostream> using namespace std; int main(void)
{ int num, counter, secret = 3; cout << Guess a number
between 1 and 10\n"; cout << You have 3 tries\n";
for (int counter = 1; counter <= 3; counter++) {
cout << Enter the number now: "; cin >> num;
if (num == secret) { cout << You guessed the secret
number!"; break; } } cout << Program over"; return 0; }

Criao de menu.
#include <iostream> using namespace std; int main
() { int i; do { cout << "\n\nEscolha a fruta pelo
numero:\n\n"; cout << "\t(1)...Mamao\n"; cout <<
"\t(2)...Abacaxi\n"; cout << "\t(3)...Laranja\n\n"; cin
>> i; } while ((i<1)||(i>3)); switch (i) { case 1: cout <<
("\t\tVoce escolheu Mamao.\n); break; case 2: cout
<<"\t\tVoce escolheu Abacaxi.\n"; break; case 3: cout
<< ("\t\tVoce escolheu Laranja.\n); break; } return(0); }
Captulo 16

Funes

Funo, do latim functio, onis, representa na computa- A funo no pode ser overloaded apenas com diferentes
o, um pequeno algoritmo com uma funo simples e tipo de retorno de funo (ie, uma funo retornar ints e
bem denida. como se cada funo fosse um micro a outra retornar oats) ento os parmetros que interes-
programa, ou um tijolo na construo do programa prin- sam.
cipal. O uso de funes facilita muito o desenvolvimento, #include <iostream> using namespace std; void Con-
pois, divide o problema principal em pequenos proble- vertFToC(double f, double &c); void ConvertFToC(oat
mas mais simples. Essa tcnica se chama, Dividir para f, oat &c); void ConvertFToC(int f, int &c); int main()
conquistar. { double df, dc; oat , fc; int i_f,i_c; //if is a reserved
A experincia mostra que o uso de funes facilita e ace- word df = 75.0; = 75.0; i_f = 75; // The compiler resol-
lera a criao e manuteno de sistemas. ves the correct // version of ConvertFToC based on // the
Todo programa em C++ tem pelo menos uma funo, o arguments in each call cout << Calling ""double"" ver-
sion << endl; ConvertFToC(df,dc); cout << df << " ==
main. Veja o exemplo do programa em C++:
" << dc << endl << endl; cout << Calling ""oat"" ver-
#include <iostream> //Biblioteca com funes de en- sion << endl; ConvertFToC(,fc); cout << << " == "
trada e sada de dados using namespace std; int main << fc << endl << endl; cout << Calling ""int"" version
(void) //Funo principal do programa { cout << Ol << endl; ConvertFToC(i_f,i_c); cout << i_f << " == "
mundo!"; //cout tambm uma funo, e precisa ser << i_c << endl << endl; system (pause); } void Con-
importada da biblioteca iostream //Esta funo main vertFToC(double f, double &c) { cout << In ""double""
retorna um valor int, ou inteiro, por isso faz a operao version << endl; c = (f - 32.0) * 5. / 9.; } void ConvertF-
de retornar 0 return 0; } ToC(oat f, oat &c) { cout << In ""oat"" version <<
endl; c = (f - 32.0) * 5. / 9.; } void ConvertFToC(int f,
Do exemplo Ol mundo, vemos que toda funo em C++ int &c) { cout << In ""int"" version << endl; c = (f -
tem um nome. O nome de uma funo junto com o tipo 32) * 5. / 9.; }
de dados que retorna chamado assinatura da funo. O que que acontece se tivermos um n diferente de ar-
int main (void) //Assinatura da funo main gumentos entre a chamada e a denio?
A soluo aqui proposta quando no sabemos a quan-
Essa assinatura informa que a funo de nome main re- tidade de parmetros que a funo vai ser chamada ou
torna na sua execuo um valor do tipo int, ou inteiro, mesmo a tipologia desses argumentos, o que se sugere
e recebe void como parmetro. Receber void signica fazer vrias denies para a funo e dar a todas elas o
que a funo no recebe parmetro, se a funo retorna mesmos nome, que o compilador vai saber escolher a de-
void, signica que no retorna nada. Algumas funes nio correcta atravs do n e tipologia de argumentos.
no precisam retornar nenhum valor para funcionar, ape- Entretanto, por boa prtica, as funes no devem ser so-
nas realizar alguma ao. brecarregadas se zerem operaes distintas.

16.1 Sobrecarga de funes 16.2 Parmetros default (padro)


Em C++ duas funes podem ter o mesmo nome se:
Pode acontecer que tenhamos que declara varia vezes o
mesmo valor como parmetro de uma funo. Para sim-
Tiverem um n diferente de parmetros e/ou plicar a chamada a funes que variam pouco podemos
Se os parmetros forem de tipos diferentes (ints o- denir uma parmetro default.
ats,..) #include <stdio.h> #include <stdlib.h> /*-----------------

35
36 CAPTULO 16. FUNES

------------Cabealho--------------------------------*/ /*De-
nimos uma funao*/ void function(int a,int b, int c
= 100 ) { printf(Meu Primeiro argumento :%d\n,a );
printf(Meu Segundo argumento :%d\n,b ); printf(Meu
terceiro argumento :%d\n,c ); getchar(); } int main
(void) { function( 10, 30); /* Agora use a funo assim e
veja o que acontece */ // function( 10,30,999); }
Os parmetros por default devem ser os ltimos da lista,
ou seja, mais direita. O parmetro padro deve ser es-
pecicado no prottipo e no na declarao da funo.
Captulo 17

Referncias de dados

17.1 Variveis de referncia jamais alterar o valor do seu argumento x.


Diferentemente da linguagem C, a chamada a uma fun-
Em C++ podemos criar variveis que podem ser uma o em C++ pode alterar o valor de uma varivel denida
alternativa para os ponteiros em algumas situaes. A antes da chamada da funo, mesmo sem esta varivel ser
vantagem de no usar diretamente o endereo (valor de explicitamente passada como um ponteiro. Este modo
ponteiro) em situaes onde no precisamos lidar direta- chamado de passagem por referncia. Em termos mais
mente com valores de memria torna a programao mais gerais, signica a passagem da varivel propriamente dita,
segura e simplicada. Podemos deixar as operaes com para o corpo interno da funo com outro nome, aquele
ponteiros apenas para quando for estritamente necess- denido na lista de parmetros da funo.
rio.
Em C++, uma funo pode ser chamada na forma acima e
Variveis de referncia podem ser criadas para dar um alterar o valor das suas variveis. Para isso basta declar-
nome diferente para as variveis que j existem no pro- la como:
grama, ou para passar a varivel para dentro do corpo de
int function(int & x) { x--; return x; }
uma funo. Observemos, inicialmente, um caso sim-
ples:
Temos em C++ o operador & que se comporta diferente-
int a = 10; int &b = a; b = 20;
mente de C, tendo uma funo a mais, a de criar variveis
de referncia:
Neste trecho de programa, criamos uma varivel de refe-
rncia b para a varivel a, o que signica que criamos ou- &x quando usado no cdigo retorna o pointero para
tro nome para a varivel a. De fato, b a prpria varivel o endereo de x;
a com outro nome, apenas isso. Desta forma, podemos
alterar o valor de a usando b. &x quando usado na declarao de varivel, cria
uma referncia;
&x quando usado como parmetro na declarao de
17.2 Passagem de parmetros uma funo faz com que suas chamadas transra o
argumento/parmetro passando-o de forma similar
Na linguagem C, durante a chamada de uma funo, os a passagem de seu pointero. (Passagem por refern-
argumentos (parmetros) tm seus valores copiados para cia).
a rea de processamento da funo. Depois que os mes-
mos foram usados dentro do bloco de processamento da Em termos semnticos, ao passar a varivel para uma
funo, eles so descartados. A funo retorna o proces- funo onde o parmetro uma referncia, o endereo
samento para o bloco que a chamou trazendo apenas o da varivel atribudo ao endereo do parmetro. Desta
valor de retorno. A nica maneira de fazer com que a forma, o parmetro a mesma varivel passada, no tre-
funo modique o valor de alguma varivel denida no cho de cdigo onde a funo foi invocada, assumindo um
bloco de programa que a chamou pass-la por um pon- nome diferente dentro da funo.
teiro com o seu endereo.
Vejamos um exemplo usando a funo anterior:
Vejamos o fragmento de cdigo seguinte: int m = 4; function(m); cout << m << endl;
int f( int x ) { x--; return x; } int main() { int a = 10; int
b; b = f(a); ... ... O cdigo anterior imprime na sada padro o valor 3.
Acompanhando o uxo de execuo vericamos o se-
Em C, a menos que o programador seja bem malicioso guinte: Depois que a varivel m includa na chamada
e faa manipulaes de memria arriscadas, a funo f da funo o seu nome muda para x e o programa passa

37
38 CAPTULO 17. REFERNCIAS DE DADOS

a ser executado dentro da funo, onde a varivel de- mente chamada como Swap(a, b) do que Swap(&a, &b);
crementada. Portanto, quando a execuo retorna para o assim, mais simples declarar a funo usando refern-
corpo principal a varivel estar decrementada. cia:
#include <iostream> using namespace std; void Swap
(int &i,int &j) { int t=i; i=j; j=t; } int main () {
17.3 Exemplo: alterando o valor da int a,b; a=5; b=10; cout<<a<<"\t"<<b; Swap (a,b);
varivel usando referncia cout<<a<<"\t"<<b; system (pause); return 0; }

#include <iostream> using namespace std; int main() {


int val = 1; int &ref = val; cout << val is " << val <<
endl; cout << ref is " << ref << endl; cout << Setting 17.5 Comparao entre passagem
val to 2 << endl; val = 2; cout << val is " << val << por referncia e ponteiros
endl; cout << ref is " << ref << endl; cout << Setting
ref to 3 << endl; ref = 3; cout << val is " << val <<
Para exercitar vamos criar um novo problema: Criar um
endl; cout << ref is " << ref << endl; system (pause);
funo que duplique qualquer valor colocado pelo utili-
return 0; }
zador:
Ou seja nestes dois cdigos temos uma passagem por re-
Como se viu conseguimos alterar o valor de val alterando
ferncia e outro por endereo. Com diferenas:
o valor de ref.
Existe apenas umas restries para o seu uso: Na chamada da funo (dentro do main() )

Teremos de inicializar e no momento da declarao doubleIt(num); // by reference doubleIt(&num); // by ad-


teremos de atribuir de imediato o valor (se no - dress
zermos isso gerar um erro de compilao)
As referncia no podem ser reatribudas, ou seja no No prototype da funo (conrmar o ponto e vir-
exemplo anterior tinha gula)

int &ref = val; se mais tarde no cdigo tentar-se fazer int void doubleIt(int&); // by reference void doubleIt(int*);
&ref=m; (sendo m uma varivel j declarada e iniciada // by address
por hiptese) o que acontece que a 2 instruo com-
pletamente ignorada e camos sempre com a primeira. Na function header
A vantagem real das referncias que quando elas so
void doubleIt (int& x) // by reference void doubleIt (int*
usadas para passar valores para as funes elas providen-
x) // by address
ciam uma maneira de retornar valores das funes.
Vejamos o exemplo dentro do body function (dentro da prpria funo)
#include <iostream> using namespace std; int main() {
int val1 = 10; int val2 = 20; int &ref = val1; cout << x *x
val1 is " << val1 << endl; cout << val2 is " << val2 << Podemos pensar que passando por referncia parece ser
endl; cout << ref is " << ref << endl; ref = val2; //What muito mais simples do que passado por address.
does this do? cout << endl << ref = val2 << endl; cout
<< val1 is " << val1 << endl; cout << val2 is " << val2 Na verdade existem certas funes da biblioteca que s
<< endl; cout << ref is " << ref << endl; val2 = 30; cout permitem a passagem por address.
<< endl << Setting val2 = 30 << endl; cout << val1 is
" << val1 << endl; cout << val2 is " << val2 << endl;
cout << ref is " << ref << endl; system (pause); return
0; }

17.4 Exemplo: Swap


O exemplo abaixo mostra uma forma muito comum de
usar referncias. A instruo swap, que tem por obje-
tivo trocar os valores de duas variveis, mais natural-
Captulo 18

Entrada e sada de dados

18.1 Entrada e sada 18.1.1 Buer

Aqui vamos dar incio ao estudo de recursos que possibi- Para entendermos um pouco mais sobre Buer, se faz
litaro inserir dados e fazer reporte da falta deles. necessrio recordar um pouco sobre o funcionamento da
memria e suas operaes relacionadas a Buer.
No C++ a entrada e sada podem ser feitas atravs da bi-
blioteca iostream. Para podermos us-la deveremos co- Buerizao um meio de sincronizao entre dispositi-
locar a linha de cdigo: #include <iostream> vos de velocidades diferentes, tais quais memria e dispo-
sitivos de armazenamento mecnicos, como discos mag-
A estrutura de comunicao com o meio externo em nticos. Para evitar que as operaes do dispositivo mais
modo texto composta por um conjunto de objetos. Es- lento interram no desempenho do programa pode-se fa-
tas, em conjunto com operadores e funes de formata- zer com que os dados sejam colocados em uma memria
o possibilitam uma forma de comunicao mais intui- mais rpida e depois sejam enviadas ao dispositivo mais
tiva. Devido abstrao de elementos do mundo real por lento a medida que ele tenha disponibilidade para receb-
recursos da orientao a objetos, a forma de entender o los, desta forma temos os seguintes modos de escrita em
cdigo torna-se mais natural. dispositivos de sada:
Na biblioteca iosteam, temos os seguintes objetos:
unbuered signica que qualquer mensagem ou
cin - Este objeto fornece entrada de dados bueri- dados sero escritos imediatamente. o caso da es-
zada atravs do standard input device, o disposi- crita no dispositivo cerr;
tivo de entrada padro; buered - signica que os dados sero mantidos
cout - Este objeto fornece sada de dados bueri- num buer de memria at que o dispositivo de
zada atravs do standard output device, o dispo- destino solicite, ou que um comando de descarre-
sitivo de sada padro; gamento seja executado, ou quando o buer estiver
cheio. O problema que se o programa interrom-
cerr - Este objeto fornece sada de dados no buf- pido antes do buer ser escrito esses dados so per-
ferizada para o standard error device, o disposi- didos.
tivo de erro padro, que inicialmente denido para
a tela.
clog - Este objeto fornece sada buerizada atra- 18.2 cout
vs do standard error device, o dispositivo de erro
padro que inicialmente denido para a tela. cout << hello"; // mostra a palavra hello no
ecr(monitor) cout << 120; // mostra o nmero
O foco de orientao a objetos que a biblioteca iostream 120 no ecr(monitor) cout << hello; // mostra o contedo
confere aos dispositivos de entrada e sada uma das ca- do pedao de memoria a que chamamos de hello no
ractersticas da linguagem C++. Ele est presente na ma- ecr(monitor) cout << hello, tenho " << age<< " anos
neira na qual o cdigo foi idealizado e est formatado, de idade"; /* mostra a primeira string depois vai buscar
modicando a maneira como as partes do sistema de en- o contedo da varivel age de depois a string anos de
trada/sada interagem. Desta forma, as operaes de in- idade */ cout << Primeira frase. "; cout << Segunda
terao entre o usurio e o software tornam-se mais in- frase.\n << Terceira frase."; /* imprime: Primeira
tuitivas para o programador. frase. Segunda frase. Terceira frase. */
O sistema de entrada e sada um exemplo deste modelo
de programao, onde cada entidade fsica ou lgica de O cout (c+out) usado em conjugao com o operador de
entrada e sada representada por objetos cujas operaes insero << permite enviar dados para o stream out
podem ser acessadas diretamente nos programas. que por denio o ecr (monitor).

39
40 CAPTULO 18. ENTRADA E SADA DE DADOS

Ento podemos enviar as constantes, as variveis, a con- 18.3 cin


jugao das duas se nos apetecer, separadas pelo opera-
dor de insero. O objeto cin obtm informao do standard input (que
Temos ainda diversos recursos de formatao atravs de usualmente o teclado). Este objeto est tal como o cout
escapes sequences que detalharemos no tpico logo a declarado no cabealho da biblioteca <iostream>
seguir, o recurso usado aqui concatena as vrias frases na A sintaxe mais comum da instruo para obter dados do
mesma linha. Temos de dizer explicitamente quebra de cin :
linha, atravs do "\n, que faz com que a sequncia logo
aps, seja escrita na prxima linha. cin >> [variable name];
Uma caracterstica muito importante do C++, presente
nas instrues logo acima, o polimorsmo notvel na Aqui temos o operador de extrao ">>" que diz que tudo
operao de apresentao dos dados na sada; Note que os o que o teclado escrever, coloque esses dados na varivel
tipos de dados que so passados para o cout so diversos, que me segue. Este operador consegue at traduzir o con-
ou seja, no importa qual o tipo de dado que ser entregue ceito de dados de fora para dentro.
ao cout, de alguma maneira ele sempre formatar de uma #include <iostream> using namespace std; int main(void)
maneira legvel no monitor. Nos captulos mais adiante { int testScore; cin >> testScore; cout << Your test
veremos como fazer com que tipos de dados diferentes score is " << testScore << "\n"; #ifdef WIN32 system
sejam tratados pelo mesmo objeto. (pause); /* Necessrio apenas para sistemas Micro-
soft, em modo grco. Em UNIX, variantes e
similares use um terminal de texto e esta funo no ser
18.2.1 Escape Sequences necessria. */ #endif return 0; }

H um conjunto de caracteres, ns chamamos de string. H mais um pormenor. O computador est espera de


Mas no exemplo anterior quando usamos o "\n, ns antes um Return (ENTER, ou New Line, ou Espao em
dissemos que o cout com o operador << iria colocar no Branco ) para nalizar a entrada de dados na varivel, at
monitor todos os caracteres que estivessem entre aspas. l o cursor aparece a piscar.
Acontece que existem estas strings especiais chamadas
de escape sequences - que de alguma forma alteram o Bem, na verdade, este ponto muito importante, por
sentido das strings. Existem muitas destas sequncias. As que Vejamos mais a baixo a questo de termos 2 en-
mais conhecidas so estas: tradas.
Escape Sequences (as mais comuns) Pergunta: declaramos uma varivel int testScore e se
colocarmos um valor que no seja um int? Isto no a
mesma situao do captulo anterior porque antes o pro-
\n nova linha muda o cursor para uma linha abaixo grama ainda no tinha compilado, e agora temos entrada
de dados quando o programa j est compilado e a cor-
\r retorno rer/rodar.
Assim se no exemplo anterior colocarmos o nome Je,
\t tabulador muda o cursor para o prximo ponto de que uma string, e o programa est a espera de um int, o
tabulao que acontece que o cin no vai colocar je na varivel
(ele ignora a entrada). E quando o cout chamado ele vai
\v tabulador vertical colocar o valor que est na varivel.
Ento porque que me apareceu o nmero 858993460
\b deleo reversa
quando corri/rodei o programa? que na memria fsica
do computador existem dados da rea onde a varivel est
\f alimentador de pgina alocada sicamente, e quando declarei o testScore o com-
pilador apenas reserva aquela memria mas no apaga o
\a alerta (bipe) faz o computador emitir um sinal so- que l est.
noro
Pergunta: O que que acontece quando inserimos um
nmero maior do que o limite do tipo quando o programa
\' aspas simples (') imprime aspas simples
executar? o caso de overow - estouro de memria,
mas quando o programa corre/roda.
\" aspas duplas (") imprime aspas duplas
Aqui j no temos a questo de dar a volta ao intervalo
\? sinal de interrogao (?) permitido, aqui temos o caso em que vai ser colocado um
nmero estranho. Isto no est perfeitamente explicado.
\\ barra oposta (contrabarra) (\) Chama-se prompt quando dito ao utilizador o que deve
18.3. CIN 41

fazer, o que no deixar como no exemplo anterior o cursor No caso de no conter argumentos apenas ir ler um ca-
a piscar sem o utilizador saber o que fazer. Alm de que ractere, em vez de uma cadeia de caracteres.
temos o problema de overow em execuo, portanto No caso de ter um argumento, ela aceita qualquer tecla
bom que o utilizador cumpra os requerimentos. incluindo o enter. (o que no se passa com o cin e o ope-
De uma maneira muito conveniente, os dados recebidos rador de extrao). Aqui um exemplo
pelo cin so tratados de forma a tornar o processo poli- #include <iostream> using namespace std; int main(void)
mrco, da mesma forma que no caso de cout, assim te-
{ char ch; do { cout << Pressione S ou s para sair, \nqual-
mos como receber os dados da maneira que precisamos, quer outra tecla para continuar: "; cin.get(ch); if (ch !=
ou seja, quando declaramos uma varivel int e a usamos 'S' && ch != 's) cout << Deseja continuar?"<<endl;
para receber um dado do cin, o mesmo convertido na else cout << Saindo..."<<endl; } while (ch != 'S' && ch
entrada para inteiro, quando usamos uma varivel de ou- != 's); #ifdef WIN32 system (pause); #endif return 0; }
tro tipo, a entrada convertida para o tipo da varivel.

Porm se pressionarmos uma tecla de caractere imprim-


18.3.1 Lendo um caractere vel, no conseguiremos inserir o prximo prompt, parece
que houve um salto. Estranho!
Ler um caractere at simples, basta utilizar o objeto cin Para explicar a razo deste novo problema necessitamos
e ser guardado o valor digitado na varivel. de explicar o conceito de buer.
char nivel; cout << Entre um nvel: "; cin >> nivel;
O input buer uma rea de memria que guarda os
caracteres de entrada, por exemplo do telado, at que essa
Porm teremos de pressionar a tecla ENTER depois de entrada seja atribuda pelo cin e o operador de extrao
digitar o caractere. Isto leva a vrias questes. >>, ou por funes como get() ou getline() do objeto cin.

O problema pressione uma tecla para continuar... Quando o loop comea, o input buer est vazio.

#include <iostream> using namespace std; int main(void) Se digitarmos apenas o enter, sendo este o primeiro e
{ char ch; do { cout << Pressione S ou s para sair, nico caractere no imput buer, ele removido do
qualquer outra tecla para continuar: "; cin >> ch; if (ch input buer e atribudo varivel ch, ento o input
!= 'S' && ch != 's) cout << Deseja continuar?"<<endl; buer est vazio na prxima iterao do loop;
else cout << Saindo..."<<endl; } while (ch != 'S' && ch
!= 's); #ifdef WIN32 system (pause); #endif return 0; } Se digitarmos x e enter. Temos 2 caracteres. A
funo get() retira o primeiro caractere do input
buer e atribui varivel ch, mas nisto o carac-
tere nova linha permanece no input buer. Isto
O programa funciona bem se pressionarmos S ou s
faz com que na prxima iterao do loop, no haja
para sairmos;
a oportunidade para entrar com dados.
O programa funciona bem se pressionarmos qual-
Ou seja, na segunda iterao, retirado o caractere nova
quer outra tecla com caractere imprimvel;
linha que cou da 1 iterao - e colocado na varivel
ch. Agora o input buer est vazio.
Mas se pressionarmos a tecla ENTER, nada acon-
tece, o cin continua espera de entrada. A razo
o operador de extrao ">>" ignora os espaos em 18.3.3 cin.ignore()
branco e os caracteres nova linha resultantes do
pressionamento da tecla enter. Uma soluo limpar o caractere nova linha do input
buer antes da chamada da funo getline(). E fazemos
isso usando a funo ignore() do objeto cin.
18.3.2 A funo cin.get()
Esta funo membro tal com a get() e a getline() so
sobrecarregadas, podem ser chamadas sem argumentos,
J tivemos oportunidade para discutir a funo getline
com um ou dois argumentos.
(funo membro) do objeto cin.
Utilizar a funo ignore() sem argumentos, permite que
cin.getline(name,80);
o prximo caractere no input buer seja lido e depois
descartado,- e isto exatamente aquilo que queramos.
Aqui vamos utilizar uma outra funo, a cin.get().
A funo com 1 ou 2 argumentos usada para cadeias de
Esta funo pode ser chamada, tal como a getline(), atra- caracteres.
vs de 3 argumentos, onde o primeiro o array de carac-
teres, mas tambm o pode ser sem argumentos ou ainda Com um argumento, o argumento o nmero m-
apenas um argumento. ximo de caracteres a ser removido do input buer.
42 CAPTULO 18. ENTRADA E SADA DE DADOS

Exemplo: Seu nome : " << name << endl; #ifdef WIN32 system
(pause); #endif return 0; }
cin.ignore(80); // Remove at 80caracteres do input
buer Aqui, neste exemplo, ns no tivemos a oportunidade
de colocar o nome. Quando digitamos o nmero e de-
pois pressionamos a tecla enter, o cin coloca o nmero
Com dois argumentos, o segundo argumento o de- no courseNUm mas o caractere nova linha permanece no
limitador, um caractere que se encontrado, antes do input buer, que ca para o enter name, pois o getline
nmero de caracteres especicado no primeiro pa- l espaos em branco.
ramento, faz com que a remoo pare. Exemplo:
A soluo pode ser:
cin.ignore (80, '\n'); // Remove 80 caracteres se at l #include <iostream> using namespace std; int main(void)
no encontrar o nova linha. { char name[80]; int courseNum; cout << Informe o
nmero do curso: "; cin >> courseNum; cin.ignore();
cout << Informe seu nome: "; cin.getline(name, 80);
Reescrevendo o cdigo anterior utilizando o cin.ignore() cout << O nmero do curso : " << courseNum <<
#include <iostream> using namespace std; int main(void) endl; cout << Seu nome : " << name << endl; #ifdef
{ char ch; do { cout << Pressione S ou s para sair,\n WIN32 system (pause); #endif return 0; }
qualquer outra tecla para continuar: "; cin.get(ch);
cin.ignore(); if (ch != 'S' && ch != 's) cout << Deseja A partir destes exemplos podemos criar umas regras:
continuar?"<<endl; else cout << Saindo..."<<endl; }
while (ch != 'S' && ch != 's); #ifdef WIN32 system
(pause); #endif return 0; } 1. Colocar sempre a funo ignore() depois do cin e do
>>;
Ora este programa funciona muito bem, MAS Razo: O cin>>" deixa sempre o nova linha
Se pressionarmos a tecla Enter para continuar, teremos no input buer. Assim devemos elimin-lo
de fazer isso duas vezes, pois a primeira vez ignorada. com a funo ignore().
A razo: que no existe nada no input buer quando
a funo ignore chamada, por isso que a tecla enter 2. No colocar a funo ignore(), no caso de ser sem
necessita de ser pressionada 2 vezes, colocando um carac- parmetros, depois do getline();
tere nova linha a mais no buer para a funo ignore()
remover. Razo:O getline() remove o caractere nova li-
nha que termina a entrada do input buer,
Se tentarmos modicar isto atravs do if? portanto no necessrio o ignore().
#include <iostream> using namespace std; int main(void)
{ char ch; do { cout << Pressionar S ou s para sair,\n 3. Vericar se temos o caractere nova linha no input
qualquer outra tecla para continuar: "; cin.get(ch); buer depois de utilizar o get(), se tivermos deve-
if (ch != '\n') cin.ignore(); if (ch != 'S' && ch != remos utilizar o ignore().
's) cout << Deseja continuar?"<<endl; else cout <<
Razo: A funo get() com um argumento
Saindo..."<<endl; } while (ch != 'S' && ch != 's);
deixa o caractere nova linha no input buer
#ifdef WIN32 system (pause); #endif return 0; }
se pressionarmos um caractere e o enter. mas
no deixar, se apenas pressionarmos o enter.
Agora sim temos todos os problemas resolvidos e isto portanto necessrio conrmar.
agora funciona!!

18.3.4 cin, cin.get(), cin.getline() 18.4 Entrada de valores para va-


riveis mltiplas
O problema anterior do caractere nova linha permanece
quando usamos o cin, o get() e o getline() juntos num
programa, uma vez que o enter usado para terminar a Podemos fazer com que o programa receba vrios valores
entrada. ao mesmo tempo

#include <iostream> using namespace std; int main(void) cin >> [rst variable] >> [second variable] >> [third va-
{ char name[80]; int courseNum; cout << Informe riable];
o nmero do curso: "; cin >> courseNum; cout << Neste caso o utilizador separa os dados por espaos (o en-
Informe seu nome: "; cin.getline(name, 80); cout << O ter tambm d) e como anteriormente o utilizador fecha
nmero do curso : " << courseNum << endl; cout << utilizando o enter
18.4. ENTRADA DE VALORES PARA VARIVEIS MLTIPLAS 43

#include <iostream> #include <string> using namespace


std; int main(void) { int peso, altura; string nome; cout
<< escreva o seu nome, peso e altura \n separe os
valores por espaos\n"; cin >> nome >> peso >> altura;
cout << o seu nome :" << nome << "\n"; cout << o
seu peso :" << peso << "\n"; cout << a sua altura :
" << altura<< "\n"; #ifdef WIN32 system (pause);
/* Necessrio apenas para sistemas Microsoft, em
modo grco. Em UNIX, variantes e similares use um
terminal de texto e esta funo no ser necessria. */
#endif return 0; }

Note-se que no exemplo anterior poderamos colocar as


3 variveis, mesmo no caso de elas serem de tipos dife-
rentes. Temos de ter ateno na ordem de entrada.
Pergunta: se escrevssemos duas palavras para o nome,
apenas a primeira que apareceria a 2 palavra que estava
separada da primeira para um espao seria colocada na
varivel peso.
Captulo 19

Entrada e sada de dados 2

19.1 Entrada/Sada em cheiros joao, e que tem a extenso .doc que refere usualmente a
documentos do WORD no primeiro caso e com extenso
(arquivos) ".odt do OpenOce no segundo. Outros tipos de exten-
ses podem ser ".xls para documentos EXCEL, ".ods
Nota introdutria: Este capitulo geralmente colocado para planilhas do OpenOce. ou ainda ".cpp para -
uns captulos mais para o m, mas acho por bem que cheiros(arquivos) de cdigos de c++.
se torne as coisas mais interativas, o que possvel in-
troduzindo agora operaes em arquivos, d muito mais
entusiasmo. Encontramos aqui conceitos avanados mas 19.4 Ficheiros(Arquivos) binrios
podero ser deixados para depois se o leitor no quiser
observar o tema neste momento. e tipo texto
Existem na verdade dois tipos de cheiros(arquivos): os
19.2 Gravar (Salvar) os dados para do tipo texto e os do tipo binrio.
um cheiro(arquivo) Os arquivos tipo texto apenas armazenam texto obe-
decendo uma codicao de caracteres, a mais co-
Os dados que mantemos nos programas esto guardados mum a ASCII, isto implica no uso do cdigo para
na memria RAM, que limpa quando o programa ou armazenamento, ou seja, pode ser que a codicao
computador para de funcionar. Isso implicaria que per- seja interpretada antes de ser efetivada no meio de
deramos toda a informao! Porm existe uma maneira armazenamento.
para tornar os dados persistentes que gravar os dados
num cheiro (arquivo) no hard drive (disco rgido) ou Os arquivos binrios podem guardar mais informa-
no outro meio persistente. Nas formas mais diretas de es- o, como imagens, base de dados, programasPor
crita podemos passar os dados em formato binrio para exemplo, editores de texto com formatao, como
o cheiro(arquivo). Outros meios avanados para guar- o OpenOce e o Word, guardam os seus arquivos
dar dados podem envolver bases de dados relacionais ou em formatos binrios, porque eles possuem alm do
XML. texto, informao acerca da formatao do texto,
para as tabelas, as listas numeradas, tipo de fonte,
etc... da aparecerem os caracteres de formatao
tipo 6, L, h5
19.3 O que um cheiro(arquivo)?
Os arquivos binrios podero ser mais bem explorados
Um arquivo uma coleo de dados que esto localiza-
em um tpico avanado, vamos trabalhar inicialmente
dos numa memria persistente tipo hard drive, cd-rom,
com arquivos tipo texto, que poderemos operar de ma-
etc. Para identicarmos o arquivo podemos atribuir-lhe
neira mais simplicada.
um nome (lename). Os lenames tm usualmente
uma extenso, que determina o tipo de arquivo em sis-
temas operacionais semelhantes aos da Microsoft , mas
que podem ser dispensados em sistemas operacionais que 19.5 biblioteca padro fstream
guardam as caractersticas dos arquivos no meio de arma-
zenamento, tais quais sistemas UNIX e seus similares At agora temos usado a biblioteca iostream (i de input
GNU/Linux, FreeBSD, etc... A extenso representada + o de output + stream), que suporta, entre vrias funcio-
por 3 ou 4 letras que seguem aps o nome do arquivo nalidades, o objeto cin para ler da standard input (que
e um ponto ".. Por exemplo: joao.doc ou joao.odt. usualmente o teclado) e o objeto cout para standard
Isto diz-me que temos um cheiro(arquivo) que se chama output (que usualmente o monitor)

44
19.8. USANDO A FUNO MEMBRO OPEN 45

Ora, agora queremos ler e escrever para chei- 19.8 Usando a funo membro
ros(arquivos) e isso requer a biblioteca fstream (f de le
+ stream). Esta biblioteca dene 3 novos tipos de classe:
open

ofstream (apenas para sada out to a le. serve Esta funo tem como primeiro argumento o nome e lo-
para criar, manipular cheiros (arquivos) e escrever, calizao do cheiro/(arquivo) a ser aberto, o segundo ar-
no serve para ler). gumento especica o modo de abertura.
Sobre a questo da localizao existem 2 tipos, o path
ifstream (apenas para entrada in from a le . relativo e o path absoluto. Para este ltimo indi-
serve para ler cheiros (arquivos), receber dados dos camos o caminho todo: c:\\....\\joao.doc em siste-
mesmos, no serve para criar nem escrever). mas Microsoft ou "/home/joao/joao.odt para sistemas
UNIX e similares. O path relativo dispensa essa des-
fstream (este conjuga os dois tipos anteriores, input crio se o cheiro/(arquivo) estiver (na mesma directo-
and output to le. cria cheiros (arquivos), escreve ria)/(no mesmo diretrio) que o programa.
e l informao dos mesmos.
Sobre a questo do modo de abertura temos as seguintes
modalidades:

19.6 Abrir um cheiro(arquivo) Os sinalizadores (ags) so nmeros em potncias da


base binria, portanto podemos ter vrios ags ao mesmo
tempo se usarmos o operador unrio para a operao
Um cheiro(arquivo) deve ser aberto pelo programa para OU, como no exemplo abaixo:
que o mesmo possa ser manipulado, a abertura do arquivo
implica, entre outras coisas, em atribuir um identicador ofstream outle; //crio o objeto outle out-
que nos permita ter acesso aos seus dados. necessrio le.open(students.dat, ios::binary | ios::app); /*chamo
criar uma linha de comunicao entre o arquivo e o objeto a funo membro open do objeto, com o 1 parme-
stream. tro que o nome do arquivo e o 2 o modo de abertura. */

Podemos recorrer a dois mtodos para abrir um cheiro


(arquivo): Observe que estamos abrindo o arquivo students.dat em
modo binrio e ao mesmo tempo com o modo append,
isto signica que abriremos o arquivo e poderemos pre-
1. Usando um construtor; servar o seu contedo anterior inserindo os novos dados
no m do arquivo.
2. Usando a funo membro chamada de open.

19.7 Usando o Construtor


19.9 Comparando os dois mtodos
O construtor uma funo que automaticamente cha-
mada quando tentamos criar uma instncia de um objeto. (pela funo membro e pelo
fstream ale; // criado uma instncia do fstream cha- construtor)
mada de ale
O primeiro mtodo similar a ter
Os construtores de objetos podem ser sobrecarregados,
int age; age=39;
ou seja, para a mesma classe podemos ter um construtor
sem argumentos, com um argumento, dois argumentos,
etc. No exemplo anterior criamos um sem argumentos. O segundo mtodo similar a
Os construtores no retornam valores, geralmente o com- int age=39;
pilador reporta erro quando se declara funes que retor-
nam valor e estas tm o mesmo nome da classe, pois este
nome reservado para os construtores. Vamos dar um A escolha do melhor mtodo em cada situao depende
exemplo com dois argumento: do contexto em que estamos criando o cdigo, geralmente
quando j temos o objeto criado e ele est fechado po-
ofstream outle (joao.doc, ios::out); demos abrir um novo arquivo com ele e depois fech-lo
novamente, isto nos sugere que usemos a funo open
Chama o construtor com dois argumentos, criando quando o objeto deve abrir arquivos diferentes em cada
uma instncia de ofstream e abrindo o cheiro(arquivo) trecho de cdigo, embora que possam surgir outras funci-
joao.doc para operaes de sada. onalidades, dependendo de como o projeto foi idealizado.
46 CAPTULO 19. ENTRADA E SADA DE DADOS 2

19.10 Abrir um arquivo para lei- Agora, vajamos um exemplo mais completo:
tura #include <fstream> #include <iostream> using names-
pace std; int main () { ifstream arq; //crio objeto arq da
classe ifstream - leitura string str; arq.open(joao.doc);
A histria aqui a mesma s tem uma diferena: que no
//chamo funo membro open if (arq.is_open() &&
caso de leitura, no ser criado nenhum cheiro (arquivo)
arq.good()) { arq >> str; cout << contedo: \n " << str
caso ele no exista.
<< endl; //imprime o contedo do arquivo arq.close(); }
ifstream arq; //cria objeto arq arq.open (joo.doc); #ifdef WIN32 system (pause); #endif return 0; }
//chama funo membro open ao objeto arq, com o
//parmetro do nome do cheiro
Observe que aqui vericamos se o arquivo foi aberto
com a funo membro is_open() que retorna verdadeiro
Poderamos fazer o mesmo com o construtor: true caso o arquivo foi aberto, depois vericamos se
ifstream arq (joo.doc); o arquivo foi aberto satisfatoriamente atravs da funo
membro good(), que tambm retorna verdadeiro se o ar-
quivo pode ser usado.
Ou ainda
fstream bloco; bloco.open(joao.doc, ios::in)
19.12 Fechar um cheiro (arquivo)
ou ainda
fstream b(joao.doc, ios::in) Devemos fechar depois de ler e/ou escrever. Mas por
que, se o objeto do cheiro ir ser fechado assim que
o programa acabar? Porque estamos a utilizar recursos
H mais uma nota a fazer, se quisermos ler e escrever, no com um cheiro (arquivo) aberto, porque alguns siste-
podemos usar o ofstream e o ifstream ao mesmo tempo, mas operativos (operacionais) limitam o n de cheiros
teremos de usar o fstream. Teremos de fazer: (arquivos) abertos, e estando este aberto impede que ou-
fstream a (joo.doc, ios::in | ios::out); tros se possam abrir e por m porque se no fecharmos,
outros programas no podero abri-lo at que o feche-
mos. Este comportamento faz parte de um esquema de
Neste caso, o comportamento padro preservar o con- controle de acesso usado pelo sistema para assegurar que
tedo do cheiro (arquivo) ou cri-lo caso ele no exista. os arquivos no sero usados por processos diferentes ao
mesmo tempo.
ofstream outle; outle.open(students.dat); // ....
19.11 Vericar se o cheiro (ar- outle.close();

quivo) foi aberto.


Vamos criar um exemplo mais real. Queremos criar um
programa que escreva informao inserida pelo utilizador
Vamos vericar o que acontece quando tentamos abrir num cheiro por ns escolhido
um arquivo que no existe, a primeira verso do nosso
exemplo observa o comportamento bsico do fstream: #include <fstream> #include <iostream> using names-
pace std; int main () { char data[80]; //criamos um array
#include <fstream> #include <iostream> using names- de 80 caracteres ofstream outle; //criamos objeto da
pace std; int main () { ifstream arq; //crio objeto arq da classe ofstream outle.open(joao.doc); //chamamos
classe ifstream - leitura arq.open(joao.doc); //chamo a funo membro da classe para o objeto criado. //
funo membro open cout << "(arq) = " << arq << endl; Esta funo membro cria o arquivo joao.doc if (out-
//imprime o objeto cout << "(arq.fail()) = " << arq.fail() le.is_open() && outle.good()) //vericamos se est
<< endl; //chamo funo membro fail #ifdef WIN32 tudo bem { cout << digite o seu nome: "; //imprime
system (pause); #endif return 0; } no ecr (monitor) a frase cin.getline(data, 80); //chama
funo membro getline do objeto cin para //ler o que
No caso do cheiro (arquivo) joao.doc no existir: foi escrito pelo usurio outle << data << endl; //coloca
o array no objeto criado. outle.close(); //fechamos o
(arq) = 00000000 (arq.fail()) = 1 objeto. } #ifdef WIN32 system (pause); #endif return
No caso do cheiro (arquivo) joao.doc existir no 0; }
mesmo diretrio que o programa:
(a) = 0012FE40 (a.fail()) = 0 Podemos ir ver o novo cheiro/arquivo com o nome
Repare que o resultado a impresso do endereo, do joao.doc e tem l escrito aquilo que digitamos.
objeto a de ifstream. d um ponteiro!! Agora vamos tentar ler o que escrevemos no documento
19.13. LOOPING PELO FICHEIRO (ARQUIVO). 47

criado. (e-end+o-of+f-le). Esta funo no tem parmetros e


#include <fstream> #include <iostream> using na- retorna true se o m do arquivo for alcanado e false
mespace std; int main () { char data[80]; ifstream caso contrrio. No entanto, esta funo eof() no de
inle; inle.open(joao.doc); if (inle.is_open() && conana com os cheiros (arquivos) texto como o para
inle.good()) //vericamos se est tudo bem { inle >> os binrios ( que nos cheiros (arquivos) binrios no
data; //colocamos os dados abertos no array cout << data existem espaos em branco).
<< endl; inle.close(); } #ifdef WIN32 system (pause); A melhor alternativa usar a funo membro fail().
#endif return 0; } ifstream inle; inle.open(joao.doc); if (in-
le.is_open() && inle.good()) { inle >> data;
Repare que se tivssemos escrito duas palavras, apenas while(!inle.fail()) { inle >> data; cout << data; }
uma era apresentada (ela pra no primeiro whitespace), inle.close(); }
para isso necessitaramos de repetir:
#include <fstream> #include <iostream> using na- Refazendo tudo
mespace std; int main () { char data[80]; ifstream
#include <fstream> #include <iostream> #include
inle; inle.open(joao.doc); if (inle.is_open() && <string> using namespace std; int main () { string
inle.good()) //vericamos se est tudo bem { inle >>
data; ofstream outle; outle.open(joao.doc);
data; //colocamos os dados abertos no array cout << data if (outle.is_open() && outle.good()) { cout
<< endl; inle >> data; //colocamos os dados abertos
<< Escrevendo no arquivo << endl; cout <<
no array cout << data << endl; inle.close(); } #ifdef "===================" << endl; cout << In-
WIN32 system (pause); #endif return 0; }
forme o nome da classe: "; getline(cin, data); outle
<< data<< endl; cout << informe o nmero de
Agora j obtemos 2 palavras e so apresentadas em linhas estudantes: "; cin >> data; cin.ignore(); outle
diferentes. Mas temos de arranjar um mtodo para no << data<< endl; outle.close(); } ifstream inle;
estar a repetir constantemente, podemos fazer isso com inle.open(joao.doc); if (inle.is_open() && in-
inle.getline(data, 80); le.good()) { cout << Lendo do arquivo << endl;
cout << "=====================" << endl;
getline(inle, data); while(!inle.fail()) { cout << data
Ento camos com: << endl; getline(inle, data); } inle.close(); } #ifdef
#include <fstream> #include <iostream> #include WIN32 system (pause); #endif return 0; }
<string> using namespace std; int main () { string
data; ofstream outle; outle.open(joao.doc); if Agora vamos fazer o nosso programa mais modular:
(outle.is_open() && outle.good()) //vericamos se
est tudo bem { cout << Writing to the le << endl; 1. . writeFile para abrir um arquivo para escrita
cout << "===================" << endl; cout usando o ofstream e
<< Enter class name: "; getline(cin, data); outle <<
data << endl; cout << Enter number of students: "; 2. . readFile - ler do cheiro (arquivo) usando o ifs-
cin >> data; cin.ignore(); //esta funo membro para tream
limpar o caractere //newline do inputbuer depois
3. . Cada funo ir vericar se o cheiro (arquivo) foi
de usar o objeto //cin com o operador de extrao
aberto com sucesso
>> outle << data<< endl; outle.close(); } ifstream
inle; inle.open(joao.doc "); if (inle.is_open()
&& inle.good()) //vericamos se est tudo bem { #include <fstream> #include <iostream> #include
cout << Reading from the le << endl; cout << <string> using namespace std; bool writeFile (ofs-
"=====================" << endl; getline(inle, tream&, char*); bool readFile (ifstream&, char*); int
data); cout << data << endl; getline(inle, data); cout main () { string data; bool status; ofstream outle;
<< data << endl; inle.close(); } #ifdef WIN32 system status = writeFile(outle, students.dat); if (!status) {
(pause); #endif return 0; } cout << Arquivo no pode ser aberto para escrita.\n";
cout << Programa terminando...\n"; return 0; } else
{ cout << Escrevendo no arquivo << endl; cout <<
"===================" << endl; cout << Informe
o nome da classe: "; getline(cin, data); outle << data<<
19.13 Looping pelo cheiro (ar- endl; cout << Informe o nmero de estudantes: "; cin >>
data; cin.ignore(); outle << data<< endl; outle.close();
quivo). } ifstream inle; status = readFile(inle, students.dat);
if (!status) { cout << O arquivo no pode ser aberto para
E se no soubermos quantas linhas tem o arquivo? O leitura.\n"; cout << Programa terminando...\n"; return
objeto ifstream tem uma funo membro que a eof() 0; } else { cout << Lendo do arquivo << endl; cout <<
48 CAPTULO 19. ENTRADA E SADA DE DADOS 2

"=====================" << endl; getline(inle, << showbase << endl; cout << Decimal: " << dec
data); while(!inle.fail()) { cout << data << endl; << intValue << endl; cout << Octal: " << oct <<
getline(inle, data); } inle.close(); } #ifdef WIN32 intValue << endl; cout << Hexadecimal: " << hex <<
system (pause); #endif return 0; } bool writeFile intValue << endl; cout << Desativando showbase " <<
(ofstream& le, char* strFile) { le.open(strFile); return noshowbase << endl; cout << endl; double doubleVal
!(le.fail()||!le.is_open()||!le.good()); } bool readFile = 12.345678; cout << Nmeros com ponto utuante
(ifstream& ile, char* strFile) { ile.open(strFile); << endl; cout << Padro: " << doubleVal << endl;
return !(ile.fail()||!ile.is_open()||!ile.good()); } cout << setprecision(10); cout << Preciso de 10: "
<< doubleVal << endl; cout << scientic << Notao
cientca: " << doubleVal << endl; cout << uppercase;
cout << Caixa alta: " << doubleVal << endl; cout
19.14 Manipuladores << endl; bool theBool = true; cout << Booleano <<
endl; cout << Padro: " << theBool << endl; cout
<< boolalpha << BoolAlpha ativo: " << theBool <<
Os objetos das classes stream podem ser congura-
endl; cout << endl; string myName = John"; cout <<
dos para fornecer e reportar os dados de maneira pr-
Strings << endl; cout << Padro: " << myName <<
formatada. Da mesma maneira que temos a formatao
endl; cout << setw(35) << right << Com setw(35) e
quando usamos funes de formatao, como printf() e
\"right\": " << myName << endl; cout.width(20); cout
scanf(), na linguagem C, podemos usar os manipulado-
<< Com width(20): " << myName << endl; cout <<
res na linguagem C++ para informar os objetos streams
endl; #ifdef WIN32 system (pause); #endif return 0; }
em que formato desejamos receber os dados deles ou for-
necer para eles.
Abaixo temos uma srie de manipuladores teis:
19.15 Exerccios
19.14.1 Ajustando a largura da en-
1. Quero colocar num documento, uma lista das com-
trada/sada binaes possveis entre a,b,c e d. com a respectiva
ordenao e quantidade;
setw(w) - Ajusta a largura da sada e entrada para w;
precisa ser includo. 2. . Quero que seja a pessoa a escolher o nome do -
cheiro (arquivo) e escrever tambm a localizao;
width(w) - Uma funo membro das classes ios-
tream. 3. . Quero que seja depois tansformado num sistema
modular;
19.14.2 Preenchimento de espaos em 4. . Encontrar uma maneira para contar o n de espaos
branco em branco, o n de caracteres ". que quisermos de
um dado documento.
setll(ch) - Preenche os espaos em branco em cam-
pos de sada com ch; precisa ser includo. #include <iostream> #include <fstream> using na-
mespace std; int main() { int blank_count = 0; int
ll(ch) - Uma funo membro das classes iostream.
char_count = 0; int sentence_count = 0; char ch; ifstream
object(jo.txt); if (! object) { cout << Erro abrindo
19.14.3 Ajustando a preciso arquivo. << endl; return 1; } while (object.get(ch))
{ switch (ch) { case ' ': blank_count++; break; case
setprecision(n) - Ajusta a preciso de casas decimais '\n': case '\t': break; case '.': sentence_count++; break;
em nmeros com ponto utuante, para n dgitos. default: char_count++; break; } } cout << Existem "
Este ajuste apenas visual, de forma que o manipu- << blank_count << " espaos em branco;" << endl; cout
lador no afeta o modo de clculo do nmero pelo << Existem " << char_count << " caracteres;" << endl;
programa. cout << Existem " << sentence_count << " sentenas.
<< endl; #ifdef WIN32 system (pause); #endif return
0; }
Exemplicando o uso de manipuladores:
#include <iostream> #include <iomanip> #include
<string> using namespace std; int main() { int intValue =
15; cout << Nmero inteiro << endl; cout << Padro:
" << intValue << endl; cout << Octal: " << oct <<
intValue << endl; cout << Hexadecimal: " << hex
<< intValue << endl; cout << Ativando showbase "
Captulo 20

Manipulando strings

20.1 Char strings e Strings das funes da linguagem C e mais algumas caractersti-
cas prprias possibilitadas pela orientao a objetos.

Os caracteres so entendidos como sendo nmeros que // listandoCodigoASCII.cpp #include<iostream> using


geralmente tm oito bits, esses nmeros so traduzidos std::cout; using std::cin; using std::endl; #include<string>
na tabela ASCII de 128 caracteres, como existem in- using std::string; using std::getline; int main(){ string
meras regies no mundo com caractersticas lingusticas anyWord; cout << Digite uma palavra: "; getline(cin,
prprias, a tabela ASCII estendida por um bloco de ca- anyWord); for ( int i = 0; i < anyWord.length(); i++) cout
racteres acima dos 128 mais baixos que varia de acordo << anyWord[i] << " - " << (int)anyWord[i] << endl;
com as necessidades de cada lngua. A parte superior cout << endl; return 0; } //end main
da tabela ASCII conhecida como parte estendida e
referenciada por pginas de cdigos para cada propsito
lingustico, isso quer dizer que podemos ter os mesmos
nmeros signicando caracteres diferentes para cada re- 20.2 Funes de caracteres teis.
gio do mundo.
No estilo da linguagem C quando queremos representar As seguintes funes esto no cabealho da biblioteca
um conjunto de caracteres colocamos todos eles em uma <cctype>
matriz sequenciada na memria: toupper() (to+upper) retorna a maiscula de uma letra.
Por exemplo, para declarar um espao na memria que uma funo de um argumento o caractere. no caso do
contenha 20 caracteres fazemos: argumento no ser uma letra, a funo retorna o mesmo
caractere que argumento.
char dados[20];
tolower() (to+lower) o mesmo comportamento que
toupper(), porm com o resultado em minscula.
Este o estilo de strings usado pela linguagem C pura.
Para manipular este tipo de string preciso ter certo cui- #include <iostream> #include <cctype> using namespace
dado, pois a matriz sempre tem um tamanho denido e std; int main(void) { char ch; do { cout << Pressionar S
caso faamos um acesso a um endereo fora da matriz in- ou s para sair, \nqualquer outra tecla para continuar: ";
vadiremos outras reas de memria que no temos como cin.get(ch); ch = toupper(ch); if (ch != '\n') cin.ignore();
denir o que so, e portanto poderemos fazer o programa if (ch != 'S') cout << Deseja continuar?\n"; else cout
parar de funcionar, em muitos sistemas pode tambm << Saindo..."; } while (ch != 'S'); #ifdef WIN32 system
haver danos aos outros programas e at mesmo ao pr- (pause); #endif return 0; }
prio sistema operacional, porm em sistemas operacio-
nais mais sosticados como o GNU/Linux, que possuem Funes que vericam o caractere. Estas funes rece-
gerenciamento de memria com proteo de memria, bem apenas um argumento, o caractere e retornam um
apenas o programa que causou a falha ir parar de funci- valor booleano.
onar.
Para manipular este tipo de string a biblioteca padro da
linguagem C dispe de diversas funes, para mais deta- 20.3 Strings em C++
lhes consulte o livro Programar em C.
No estilo C++, como era de se esperar, as strings so ob- As cadeias de caracteres da linguagem C podem formatar
jetos, eles podem ser criados facilmente atravs da bi- um novo tipo de dados, porm criar tipos de dados mais
blioteca padro referenciada pelo arquivo de cabealho sosticados no possvel nesta linguagem, as strings em
<string>. As strings so objetos com recursos que permi- C++ so objetos da classe string, o que isso traz de novo
tem manipular os seus caracteres com as funcionalidades para o tratamento de textos em programas? A primeira

49
50 CAPTULO 20. MANIPULANDO STRINGS

coisa a notar quando criamos strings em C++ a maneira Estas operaes resultam em:
de cri-las, a classe disponibiliza uma srie de construto- Alice e Beto gostam de chocolate. Alice e Beto gostam
res: de doce de leite. Alice e Beto gostam de pipoca. Alice e
1 string ( ); 2 string ( const string& st ); 3 string ( const Beto gostam de doce de leite.
string& st, size_t position, size_t n = npositions ); 4
string ( const char * ps, size_t n ); 5 string ( const char *
ps ); 6 string ( size_t n, char ch );
20.3.1 Exemplos de como manipular
Isto torna possvel, basicamente, criar string de seis ma- strings em C++
neiras diferentes:
erase A funo membro erase elimina parte de uma
string. Os parmetros passados para a funo so a posi-
1. Podemos denir um objeto string vazio, para futu-
o inicial e o nmero de caracteres a ser excludo. Veja
ramente usarmos de acordo com a necessidade;
um exemplo de uso abaixo:
2. Podemos criar um objeto string com uma cpia de #include<iostream> using std::cout; using std::endl;
outro; using std::cin; #include<string> using std::string; using
3. Podemos criar um objeto string com uma cpia de std::getline; int main(){ string myText; cout << Digite
uma poro de outra string; um texto qualquer << endl; getline( cin, myText );
myText.erase(7, 3); cout << myText << endl; return 0; }
4. Podemos criar um objeto string com uma cpia de
uma parte de uma char string";
5. Podemos criar um objeto string com uma cpia de
uma char string"; 20.4 Comparando formas de ope-
6. Podemos criar um objeto string preenchida com rar strings em C e C++
uma quantidade denida de um determinado carac-
tere; Em C, temos diversas funes que so usadas para ma-
nipular strings, para mais detalhes veja o livro Programar
Quando manipulamos strings, podemos faz-lo com ope- em C, aqui faremos uma comparao dos modos de ope-
radores, como por exemplo "+", "+=", "<<", etc... Isto rar strings em C e C++, algumas particularidades da lin-
torna o cdigo um pouco mais intuitivo, vejamos os ope- guagem C++ permitem uma operao mais intuitiva das
radores: strings e algumas novas formas de trat-las. Vejamos
como manipular estes dados to comuns em qualquer
1 operator= 2 operator[] 3 operator+= 4 operator+ 5 programa.
operator<< 6 operator>>

Que representam as operaes: 20.4.1 Funes uteis para o uso de strings

1. Atribuir o valor de uma string para outra; strlen() (str=string + len=length)- aceita um argumento
que pode ser um array (uma cadeia) de caracteres, um
2. Acessar caracteres individualmente; ponteiro (que aponta para um array de caracteres) ou uma
string literal. retorna um nmero inteiro que representa o
3. Adicionar uma string no nal de outra; nmero de caracteres, no incluindo o caractere null":
4. Concatenar strings; int len; len = strlen(Je) // a extenso 4 char* stinky-
dog = Dante"; len = strlen(stinkydog); // a extenso
5. Enviar uma string a um output stream;
5 char name[80] = Devvie"; len = strlen(name); // a
6. Receber uma string do input stream. extenso 6

Apenas com estas poucas informaes j possvel ope- No c++ temos duas funes similares na classe string que
rar strings com bastante exibilidade e de uma maneira so o lenght() e size(). Estas funes no tem argumen-
muito intuitiva, vejamos alguns exemplos: tos pois reportam as informaes sobre o objeto a quem
string a = (Alice e Beto gostam de "), b = (chocolate.), pertencem, ambas retornam um inteiro que representa o
c = (doce de leite.), d = (pipoca.), e = (c); cout << tamanho das strings:
a + b << endl; cout << a + c << endl; cout << a + d << string s = Je Kent"; cout << s.length(); // mostra: 9
endl; cout << a + e << endl; cout << s.size(); // tambm mostra: 9
20.4. COMPARANDO FORMAS DE OPERAR STRINGS EM C E C++ 51

20.4.2 Copiando strings Deve-se observar que strcat , potencialmente, uma das
rotinas mais perigosas do C, por um motivo bem simples:
Se tentssemos copiar strings desta maneira a string de destino deve ser pre-dimensionada, e deve ter
char* target = Je Kent"; char src[80] = Micaela"; espao suciente para receber a string de origem. Um
target = src; pequeno programa como:
char target[13] = Regras do C!"; char* source = " Mas
O que acontecia que era a cpia do endereo de src para pode dar resultados imprevisiveis"; strcat(target, source);
o ponteiro e no os caracteres que esto dentro da matriz.
No entanto existe a funo strcpy (estilo C) ela aceita Escrever bytes em regies da memria que no foram
dois argumentos, previamente alocadas para a string. Em c++, este pro-
blema resolvido pelo uso de objetos string.

O primeiro para onde vai ser copiada e passado Ao estilo de c++ podemos fazer.
o ponteiro desse array (no pode ser uma string lite- string target = Regras do C++!\n"; string source = "
ral). Geralmente no do resultados imprevisiveis.\n"; target
+= source; cout << target; // Mostra: Regras do C++! //
O segundo a frase a ser copiada e pode ser um Geralmente no do resultados imprevisiveis.
array, um ponteiro ou um string literal

Isto porque a classe string prev o uso do operador "+="


char* target = Je Kent"; char src[80] = Micaela";
de concatenao e nele est embutido um cdigo de ve-
strcpy(target, src);
ricao de espao e realocao do mesmo para string,
caso seja necessrio.
Note que esta operao muito arriscada visto que,
quando criamos target, a quantidade de caracteres que foi
reservada para a string era de 9 caracteres mais o carac- 20.4.4 comparar frases
tere nulo no nal, se zermos uma cpia de uma string
com mais de 9 caracteres para este endereo, represen- se zessemos
tado por target, ele fatalmente causar uma violao de
endereo. char str1[80] = Devvie Kent"; char str2[80] = Devvie
Kent"; if (str1 == str2) cout << The two C-strings are
Porm em C++ podemos atribuir o valor de uma varivel equal"; else cout << The two C-strings are not equal";
para outra da classe string da forma:
string target = Je Kent"; string src = Micaela"; target o que acontecia que estariamos a comparar os endereos
= src; e no os valores
temos a funo strcmp (string+compare) (tem 2 arguen-
Agora, reitamos no que signica estas operaes: Em tos. retornar 0 se forem iguais)
primeiro lugar string no um tipo primitivo de dado,
uma classe, portanto um tipo de dado mais inteli- char str1[80] = Devvie Kent"; char str2[80] = Devvie
gente, uma das caractersticas dos objetos string que Kent"; if (!strcmp(str1, str2)) cout << The two C-strings
eles so redimensionveis, ou seja, quando atribumos a are equal"; else cout << The two C-strings are not equal";
uma string um dado maior que seu espao interno de
armazenamento ela aumenta o seu espao interno para esta comparao pode ser resultar em negativo e positivo
comportar o novo dado. Outra caracterstica que a ope- e isso tem a ver com o jogo de caracteres na tabela ascII.
rao "=" para a string uma operao de atribuio de aqui vai um resumo
contedo, de forma que a string copia a outra quando usa-
Resultados de comparaes entre strings
mos este operador e no apenas o ponteiro que referncia
o endereo da string. Em C++ podemos comparar duas strings atravs da fun-
o membro da classe string: compare(), existem os se-
guintes formatos (assinaturas) para a funo:
20.4.3 Unir strings 1 int compare ( const string& str2 ) const; 2 int compare
( const char* szc ) const; 3 int compare ( size_t pos1,
strcat() (string+concatenate) une duas frases. Recebe size_t n1, const string& str2 ) const; 4 int compare
2 argumentos, a frase primria o ponteiro para esse ar- ( size_t pos1, size_t n1, const char* szc) const; 5 int
ray. compare ( size_t pos1, size_t n1, const string& str2,
char target[80] = Je"; char* source= " Kent"; str- size_t pos2, size_t n2 ) const; 6 int compare ( size_t
cat(target, source); cout << target; // Mostra Je Kent pos1, size_t n1, const char* szc, size_t n2) const;
52 CAPTULO 20. MANIPULANDO STRINGS

A funo permite os seguintes modos de operao, res- '-') return 1; } else { if (!isdigit(input[x])) return 2; } }
pectivamente: num = atoi(input); cout << num; #ifdef WIN32 system
(pause); #endif return 0; }
1. Comparar uma string de entrada (str2) com o con-
tedo do objeto a qual ela pertence; Neste exemplo temos a vantagem de o usurio inserir um
dgito para o array de caracteres em vez de um inteiro,
2. Comparar uma C-string apontada por um ponteiro para evitar um run-time error ou garbage data que
com o contedo do objeto a qual ela pertence; aconteceria se a entrada fosse no numrica. Depois o
3. Comparar uma seo comeando em (pos1) do ob- array vericado para ver se representa um nmero. Se
jeto, a qual contm (n1) caracteres, com a string o numero for negativo tem o caractere "".
de entrada (str2); Em C++ usamos objetos da classe stringstream (biblio-
teca sstream.h) para armazenar temporariamente os ca-
4. Comparar uma C-string apontada por um ponteiro racteres, depois usamos o operador ">>" para converter
(szc), com uma seo comeando em (pos1), a qual os caracteres em nmero, bastando para isto criar a va-
contm (n1) caracteres do contedo do objeto a qual rivel no formato que desejamos receber o nmero. Mais
ela pertence; uma vez temos o uso do poliformismo para resoluo
5. Comparar uma seo do objeto, iniciada em (pos1) de um problema comum de programao, a operao do
com (n1) caracteres, com uma seo de (str2), ini- ">>" diferente para cada tipo de dado, selecionada au-
ciada em (pos2) com (n2) caracteres; tomaticamente pelo compilador de acordo com o tipo de
dado da varivel destino.
6. Comparar uma C-string apontada por um ponteiro string name = 123"; stringstream sst; int i; sst << name
(szc) de extenso (n2), com uma seo comeando << endl; sst >> i;
em (pos1), a qual contm (n1) caracteres do con-
tedo do objeto a qual ela pertence.
Os passos acima armazenam o valor 123 na varivel i,
todo processo de converso feito pelo operador ">>".
O resultado similar ao da funo strcmp() em C, re-
tornando uma referncia de valor de acordo com o cdigo
ASCII.
Se estiver comparando duas strings uma outra opo,
ainda mais natural, utilizar os operadores de compa-
rao < e ==.
using namespace std; string str1 = check"; string str2
= chess"; if (str1 == str2) cout << As palavras so
iguais. << endl; else if (str1 < str2) cout << A palavra "
<< str1 << " vem antes de " << str2 << endl; else cout <<
A palavra " << str1 << " vem depois de " << str2 << endl;

20.4.5 Convertendo C-string e nmero


No cheiro (arquivo) cabealho da biblioteca cstdlib
(c+std+lib) temos vrias funes de converso de nme-
ros em tipo numrico.
atoi (acrnimo para ASCII to integer) recebe um argu-
mento c-string) e retorna o inteiro que a c-string repre-
senta. No verica se o argumento pode ser convertido:
int num = atoi(7654);

Programa exemplo:
#include <iostream> #include <cstdlib> // necessrio
para atoi #include <cstring> using namespace std; int
main(void) { char input[80]; int num; cout << Enter an
integer: "; cin >> input; for (int x = 0; x < strlen(input);
x++) { if (x == 0) { if (!isdigit(input[x]) && input[x] !=
Captulo 21

Classes

21.1 Classes Um acesso de memria a qualquer elemento da matriz


acima da posio 9, far com que invadamos dados na
Existem duas categorias de tipos de dados usuais em C++, rea onde a varivel nReal est denida.
so classicados como tipos bsicos e tipos denidos
pelo programador.
21.1.2 Funes membro (Mtodos)
Assim como na linguagem C, podemos denir dados
compostos por associaes dos tipos bsicos, estes tipos Agora suponha que tenhamos como denir um modo para
so chamados de estruturas (structs). C++ traz uma nova entrar e outro para ler dados da matriz:
representao de dados, muito semelhante na forma s es-
truturas, porm diferentes na forma conceitual: a palavra struct MyData { int n; char data[10]; oat nReal; bool
chave class, que usada para criar uma classe de objetos write_data(int pos, char c) { if (pos >= 0 && pos <
mais rica que as structs. Ao declararmos um identica- 10) { data[pos]=c; return true; } return false; } char
dor, tal qual fazemos ao declarar uma varivel e no lugar read_data(int pos) { if (pos >= 0 && pos < 10) { return
do tipo especiquemos uma classe criaremos um objeto. data[pos]; } return '\0'; } };
Antes de prosseguirmos, vejamos um pouco sobre o con-
ceito por trs do uso de objetos. Um objeto entendido Agora temos assegurados mtodos de incluso e acesso a
como uma entidade de dados dentro da memria que, dados da matriz de caracteres, porm ainda existe um pe-
basicamente, deve ser responsvel por seu contedo, ou queno problema: Quem quiser o antigo mtodo de acesso
seja, um objeto deve ser capaz de gerenciar seu contedo direto conseguir facilmente, pois os elementos da estru-
autonomamente, ou prover meios de outras entidades de tura esto acessveis publicamente por padro.
cdigo faz-lo de forma segura.

21.1.3 Conceituao
21.1.1 Origem (atributos)
O problema da visibilidade pblica dos dados em uma es-
trutura pode ser resolvido com um dos conceitos de ob-
Observemos, por exemplo, o cdigo abaixo:
jetos, o encapsulamento. Encapsular os dados, signica
struct MyData { int n; char data[10]; oat nReal; }; reservar o acesso a funes que estejam dentro de um
grupo restrito, especializado para tais operaes de ma-
Esta declarao, bem conhecida de quem j est famili- nipulao destes dados. Uma das vantagens deste proce-
arizado com a linguagem C, cria um tipo de dado com- dimento que o cdigo adquire um formato mais organi-
posto heterogneo, que neste exemplo chamamos de My- zado, onde os processos tornam-se claramente distintos,
Data, o que acontece aqui que os dados esto agrupados caso tenhamos que analisar o cdigo, cada procedimento
dentro desta estrutura, isto promove a possibilidade de estar restrito a partes denidas para cada operao.
manipul-los em conjunto. Um dos problemas com esta
estrutura a presena de uma matriz de caracteres cha-
mada data, observe que a mesma tem um tamanho de- 21.2 Declarando classes
nido de 10 caracteres, imagine que em algum momento
da execuo do programa tentamos colocar um caractere
na posio 11, ou qualquer posio fora da matriz, neste As estruturas so bem parecidas com as classes, com uma
caso estamos colocando o referido dado em endereos pequena diferena, peguemos o caso da passagem de es-
invlidos para a operao que pretendemos realizar, ou truturas como argumentos de funes:
seja, no h controle nenhum que assegure que o cdigo #include <iostream> #include <string> using names-
no far um acesso fora da rea que pertena a matriz. pace std; class Person { string name; int height; };

53
54 CAPTULO 21. CLASSES

void setValues(Person&); void getValues(const Per- name: " << pers.getName() << endl; cout << Persons
son&); int main () { Person p1; setValues(p1); cout height in milimeters is: " << pers.getHeight() << endl; }
<< Informando dados sobre a pessoa:\n"; cout <<
"================================\n"; get- Mas perguntam: Por que que nos demos ao trabalho
Values(p1); return 0; } void setValues(Person& pers) de recorrer a membros privados em vez de fazer todos
{ cout << Informe o nome da pessoa: "; getline(cin, pblicos? Quando tnhamos uma estrutura no lugar de
pers.name); cout << Informe a altura em milmetros: "; uma classe, no havia nada que impedisse a colocao de
cin >> pers.height; cin.ignore(); } void getValues(const valores invlidos, por isso poderamos ter valores vazios
Person& pers) { cout << Nome da pessoa: " <<
para a string e valores negativos para a varivel height.
pers.name << endl; cout << A altura da pessoa em
milmetros : " << pers.height << endl; } Agora que Person uma classe, as funes membro
podem realizar a validao dos dados antes da atribui-
o de valores nas variveis. Poderamos fazer com que
Mudamos o identicador de struct para class a funo setName vericasse se a entrada na string se-
ria vazia e caso fosse, colocaria um valor padro como:
Mas se tentarmos compilar o programa isto vai cau- sem nome. similarmente poderamos ter setHeight
sar erros de compilao, porque agora temos vari- para vericar se seriam colocados valores de entrada ne-
veis membro que so privadas por padro, estas no gativos e caso fossem, colocaria zero, ou no tomaria ne-
so vistas por funes fora da classe. nhuma ao.
Todas estas caractersticas demonstram o conceito de en-
Dentro de uma classe podemos denir diversos modos de capsulamento. A sua nalidade de tornar o cdigo mais
visibilidade de variveis e funes. modularizado, restringindo o escopo de anlise a partes
As modalidades podem ser: bem delimitadas dos programas. Devido a este conceito
podemos contar com cdigos mais fceis de analisar e fa-
zer manuteno.
private (s podem ser acessados por membros da
mesma classe)
public (pode ser acessadas fora do objeto, onde este 21.3 Instanciando objetos
estiver denido)
protected (deixemos esta para quando falarmos em Instanciao de objetos o processo de criar a estrutura
classes derivadas, pois depende deste conceito). lgica dos mesmos na memria. Isto ocorre quando de-
claramos os objetos, pois neste momento todo o processo
Ora, como as funes getValues e setValues no so de construo dos mesmos efetivado. Assim, toda vez
membros da classe Person, tal como o construtor Person, que declaramos um objeto estamos instanciando-o, ou
no conseguem acessar as variveis name e height. seja, estamos criando uma instncia da classe.

Visualizamos melhor em forma de tabela: Podemos declarar os objetos logo aps denir a classe
conforme podemos ver no 1 caso logo abaixo. Neste
A soluo criar funes publicas, para ler de e escrever caso teremos a varivel rect criada como um objeto con-
para as variveis privadas: forme estabelecido pelo modelo denido pela palavra
#include <iostream> #include <string> using na- chave class. Este tipo de declarao mais usual para
mespace std; class Person { private: string name; objetos criados globalmente, pois a incluso desta decla-
int height; public: string getName() const; void set- rao no cabealho pode fazer com que vrios objetos
Name(string); int getHeight() const; void setHeight(int); sejam criados com o mesmo nome quando o cabealho
}; string Person::getName() const { return name; } invocado de vrios arquivos. Portanto, mais prudente
void Person::setName(string s) { if (s.length() == usar esta opo quando a declarao est no arquivo fonte
0) name = No name assigned"; else name = s; } e no no cabealho.
int Person::getHeight() const { return height; } void 1 caso:
Person::setHeight(int h) { if (h < 0) height = 0; else
height = h; } void setValues(Person&); void get- class CRectangle { int x, y; public: void set_values
Values(const Person&); int main () { Person p1; (int,int); int area (void); } rect;
setValues(p1); cout << Outputting person data\n"; cout
<< "======================\n"; getValues(p1); No 2 caso, apresentado logo abaixo, podemos declarar
return 0; } void setValues(Person& pers) { string str; objetos apenas quando precisarmos. Esta opo de de-
int h; cout << Enter persons name: "; getline(cin,str); clarar o objeto depois a mais usada, pois na maioria das
pers.setName(str); cout << Enter height in milimeters: vezes temos o modelo dos objetos, a classe, declarada
"; cin >> h; cin.ignore(); pers.setHeight(h); } void em um arquivo de cabealho enquanto que os objetos se-
getValues(const Person& pers) { cout << Persons ro criados no resto do cdigo fonte. Desta forma mais
21.4. DEFINIO DE CLASSES 55

usual criar as classes em cabealhos e depois declarar os com que o cdigo seja apenas um modelo, a funo de
objetos na parte do programa que for mais conveniente. clculo da rea no ser criada se no for usada durante
2 caso: o escrita do resto do programa.

class CRectangle { int x, y; public: void set_values Vejamos outro exemplo:


(int,int); int area (void); }; int main() { CRectangle rect; class Dog { public: void setAge(int age); int getAge();
} void setWeight(int weight); int getWeight(); void speak();
private: int age; int weight; }; void Dog::setAge(int
Em ambos os casos temos age) { this->age = age; } int Dog::getAge() { return
age; } void Dog::setWeight(int weight) { this->weight =
Podemos, ento, entender os objetos como blocos de da- weight; } int Dog::getWeight() { return weight; } void
dos que tm propriedades (variveis) e que podem fazer Dog::speak() { cout << BARK!!" << endl; }
algo (mtodos). Ento, criamos todas as funcionalidades
que precisamos que a classe fornea aos programas, fa-
zendo os testes necessrios para assegurar sua consistn- Acima podemos ver um modo de declarar as funes ape-
nas como prottipos, que cam dentro da declarao da
cia e estabilidade. Sempre que precisemos utilizar os ob-
jetos s temos que instanci-los (declar-los), e no preci- classe. Nesse contexto as funes so denidas fora da
classe, usando-se o operador "::" para ligar a funo
samos nos preocupar como eles funcionam internamente,
uma vez que os desenhamos adequadamente. classe. Neste caso teremos as funes denidas e cons-
trudas no cdigo das mesmas, enquanto que o modelo
Para entendermos melhor este conceito podemos fazer da classe poder permanecer em um arquivo cabealho,
uma analogia. Consideremos um objeto resistncia: sa- o que possibilita inclu-lo em qualquer arquivo de cdigos
bemos que temos de us-lo e que ela deve ter certas ca- fontes do programa.
ractersticas, ento teremos o seu valor em Ohms, sua po-
tncia mxima, tolerncia, entre outras, e teremos uma
funo que nos dar a corrente que passa por ela quando 21.4 Denio de classes
lhe aplicamos uma tenso eltrica. No precisamos sa-
ber de que que ela feita, ou como estas caractersticas
internas a faz funcionar, basta-nos receber os resultados. Usa-se a palavra class para criar uma classe, seguindo-
se depois o nome que se queira dar-lhe e nalmente a
Vejamos o exemplo: denio da mesma entre chaves.
Agora vamos mostrar que podemos ter funes mem- A denio contm:
bro apenas como prottipos e deni-las fora da classe.
Para isso usamos o operador de denio de escopo :: os dados ( propriedades );
que permite denir o local do cdigo onde um iden-
ticador existe, no formato: ESCOPO::funo ou ES- os mtodos (as funes membro)
COPO::dado. De maneira geral, quando declaramos
Vamos acompanhar com um exemplo: Vamos fazer o de-
identicadores dentro da classe podemos deni-los no es-
senho de uma classe chamada Image, que ser usada
copo global referenciando estes pelo operador de escopo.
para guardar e manipular uma imagem.
// classes example #include <iostream> using namespace
Primeiro perguntamos o que necessrio para guardar
std; class CRectangle { int x, y; public: void set_values
uma imagem, depois que tipo de manipulaes necessi-
(int,int); int area () {return (x*y);} }; void CRectan-
tamos.
gle::set_values (int a, int b) { x = a; y = b; } //repare no ::
que pemite-nos denir a funo membro da classe CRec- A imagem possui 400 pixels de largura e 300 pixels altura.
tangle fora da classe int main () { CRectangle rect; //de- Cada pixel tem as propriedades de cor e imagem. A cor
nimos objeto de classe rect.set_values (3,4); //objeto- composta por: vermelho, azul e verde, numa escala de 0 a
membro cout << area: " << rect.area(); return 0; } // 264 . Portanto vamos necessitar de membros para guardar
classes example #include <iostream> using namespace estas informaes
std; class CRectangle { int x, y; public: void set_values Agora planejemos os mtodos. Vamos, primeiramente,
(int a,int b) { x = a; y = b; } int area () {return (x*y);} }; int assumir que temos a restrio de <= 400 pixeis, e estes
main () { CRectangle rect; //denimos objeto de classe valores sero feitos pelo construtor na criao do objeto.
rect.set_values (3,4); //objeto-membro cout << area: " Ns no precisamos dos mtodos para estipular a altura
<< rect.area(); return 0; } e largura, mas vamos precisar para obter e ler os valores.
area: 12 Esta estratgia tambm nos ajudar a manter os valores
O exemplo anterior explora a caracterstica de toda gura de um determinado pixel e a sua localizao.
geomtrica fechada, que possui uma rea interna. Ob- A primeira verso ento seria:
serve que este modo de denir a classe coloca o clculo
da rea dentro da denio da mesma. Este modo faz class Image { public: int getWidth(); int getHeight();
void setX(int x); int getX(); void setY(int y); int
56 CAPTULO 21. CLASSES

getY(); void setRed(double red); double getRed(); H dois mtodos para denir as funes membro:
void setBlue(double blue); double getBlue(); void set-
Green(double green); double getGreen(); private: int Eles podem ser denidos dentro da classe, o que
_width; int _height; int _x; int _y; double _red[400][400]; apropriado para funes pequenas;
double _blue[400][400]; double _green[400][400]; bo-
olean isWithinSize(int s); double clipIntensity(double E funes grandes podem ser denidas fora da
brightness); }; classe.

Neste caso tero de ser identicadas como pertencentes


classe e para isso utilizamos o operador de resoluo de
21.5 Especicadores de acesso escopo ::.

Temos as palavras reservadas private e public so


os chamados especicadores de acesso. 21.6 Construtores
private Especica uma faixa de variveis
ou funes que podem ser acessadas exclu- 21.6.1 Conceito
sivamente por membros da classe, de forma
que nenhum outro cdigo fora da mesma possa Os construtores constructors so funes membro (m-
acess-las; todos) especiais de uma classe. Permitem a inicializao
public Especica uma faixa de variveis ou das variveis membro de um objeto. Ou melhor, permi-
funes que podem ser acessadas por qualquer tem a construo e a inicializao de objetos das classes.
cdigo no programa, sendo que para as fun- Se no os declararmos o compilador faz isso por ns. Os
es internas da classe no necessrio espe- construtores tm sempre o mesmo nome que a classe.
cicar o objeto enquanto que para as outras Os objetos so construdos atravs destas funes espe-
partes do programa necessrio especicar o ciais chamadas de construtores. At aqui no os declara-
objeto a qual estas pertencem. mos, eram criados automaticamente. Estas funes tem
certas caractersticas que as fazem distintas das normais,
Esta caracterstica de limitar o acesso e manipulao dos que permitem que as mesmas construam a estrutura l-
membros de uma classe chama-se Encapsulamento. A gica inicial do objeto. Desta forma estas funes so ca-
boa prtica no desenho de classes deve sempre forar o ractersticas da orientao a objetos e servem para cria-
encapsulamento. raramente necessrio ou desejvel ter o dos mesmos.
acesso livre e pblico aos dados internos de uma classe. Construtores no podem ser chamados explicitamente
O encapsulamento visa, primariamente duas metas: como fazemos no caso de funes membro regulares.
Eles so apenas executados quando um novo objeto da
1. Eliminar a necessidade de conhecimento da estru- classe criado. Portanto, existe apenas um evento capaz
tura interna por quem deseja us-la. Por exemplo, se de executar um construtor, a instanciao do objeto.
os objetos precisam manter um conjunto de 4 bytes, As principais caractersticas dos construtores so:
isto pode ser conseguido usando-se duas variveis
short int, uma int, um vetor com 4 characteres, ou No tm qualquer valor de retorno;
a variao de qualquer um dos anteriores sem sinal,
mas estes detalhes no precisam estar expostos. No podem ser executados por chamada explcita no
cdigo;
2. Se a representao interna dos dados for modicada,
desde que os tipos de retorno e de parmetros das So executados logo depois que os tipos bsicos do
funes pblicas mantenham-se inalteradas, no ne- objeto foram criados;
cessitemos de alterar cdigo que utilizem objetos da
classe. Inicializam os dados com os valores que o objeto
precisa para comear a funcionar corretamente.
Ou seja, o encapsulamento simplica a programao es-
condendo as particulariadades da classe e elimina o retra-
21.6.2 Declarao
balho do cdigo por alteraes da mesma. Geralmente as
funes (mtodos) privadas, so auxiliares a outras fun- Podemos criar construtores facilmente, atravs das carac-
es da classe. tersticas que os distinguem das funes membro conven-
Se nenhum especicador de acesso for usado, todos os cionais. Ou seja, denimos uma funo membro que pos-
membros e metodos so declarados como privados por sua o mesmo nome da classe, no tenha tipo de retorno e
padro. a declaramos como pblica para que possa ser acessada
21.8. COPY CONSTRUCTORS 57

por quem queira instanciar objetos. Vejamos como de- O construtor tem o mesmo nome que a classe;
nir um construtor:
O destrutor tem o mesmo nome que a classe com o
class Caneta { string cor; int volume; /////////////// public: prexo de tilde ~;
Caneta( string c, int v ); }; Caneta::Caneta( string c, int v
) { cor = c; volume = v; } O construtor foi usado para inicializar as variveis
membro, mas noutros exemplos poderia alocar me-
Construtores podem iniciar os membros da classe de uma mria, tomar controle de recursos como dispositivos
forma simplicada. Este formato usado sempre que o de sistema e executar inicializaes de cdigo;
construtor tem dados bsicos que podem ser iniciados an-
tes do resto da construo da estrutura do objeto. Pode- O destrutor no exemplo no faz nenhuma ao real,
mos iniciar os dados do objeto declarando-o desta forma: para alm de fazer o eco informando que foi cha-
mado.
class Caneta { string cor; int volume; /////////////// public:
Caneta( string c, int v ) : cor(c), volume(v) { } };
21.8 copy constructors
Para faz-lo, como vemos no cdigo, basta listar as va-
riveis membro em uma sequncia depois da declarao
Um copy constructor um construtor especial que toma
do nome do construtor e de um sinal de dois pontos ":".
como argumento a referncia de um objeto da mesma
Iniciamos uma lista de membros, com o valor a ser atri-
classe e cria um novo objeto que a copia do objeto
budo entre parnteses depois de cada um, separando-os
em referncia. Por padro, o compilador providencia um
por vrgulas.
copy constructor que faz a cpia membro por membro
do objeto original, construindo um objeto idntico. Isto
chamado de shallow copy ou member wise.
21.7 Destrutores Em algumas situaes a cpia de um objeto no satisfa-
tria, para ver isso vamos ver a classe employee, abaixo:
21.7.1 Conceito #include <iostream> #include <string.h> using na-
mespace std; class Employee { public: Employee(char
Alm do construtor a linguagem C++, assim como ou- *name, int id); ~Employee(); char *getName(){return
tras linguagens orientadas a objeto, possuem outro tipo _name;} private://Other Accessor methods int _id;
de funo especialmente criada e gerenciada pela lingua- char *_name; }; Employee::Employee(char *name, int
gem, os destrutores. Estas so destinadas a desmontar a id) { _id = id; _name = new char[strlen(name) + 1];
estrutura do objeto quando o mesmo est sendo encer- //Allocates an character array object strcpy(_name,
rado. O destrutor ter o mesmo nome da classe, mas pre- name); } Employee::~Employee() { delete _name; } int
cedido pelo sinal til ~ e tambm no retorna valor. main() { Employee programmer(John,22); cout <<
O destrutor tem as seguintes caractersticas: programmer.getName() << endl; return 0; }

O destrutor chamado quando o objeto est sendo A funo strlen retorna o tamanho da string passada pelo
nalizado; constructor. Repare que o nome do employee agora
guardado num carcter array dinmico. o string lenght
usado para liberar qualquer memria que tenha +1 para permitir o null terminator usado no estilo c.
sido alocada; A funo strcpy automaticamente adiciona o null termi-
nator a string destino.

21.7.2 Declarao Note tambm que o destrutor liberta a memoria usada


para guardar o employee name, para evitar memory leak.
Faamos a classe Dog com o construtor e o destrutor. Agora imagine que o john promovido:
class Dog { public: Dog(); //Constructor ~Dog(); int main() { Employee programmer(John,22); cout
//Destructor void setAge(int age); int getAge(); void << programmer.getName() << endl; //Lots of code ....
setWeight(int weight); int getWeight(); void speak(); Employee manager(&programmer); //Creates a new
private: int age; int weight; }; Dog::Dog() { age = 0; Employee manager, //which is an exact copy of the
weight = 0; cout << Dog Constructor Called << endl; //Employee programmer. return 0; }
} Dog::~Dog() { cout << Dog Destructor Called <<
endl; } Este programa contm um bug srio e morre com uma
exceo quando executado. O problema que o cons-
Repare que: trutor que est sendo usado para criar um objeto ma-
58 CAPTULO 21. CLASSES

nager, mas ele copia o endereo no ponteiro _name em


manager.
Nos temos 2 pointers ambos contendo o mesmo ende-
reo. Imagine que agora um novo empregado contra-
tado. quando o nome for atualizado, no apenas iremos
alterar o nome do empregado mas tambm do gerente.
Finalmente, quando os objetos deixarem de ser usados e
o destrutor da classe zer a liberao de espao na me-
mria tentar liberar duas vezes para o mesmo endereo,
provocando um erro no sistema de alocao dinmica de
memria, o que forar o sistema operacional a eliminar
o programa da memria.
Para resolver esse problema podemos denir um constru-
tor de cpia (copy constructor) na classe, substituindo
a implementao padro do compilador. Este recurso
automaticamente identicado e faz com que o compila-
dor no crie a sua verso do construtor. Assim, denir
um construtor de cpia prprio a maneira mais eci-
ente quando nossos objetos detm caractersticas que os
fazem diferentes do padro.
Para criar o construtor basta den-lo na classe:
class Employee { public: Employee( const Employee &
e); Employee(char *name, int id); ~Employee(); char
*getName(){return _name;} private://Other Accessor
methods int _id; char *_name; }; Employee::Employee(
const Employee & e ) { _id = e._id; _name = new
char[strlen(e._name) + 1]; //Allocates an character array
object strcpy(_name, e._name); }

Agora temos um construtor que pode fazer a cpia da


forma correta. Neste novo construtor alocamos uma ca-
deia de caracteres para copiar o contedo da original no
objeto a ser copiado e copiamos o contedo para o novo
objeto. Assim, teremos objetos distintos, cada um com
seu prprio contedo.

21.9 Ver tambm


Programao orientada a objetos/Classes e Objetos
- conceitos tericos
Captulo 22

Encapsulamento

22.1 Conceito para no dependermos de conceitos de herana que tam-


bm precisa de tpicos de encapsulamento, faremos uma
Encapsulamento, em linguagens orientadas a objeto, a pequena introduo dos conceitos de classes derivadas
capacidade de ocultao de detalhes de implementao antes de prosseguirmos com o nosso estudo de encapsu-
por parte de entidades de manipulao de dados. Esta lamento.
caracterstica visa prover um meio de manter cada classe Uma classe pode ser estendida a partir de outra, ou seja,
responsvel por operaes a elas atribudas sem interfe- podemos reaproveitar um cdigo j existente em uma de-
rncias externas. A vantagem dessa caracterstica de terminada classe que j temos e criar uma nova classe
manter os indivduos de cada classe com funes bem de- com tudo que j existia na primeira, mais o que denir-
limitadas e criar meios de criar mdulos onde cada classe mos para a nova.
faa bem aquilo de que est encarregada, tendo total con-
Vejamos um exemplo bsico:
trole sobre tais operaes.
class veculo { string cor; string combustivel; ... ... };
class carro : public veiculo { int nrodas; ... ... int mover(
int nkilometros ); };
22.2 Atributos de restrio
A segunda classe declarada possui a extenso ": public
Classes podem proteger sua estrutura de acessos de ou-
veiculo" a mais, esta parte refere-se a uma declarao de
tras entidades de dados que no pertencem a seu corpo.
parentesco. De fato, ao declarar a classe desta forma es-
Para isto, em C++ temos atributos de acesso para blocos
tamos informando ao compilador que a classe veiculo
de dados ou funes membros de classes. Em algumas
me da classe carro. Semanticamente, isto signica que
linguagens os atributos so denidos para cada membro
a classe carro possui toda a estrutura da classe veiculo
individualmente.
alm de seus prprios membros.
Os atributos de restrio de acesso em C++ so trs: pri-
vate, public e protected. Cada atributo oferece um nvel
de ocultao para membros de classes. Eles so usados 22.2.2 Denindo acessos
para assegurar que apenas grupos identicados de cdigo
tenham acesso a partes presselecionadas da classe. Considerando o exemplo anterior, podemos observar que
os atributos cor, combustivel, nrodas poderiam ser
Os nveis de proteo esto ligados ao parentesco do c- alterados em qualquer ponto do programa se tivssemos
digo que pretende acesso com a classe em que os mes- usado a palavra struct, porm usando a palavra class algo
mos esto denidos. Mais especicamente, classes que de diferente ocorre, pois no podemos ter acesso a estes
no so lhas da que pretendem acessar s podero ter atributos, a menos que estejamos acessando-os atravs de
acesso a membros pblicos, classes lhas tero acesso a funes denidas dentro das classes.
membros protegidos (protected) ou pblicos (public) e
nalmente, nenhum cdigo que no pertena a prpria Em classes, o atributo private denido por padro, ou
classe poder acessar membros privados (private). seja, os membros que no tenham denidos os seus atri-
butos de acesso explicitamente, sero denidos como pri-
vados. Este comportamento revela a necessidade de res-
22.2.1 Classes derivadas (pequena intro- guardar os membros de uma classe atravs de atributos de
duo) restries. Em C++, ao denir membros em uma classe
antes da denio de qualquer atributo de restrio esta-
Precisamos dos conceitos bsicos de herana para enten- mos denindo-os como privados (private).
der alguns conceitos de encapsulamento. Para no cri- Ainda levando em considerao o exemplo anterior, po-
armos dependncias circulares entre os tpicos, ou seja, demos denir atributos de restries para grupos de

59
60 CAPTULO 22. ENCAPSULAMENTO

membros e modicar o comportamento padro da classe.


Se denirmos public, os dados estaro acessveis a qual-
quer parte do programa, o que equivalente a coloca-los
em uma estrutura com a palavra struct ao invs de den-
tro de uma classe. Se denirmos protected temos uma
situao peculiar, apenas funes membro da classe ou
de suas "lhas" podero acessar dados da classe me.
Vejamos o exemplo anterior com algumas alteraes:
class veiculo { string cor; protected: string combustivel;
... ... public: bool altCor( string c ) { if ( c == vermelho
) { cor = c; return true; } if ( c == azul ) { cor = c;
return true; } if ( c == prata ) { cor = c; return true; }
return false; } }; class carro : public veiculo { int nrodas;
... ... int mover( int nkilometros ); };

Neste exemplo denimos que o atributo cor no pode ser


modicado, a no ser pela funo altCor(), onde restrin-
gimos as cores a um conjunto que desejamos. Observe
que ao tentar atribuir qualquer cor diferente de verme-
lho, azul e prata, receberemos um retorno "false".
Assim, temos a possibilidade de controlar o comporta-
mento do objeto criado atravs da restrio imposta.
O atributo combustvel ser manipulado livremente
pela classe veculo e pela classe carro, visto que o
atributo protected d visibilidade s classes derivadas de
veiculo. O mesmo mecanismo de controle visto no pa-
rgrafo anterior poder ser implementado para acessos
fora do escopo das duas classes, ou seja, para funes no
escopo global ou em outras classes.

22.3 Escopos globais


At aqui vimos os atributos de restrio sendo usados
em classes para encapsular partes internas a elas, po-
rm, existe outro mecanismo de encapsulamento muito
til em C++, os namespaces. Estes espaos de nomes
so meios de delimitar reas onde smbolos so usados,
o que permite evitar que erros ocorram por coincidncia
de nomes.
A sintaxe para criao de um namespace bem simples.
Vejamos um exemplo de cdigo, para observarmos os de-
talhes:
namespace MeuEspaco { void print() { cout << Funo
de imprimir no meu espaco << endl; } } namespace
EspacoAlheio { void print() { cout << Funo de
imprimir no Espaco alheio << endl; } }
Captulo 23

Herana

23.1 Conceito 23.2 Sintaxe

Para declarar uma classe derivada de outra j existente,


Herana um dos pontos chave de programao orien- procedemos de forma a declarar o parentesco e o grau de
tada a objetos (POO). Ela fornece meios de promover a visibilidade (acesso) que a classe derivada ter dos mem-
extensibilidade do cdigo, a reutilizao e uma maior co- bros de sua classe base. Para isso seguimos o seguinte
erncia lgica no modelo de implementao. Estas carac- cdigo sinttico:
tersticas nos possibilitam diversas vantagens, principal- class classe_derivada : [<acesso>] classe_base { //corpo
mente quando o mantemos bibliotecas para uso futuro de da classe derivada }
determinados recursos que usamos com muita frequn-
cia.
Repare que temos o operador ":" ( dois pontos ) como elo
Uma classe de objetos veiculo, por exemplo, contm to- entre as duas classes. Este operador promove o paren-
das as caractersticas inerentes aos veculos, como: com- tesco entre as duas classes quando usado na declarao
bustvel, autonomia, velocidade mxima, etc. Agora po- de uma classe derivada.
demos dizer que carro uma classe que tm as caracte- O termo [<acesso>] opcional, mas se estiver presente
rsticas bsicas da classe veculo mais as suas caracte- deve ser public, private ou protected. Ele dene o grau de
rsticas particulares. Analisando esse fato, podemos con- visibilidade dos membros da classe base quando a classe
cluir que poderamos apenas denir em carro suas ca- derivada precisar acess-los.
ractersticas e usar veculo de alguma forma que pu-
dssemos lidar com as caractersticas bsicas. Este meio Exemplo de implementao:
chama-se herana. // Demonstra herana. #include <iostream> using
Agora podemos denir outros tipos de veculos como: namespace std; class veiculo_rodoviario // Dene uma
moto, caminho, trator, helicptero, etc, sem ter que re- classe base veculos. { int rodas; int passageiros; public:
escrever a parte que est na classe veculo. Para isso void set_rodas(int num) { rodas = num; } int get_rodas()
dene-se a classe veculo com suas caractersticas e de- { return rodas; } void set_pass(int num) { passageiros
pois cria-se classes especcas para cada veculo em par- = num; } int get_pass() { return passageiros; } }; class
ticular, declarando-se o parentesco neste instante. caminhao : public veiculo_rodoviario // Dene um
caminhao. { int carga; public: void set_carga(int size)
Outro exemplo: Imagine que j exista uma classe que de- { carga = size; } int get_carga() { return carga; } void
na o comportamento de um dado objeto da vida real, mostrar(); }; enum tipo {car, van, vagao}; class automo-
por exemplo, animal. Uma vez que eu sei que o leo vel : public veiculo_rodoviario // Dene um automovel.
um animal, o que se deve fazer aproveitar a classe ani- { enum tipo car_tipo; public: void set_tipo(tipo t) {
mal e fazer com que a classe leo derive (herde) da classe car_tipo = t; } enum tipo get_tipo() { return car_tipo; }
animal as caractersticas e comportamentos que a mesma void mostrar(); }; void caminhao::mostrar() { cout <<
deve apresentar, que so prprios dos indivduos classi- rodas: " << get_rodas() << "\n"; cout << passageiros:
cados como animais. " << get_pass() << "\n"; cout << carga (capacidade em
Ou seja, herana acontece quando duas classes so pr- litros): " << carga << "\n"; } void automovel::mostrar()
ximas, tm caractersticas mtuas mas no so iguais e { cout << rodas: " << get_rodas() << "\n"; cout <<
existe uma especicao de uma delas. Portanto, em vez passageiros: " << get_pass() << "\n"; cout << tipo: ";
de escrever todo o cdigo novamente possvel poupar al- switch(get_tipo()) { case van: cout << van\n"; break;
gum tempo e dizer que uma classe herda da outra e depois case car: cout << carro\n"; break; case vagao: cout <<
basta escrever o cdigo para a especicao dos pontos vagao\n"; } } int main() { caminhao t1, t2; automovel
necessrios da classe derivada (classe que herdou). c; t1.set_rodas(18); t1.set_pass(2); t1.set_carga(3200);

61
62 CAPTULO 23. HERANA

t2.set_rodas(6); t2.set_pass(3); t2.set_carga(1200); forma as informaes esto presentes,


t1.mostrar(); cout << "\n"; t2.mostrar(); cout << mas s podem ser acessadas atravs de
"\n"; c.set_rodas(4); c.set_pass(6); c.set_tipo(van); funes publicas ou protegidas da classe
c.mostrar(); #ifdef WIN32 system (pause); #endif base.
return 0; }
Membros protegidos (protected) da classe
Na implementao acima temos a classe base vei- base:
culo_rodoviario e duas classes derivadas : caminhao e Se tivermos membros protegidos (protec-
automovel. Podemos notar que as caractersticas comuns ted) na classe derivada, eles se compor-
a todos os tipos de veculos, rodas e passageiros, esto na tam como se tivessem sido copiados para
classe base, enquanto as caractersticas exclusivas de cada a classe derivada como protegidos (pro-
tipo de veculo esto nas classes derivadas. Desta forma tected).
podemos denir procedimentos especializados para cada
classe, fazendo com que todas as eventuais modicaes Classe base herdada como private:
feitas ao longo da implementao na classe base sejam
estendidas a todos os objetos criados a partir das classes
derivadas no programa. Membros pblicos (public) da classe base:
Os membros se comportam como se ti-
Repare ainda um pormenor: tanto a classe caminhao
vessem sido copiados como privados (pri-
quanto a automovel tm como funo membro o mtodo
vate) na classe derivada.
mostrar(), mas uma no interfere com a outra. Isto ilus-
tra um outro aspecto da orientao a objeto, o polimor-
smo. Este ser exposto em mais detalhe nos captulos Membros privados (private) da classe base:
subsequentes. Os membros esto presentes na classe,
porm ocultos como privados. Desta
forma as informaes esto presentes,
23.3 Controle de acesso classe mas no podero ser acessadas, a no ser
por funes da classe base que se utilizem
base delas.

Quando uma classe herda outra, os membros da classe Membros protegidos (protected) da classe
base so incorporados como membros da classe derivada. base:
Devido separao das classes e do controle de acesso s
variveis em cada classe, devemos pensar como as res- Os membros se comportam como se ti-
tries de acesso so gerenciadas em classes diferentes, vessem sido copiados como privados (pri-
principalmente o acesso a membros da classe base a par- vate) na classe derivada.
tir das classes derivadas.
Classe base herdada como Protected:
O acesso dos membros da classe base classe derivada
determinado pelo especicador de acesso: public, pri-
vate e protected. Por defaut (padro) temos o private, Membros pblicos (public) da clase base:
ou seja, como temos a opo de no explicitar o especi- Se comportam como se tivssemos
cador de acesso, se este no estiver presente o compilador copiado-os como protegidos (protected)
usar private durante a interpretao do cdigo. na classe derivada
Assim camos com as possveis combinaes
Membros privados (private) da classe base:
Classe base herdada como public: Os membros esto presentes na classe,
porm ocultos como privados. Desta
forma as informaes esto presentes,
Membros pblicos (public) da classe base:
mas no podero ser acessadas, a no ser
como se copissemos os membros da por funes da classe base que se utilizem
classe base e os colocssemos como pu- delas.
blic na classe derivada. No nal, eles
permanecem como pblicos. Membros protegidos (protected) da classe
base:
Membros privados (private) da classe base: Se comportam como se estivssemos
Os membros esto presentes na classe, copiado-os como protegidos (protected)
porm ocultos como privados. Desta na classe derivada.
23.5. CONSTRUTORES E DESTRUTORES 63

Em suma, estas regras podem ser sintetizadas em uma x; public: void showx() { cout << x << "\n"; } }; class
regra muito simples: Prevalece o atributo mais restritivo. base2 { protected: int y; public: void showy() { cout <<
Para isto basta-nos listar os atributos por ordem de res- y << "\n"; } }; class derived: public base1, public base2
tries decrescente: // Inherit multiple base classes. { public: void set(int i,
int j) { x = i; y = j; } }; int main() { derived ob; ob.set(10,
1. private 20); // Disponvel pela classe derived ob.showx(); //
Pela classe base1 ob.showy(); // Pela classe base2 #ifndef
2. protected
WIN32 system (pause); #endif return 0; }
3. public
Repare que utilizamos o operador vrgula para dizer ao
Assim, temos todas as combinaes denidas quando co- compilador que a classe derivada herda mais de uma
locamos um atributo combinado com o outro, bastando classe. Com efeito, temos uma lista de classes separadas
para isto escolher sempre o mais restritivo na combina- por vrgulas depois do operador ":" (dois pontos).
o. Por exemplo: Quando temos uma varivel pblica
na base e a herana privada, a combinao resulta em Quando queremos que a classe derivada herde uma classe
uma varivel privada na classe derivada. como pblica e outra como privada ou protegida basta
preceder a classe com o seu especicador de acesso. Da
Aqui est um exemplo muito simples: mesma forma, a omisso do especicador leva o compi-
#include <iostream> using namespace std; class base lador a usar o padro que privado (private).
{ int i, j; public: void set(int a, int b) { i = a; j = b; }
void show() { cout << i << " " << j << "\n"; } }; class
derived : public base { int k; public: derived(int x) { k = 23.5 Construtores e destrutores
x; } void showk() { cout << k << "\n"; } }; int main() {
derived ob(3); ob.set(1, 2); // acesso a membro da base
ob.show(); // acesso a membro da base ob.showk(); // Temos uma srie de classes que mantm relaes de pa-
uso de membro da classe derivada #ifdef WIN32 system rentesco conforme mostramos nas sees anteriores. Em
(pause); #endif return 0; } termos genricos, classes que herdam caractersticas de
uma base precisam de regras claras quando forem criadas
e destrudas. Precisamos denir a sequncia em que os
Conseguimos acessar as funes set() e show() porque so construtores e destrutores sero chamados, uma vez que
heradadas como publicas. cada classe tem pelo menos um construtor e um destrutor.
Agora modiquemos o atributo de acesso na declarao Agora temos a questo: Quando que os construtores so
da herana da classe base: chamados quando eles so herdados?
#include <iostream> using namespace std; class base
{ int i, j; public: void set(int a, int b) { i = a; j = b; } Quando um objeto da classe derivada instanci-
void show() { cout << i << " " << j << "\n"; } }; class ado, o construtor da classe base chamado pri-
derived : private base { int k; public: derived(int x) { k meiro seguido do construtor das classes derivadas,
= x; } void showk() { cout << k << "\n"; } }; int main() em sequncia da base at a ltima classe derivada.
{ derived ob(3); ob.set(1, 2); // Erro, no possvel
acessar set() ob.show(); // Erro, no possvel acessar Quando o objeto da classe derivada destrudo, o
show() ob.showk(); // uso de membro da classe derivada seu destrutor chamado primeiro seguido dos des-
#ifdef WIN32 system (pause); #endif return 0; } trutores das outras classes derivadas logo abaixo, em
sequncia at a base.
Agora j no podemos acessar as funes porque esto
privadas. Vamos testar e ver como isto funciona.
No caso em que termos herana sequencial A-B-C, tere-
mos:
23.4 Heranas mltiplas
#include <iostream> using namespace std; class base {
public: base() { cout << Construindo base << endl; }
Podemos ter a situao em que uma classe derivada possa ~base() { cout << Destruindo base << endl; } }; class
herdar membros de vrias classes base. Esta caracters- derivada1 : public base { public: derivada1() { cout
tica uma distino entre C++ e outras linguagens orien- << Construindo derivada1 << endl; } ~derivada1()
tadas a objeto. Este recurso d mais poder de modelagem { cout << Destruindo derivada1 << endl; } }; class
ao programador, mas vale a pena lembrar que mais poder derivada2: public derivada1 { public: derivada2() { cout
exige mais cautela no uso. << Construindo derivada2\n"; } ~derivada2() { cout <<
// Um exemplo de mltiplas classes base. #include <ios- Destruindo derivada2\n"; } }; int main() { derivada2
tream> using namespace std; class base1 { protected: int ob; // constri e destri o objeto ob #ifdef WIN32
64 CAPTULO 23. HERANA

system (pause); #endif return 0; } derivada(int x, int y): base(y) { j = x; cout << Cons-
truindo derivada\n"; }// derivada usa x; y passada em
Caso de mltipla herana A - B e C lista para a base. ~derivada() { cout << Destruindo deri-
vada\n"; } void mostrar() { cout << i << " " << j << "\n";
#include <iostream> using namespace std; class base1 } }; int main() { derivada ob(3, 4); ob.mostrar(); // mos-
{ public: base1() { cout << Construindo base1\n"; } tra 4 3 #ifdef WIN32 system (pause); #endif return 0; }
~base1() { cout << Destruindo base1\n"; } }; class
base2 { public: base2() { cout << Construindo base2\n";
} ~base2() { cout << Destruindo base2\n"; } }; class No exemplo, a o construtor da classe derivada decla-
derivada: public base2,public base1 { public: derivada() rado com 2 argumentos (x e y). no entanto a funo deri-
{ cout << Construindo derivada\n"; } ~derivada() { cout vada() usa apenas um para inicializar a varivel interna da
<< Destruindo derivada\n"; } }; int main() { derivada classe, o segundo argumento usado para passar o valor
ob;// construindo e destruindo o objeto. #ifdef WIN32 de inicializao para a classe base.
system (pause); #endif return 0; } Vejamos mais um exemplo:
#include <iostream> using namespace std; class base1
Neste caso a sequncia de inicializao segue ordem esta- { protected: int i; public: base1(int x) { i = x; cout
belecida na lista de herana. Mais explicitamente, temos << Construindo base1\n"; } ~base1() { cout << Des-
a construo das bases: base2 e base1, nesta ordem truindo base1\n"; } }; class base2 { protected: int k;
respectivamente e depois a derivada. O que, automati- public: base2(int x) { k = x; cout << Construindo
camente, nos revela a sequncia de destruio na ordem base2\n"; } ~base2() { cout << Destruindo base2\n";
inversa, ou seja: destroi-se a derivada, depois base1 } }; class derivada: public base1, public base2 { int j;
e, nalmente, a estrutura da base2. public: derivada(int x, int y, int z): base1(y), base2(z) {
j = x; cout << Construindo derivada\n"; } ~derivada() {
cout << Destruindo derivada\n"; } void mostrar() { cout
<< i << " " << j << " " << k << "\n"; } }; int main() {
23.6 Passando parmetros para derivada ob(3, 4, 5); ob.mostrar(); // mostra 4 3 5 #ifdef
construtores da classe base WIN32 system (pause); #endif return 0; }

Agora imaginemos que temos um conjunto de bases para


uma classe que queiramos derivar, ento podemos ter um
construtor em cada base que precise de parmetros para
23.7 Superposio de funes
que possa ser invocado pela nossa classe. Como pode-
remos passar os parmetros, uma vez que os mesmos s Muitas vezes temos classes derivadas que executam uma
podem ser passados durante a inicializao da classe? determinada ao de forma distinta da mesma ao de-
nida na classe base. Por exemplo, se temos uma classe
Para que possamos passar os parmetros para as classes animal e declaramos uma funo chamada mover e
bases durante a inicializao do objeto da classe derivada depois declaramos duas derivadas: ave e peixe com a
temos o recurso de passagem de parmetros pelo constru- mesma funo mover teremos uma incoerncia devido
tor. Basicamente, ele funciona como se passssemos va- ao fato de que peixes se movem de forma totalmente di-
lores para variveis membro. Chamamos cada construtor ferente de aves. Uma vez que peixes devem nadar e
na lista de passagem de valores, a sintax para declarar o aves podem voar ou andar nosso modelo de obje-
corpo do construtor a seguinte: tos est incorreto.
class Classe_derivada : public Base1, public
Por questes de coerncia semntica, porm, precisamos
Base2, ..., public BaseN { // Membros... pu- manter o mesmo nome para as funes das classes base e
blic: Classe_derivada(lista_de_argumentos); derivada em algumas construes. Isto essencial devido
// Outras funes... }; a necessidade de criarmos objetos generalistas, por exem-
Classe_derivada::Classe_derivada(lista_de_argumentos) plo se tivermos classes ave e peixe abstradas em uma
: Base1(lista_de_argumentos), base animal, como vimos acima. Havendo estas condi-
Base2(lista_de_argumentos), ...Ba- es, como poderemos criar comportamentos diferentes
seN(lista_de_argumentos); { //Corpo do construtor usando o mesmo nome para as funes?
da classe derivada }
A resposta est em uma das caractersticas que ser muito
til quando quisermos usar de polimorsmo, que iremos
Este exemplo um pouco mais complexo, ateno! abordar em captulo especco mais adiante: a ocultao
#include <iostream> using namespace std; class base e superposio de funes da classe base a partir de uma
{ protected: int i; public: base(int x) { i = x; cout << classe derivada (conhecida como overriding em manu-
Construindo base\n"; } ~base() { cout << Destruindo ais de compiladores). Com este recurso podemos decla-
base\n"; } }; class derivada: public base { int j; public: rar em uma classe derivada uma funo com nome e pa-
23.9. VER TAMBM 65

rmetros idnticos a uma existente em uma classe base, 23.9 Ver tambm
porm com contedo diferente.
Vejamos o exemplo de cdigo e teremos uma noo mais Programao orientada a objetos/Herana - conceito
concreta do que foi explanado:
#include <iostream> using namespace std; class animal {
public: void comer(); void mover(); void dormir() { cout
<< Dormindo... << endl; } }; ... ... class ave : public
animal { public: void comer(){ cout << Bicando... <<
endl; } void mover(){ cout << Voando... << endl; } };
... ... class peixe : public animal { public: void comer(){
cout << Mordendo... << endl; } void mover(){ cout <<
Nadando... << endl; } }; int main() { ave passarinho;
peixe sardinha; passarinho.mover(); sardinha.mover();
#ifdef WIN32 system(pause); #endif return 0; }

Ao executar o programa gerado por este cdigo percebe-


mos que a mesma funo: mover(), ter comportamento
diferente quando invocada por objetos de classes diferen-
tes. O programa mostrar a mensagem Nadando... para
a funo invocada pelo objeto sardinha e Voando...
para a invocada pelo objeto passarinho. Aqui, o meca-
nismo bem simples de se entender, quando cada objeto
tem uma verso diferente para a mesma funo fcil
para o compilador relacionar o objeto classe que ele
pertence e invocar a funo apropriada.

23.8 Acessando funes superpos-


tas da classe base

O mecanismo para obter acesso s classes base a partir da


classe derivada intuitivo. Para isto usamos o operador
de resoluo de escopo, composto por um par de dois
pontos "::", usando a seguinte sintaxe:
<CLASSE>::<FUNO>(lista_de_parmetros);
Ou seja, basta invocar a funo informando qual a ver-
so especca que se deseja utilizar. Se tivermos uma
classe A e outra B com uma funo Print()", por
exemplo, e quisermos usar a funo Print()" da classe
B fazemos:
B::Print();

Talvez seja melhor visualizar um exemplo no cdigo mais


completo:
class B { public: void Print() { cout << Chamando
Print() da classe B. << endl; } }; class A : public B {
public: void Print() { cout << Chamando Print() da
classe A. << endl; B::Print(); } }; int main() { A ca;
ca.Print(); return 0; }
Captulo 24

Polimorsmo

24.1 Conceito 24.5 Construtor de cpia virtual


Polimorsmo em linguagens orientadas a objeto, a ca-
pacidade de objetos se comportarem de forma diferen- 24.6 Classe base virtual
ciada em face de suas caractersticas ou do ambiente
ao qual estejam submetidos, mesmo quando executando Consideremos o seguinte programa:
ao que detenha, semanticamente, a mesma designao.
// Este programa contm um erro e no ser compilado.
O polimorsmo em C++ se apresenta sob diversas for- #include <iostream> using namespace std; class base {
mas diferentes, desde as mais simples, como funes com public: int i; }; class derived1 : public base // derived1
mesmo nome e lista de parmetros diferentes, at as mais inherits base. { public: int j; }; class derived2 : public
complexas como funes virtuais, cujas formas de execu- base // derived2 inherits base. { public: int k; }; /* *
o so dependentes da classe a qual o objeto pertence e derived3 herda caractersticas de derived1 e deri-
so identicadas em tempo de execuo. ved2. * Isto signica que h duas cpias da base em
derived3"! */ class derived3 : public derived1, public
derived2 { public: int sum; }; int main() { derived3 ob;
ob.i = 10; // Isto se torna ambguo; A qual i estamos
24.2 Funes virtuais nos referindo??? ob.j = 20; ob.k = 30; ob.sum = ob.i +
ob.j + ob.k;// i ambguo aqui, tambm cout << ob.i <<
#include <iostream> using std::cout; using std::endl; " ";// tambm ambguo, Qual i"? cout << ob.j << " "
class Base { public: // declarao da funo virtual << ob.k << " "; cout << ob.sum; #ifdef WIN32 system
virtual void Quem_VIRTUAL() { cout << Base\n"; (pause); #endif return 0; }
} // funo comum void Quem_NAO_VIRTUAL() {
cout << Base\n"; } }; class Derivada : public Base
As classes derived1 e derived2 so herdadas como classes
{ public: // funo virtual sobrescrita virtual void
base. A classe derived3 herda tanto de derived1 quanto
Quem_VIRTUAL() { cout << Derivada\n"; } // funo
de derived2. Como resultado temos 2 cpias da classe
comum sobrescrita void Quem_NAO_VIRTUAL() {
base presentes no objeto da derived3, por exemplo pre-
cout << Derivada\n"; } }; int main () { Base *ptr_base;
sente na linha ob.i=10; isto resulta numa ambiguidade e
Derivada derivada; ptr_base = &derivada; // converso
o programa no vai compilar.
implcita permissvel ptr_base->Quem_VIRTUAL(); //
chamada polimrca (mostra: Derivada) ptr_base- H duas maneiras para remediar a situao:
>Quem_NAO_VIRTUAL(); // chamada comum, 1. Aplicar o operador de resoluo de escopo manual-
no-polimrca (mostra: Base) cout << endl; return 0; mente:
}
//Este programa usa resoluo de escopo explicita para
selecionar i. #include <iostream> using namespace
std; class base { public: int i; }; class derived1 : public
base // derived1 inherits base. { public: int j; }; class
24.3 Chamando mltiplas funes derived2 : public base // derived2 inherits base. {
public: int k; }; class derived3 : public derived1, public
virtuais derived2 /* derived3 herda as bases derived1 e
derived2. Isto signica que h duas cpias de bases
24.4 Funes virtuais e passagem em derived3"! */ { public: int sum; }; int main() {
derived3 ob; ob.derived1::i = 10; // escopo resolvido,
por valor usa o i em derived1. ob.j = 20; ob.k = 30; ob.sum
= ob.derived1::i + ob.j + ob.k; // escopo resolvido. cout

66
24.6. CLASSE BASE VIRTUAL 67

<< ob.derived1::i << " "; // tambm resolvido aqui. cout


<< ob.j << " " << ob.k << " "; cout << ob.sum; #ifdef
WIN32 system (pause); #endif return 0; }

2. A segunda maneira atravs de classes bases virtu-


ais:
Quando temos 2 ou mais objetos que so derivados da
mesma base class, podemos prevenir mltiplas cpias da
base class declarando a base class como virtual quando
ela herdada. Exemplicando:
// Este program usa classes bases virtuais. #include
<iostream> using namespace std; class base { public:
int i; }; class derived1 : virtual public base // derived1
inherits base as virtual. { public: int j; }; class derived2
: virtual public base // derived2 inherits base as virtual.
{ public: int k; }; class derived3 : public derived1,
public derived2 /* derived3 inherits both derived1 and
derived2. This time, there is only one copy of base
class. */ { public: int sum; }; int main() { derived3
ob; ob.i = 10; // now unambiguous ob.j = 20; ob.k =
30; ob.sum = ob.i + ob.j + ob.k;// unambiguous cout
<< ob.i << " ";// unambiguous cout << ob.j << " " <<
ob.k << " "; cout << ob.sum; system (pause); return 0; }

Repare que agora temos a palavra virtual antes da classe.


Captulo 25

Friend

25.1 Friend functions


O uso de funes amigas deve ser evitado sempre que
25.2 O que possvel, pois diminui a identidade da orientao a obje-
tos. Isto ocorre porque o uso desse mecanismo representa
uma quebra no encapsulamento. Quando passamos a per-
Friend um atributo especial de acesso a classes. Com ele mitir que funes tenham acesso a membros restritos dos
declaramos que uma funo fora de uma classe amiga objetos fazemos com que agentes externos interram na
da mesma. autonomia dos mesmos. Isto pode dicultar a anlise de
Declarando que uma funo (externa classe) friend programas muito extensos.
dentro de uma classe, permite que a funo (a amiga) No caso da criao de procedimentos que tem a nalidade
possa ler e manipular membros (variveis e funes de modicar o contedo do objeto explicitamente, como
membro) private - privados e protected - protegidos nos casos de operadores e modicadores de comporta-
(e claro public - publicas, mas isso j era permitido an- mento, podemos usar as funes amigas friends para
tes de serem friends). esta nalidade tomando os devidos cuidados para torn-
Considerando que o acesso a membros pode ser restrito las muito bem restritas as funes que devem executar.
para determinadas partes do cdigo, podemos adotar uma muito importante observar se estas funes alteram dados
postura mais exvel para funes que conhecemos como dentro dos objetos que no podem ser modicados. Se as
conveis e evitar os inconvenientes da restrio a mem- devidas precaues forem tomadas no haver problemas
bros por cdigos que no provoquem problemas maiores no uso de funes friend.
a nossa estrutura da aplicao.

25.4 Friend classes


25.3 Declarar funes friend
Da mesma forma que podemos declarar funes como
O processo para fazer com que funes fora do escopo amigas de uma determinada classe, podemos declarar ou-
da classe tenham acesso a membros sem nenhuma restri- tra classe como sua amiga. Este artifcio faz com que
o muito simples. Para isto apenas temos de colocar os membros da classe onde foi feita a declarao sejam
o prottipo da funo externa dentro da classe precedido acessveis declarada. Assim, a segunda classe passa a
da palavra friend. Desta forma o compilador passa a ig- ter possibilidade de manipulao livre dos membros da
norar os atributos de restrio de acesso da classe quando outra.
a funo acessa membros da mesma. Apesar da funcionalidade ser um pouco semelhante
Vamos ao exemplo: que temos no uso das funes, quando declaramos uma
// friend functions #include <iostream> using namespace classe como friend dentro de outra, teremos todas as
std; class CRectangle { int width, height; public: void funes da primeira com poderes de acesso aos membros
set_values (int, int); int area () {return (width * height);} da segunda. Esta caracterstica requer cuidado redobrado
friend CRectangle duplicate (CRectangle); }; void quando operaes da classe friend interferem no con-
CRectangle::set_values (int a, int b) { width = a; height tedo da outra.
= b; } CRectangle duplicate (CRectangle rectparam) { // friend class #include <iostream> using namespace
CRectangle rectres; rectres.width = rectparam.width*2; std; class CSquare; class CRectangle { int width, height;
rectres.height = rectparam.height*2; return (rectres); public: int area () {return (width * height);} void convert
} int main () { CRectangle rect, rectb; rect.set_values (CSquare a); //consigo acessar porque friend }; class
(2,3); rectb = duplicate (rect); cout << rectb.area(); CSquare { private: int side; public: void set_side (int
system (pause); return 0; } a) {side=a;} friend class CRectangle; //declaro friend

68
25.4. FRIEND CLASSES 69

class }; void CRectangle::convert (CSquare a) { width


= a.side; height = a.side; } int main () { CSquare sqr;
CRectangle rect; sqr.set_side(4); rect.convert(sqr); cout
<< rect.area(); system (pause); return 0; }

Nota:

No h a propriedade de reciprocidade (ou re-


verso). O facto de uma funo ou classe ser friend
de uma classe no implica o contrrio, ou seja, A ter
B como friend no implica que B a tenha em mesma
conta.
Outra propriedade que no h transitividade. Se
numa class A for declarado que a class B friend. E
depois que na classe B estiver declarado que a classe
C friend de B,Isto no implica que A seja friend
de C.
Captulo 26

Classes internas

26.1 Conceituao
As classes podem ser construdas uma dentro da outra
para uma melhor organizao do cdigo. Esta possibili-
dade nos leva a implicaes a serem consideradas durante
a fase de implementao do cdigo. Devemos vericar as
particularidades de acesso a dados, o que nos leva a di-
versas particularidades devido ao escopo das mesmas.
No exemplo a seguir, temos a implementao bsica de
uma classe interna a outra:
class data { int n; char str[256]; public: class idata { int
x; int y; int z; }; int getn(); char *getstr(); void setstr(
const char *instr); void setn(int inn); };

Uma vez que criamos o prottipo de objeto dentro de ou-


tra classe podemos us-lo atravs do operador de resolu-
o de escopo. Deveremos nos referir ao operador para
acessar o corpo da primeira classe e depois o invocamos
novamente para alcanar a outra. Desta forma, podera-
mos us-la como exemplicado abaixo:
data::idata ni;

importante notar que objetos diferentes tero dados di-


ferentes na regio da classe interna, isso impede que use-
mos dados da classe mais externa dentro das classes in-
ternas. Devido a esta caracterstica as funes dentro da
classe interna no podem acessar dados da classe mais
externa, a menos que sejam estticos, o que no exige
denio do objeto a qual eles pertencem. Portanto, o
uso de classes internas permite um isolamento de parte
dos dados e prover um tratamento diferenciado para os
mesmos.

70
Captulo 27

Sobrecarga de operadores

27.1 Modicando operadores ao compilador como ele deve efetuar a operao do novo
tipo criado.
A linguagem C++ possui os mesmos operadores presen- ponto p1(1,5), p2(3,4), Soma; Soma = p1 + p2;
tes na linguagem C. Estes tm funes padronizadas e
comportamentos semelhantes a seus parentes diretos em
Ao tentar compilar este trecho de cdigo o compilador
C. Esta caracterstica a traz compatibilidade que um re-
retornar um erro por no conhecer a maneira de como
quisito fundamental e adiciona uma nova funcionalidade
operar este tipo de dado. Como criamos o tipo de dado,
chamada sobrecarga de operadores.
precisamos denir como fazer a soma do mesmo. Pode-
Quando operamos tipos nativos da linguagem, fazemos mos fazer a seguinte denio:
com funes especcas predenidas e padronizadas.
class ponto { int x,y; public: ponto(int a, int b) {
Como poderemos operar os nossos objetos que denimos
x = a; y = b; } ponto operator+(ponto p); }; ponto
com nossas classes? Simples: criamos as funcionalidades
ponto::operator+(ponto p) { int a, b; a = x + p.x; b = y +
e as atribuimos a operadores j conhecidos, de forma a
p.y; return ponto(a, b); }
manter a idia bsica da operao embutida na simbolo-
gia.
A sintaxe desta denio, muitas vezes causa confuso,
Ao denir novas funes para os operadores padro, na
mas poder ser facilmente entendida depois que tenha-
verdade no substituimos a sua funo, apenas adiciona-
mos assimilado as idias bsicas por traz dela. Ela opera,
mos mais uma funo ao mesmo operador. Esta operao
aparentemente, apenas um dado de entrada, porm o ope-
chamada de sobrecarga de operador. O nome parece
rador deve somar dois. Como isto possvel? Obser-
um pouco fora do comum, mas apenas reete o compor-
vando mais atentamente o cdigo poderemos entender:
tamento da linguagem quando esta lida com a denio
de vrios tratamentos para o mesmo identicador, que, Vericamos que, no cdigo, nos referimos a x e y sem
neste caso, o smbolo do operador. Portanto, sobre- denir a qual objeto pertence. Acontece que a operao
carga de operador a denio de novas tarefas para o est ocorrendo dentro de um dos objetos, aquele imedia-
mesmo operador. tamente antes do operador. Esta a primeira coisa a ter
em mente: O operador pertence a um dos objetos que
est sendo operado, sendo sempre aquele que o antecede.
Com isso, s precisamos declarar o segundo dado a ope-
27.2 Denindo novas operaes rar.
Podemos visualizar isto melhor, da seguinte forma:
Digamos que temos uma classe chamada ponto, que de-
P3 = P1 + P2;
ne dois inteiros para um plano hipoteticamente denido.
Este par de inteiros poder representar uma coordenada Que pode ser entendido como a invocao da funo:
neste plano formado por pontos espaados um do outro. P3 = P1.operator+( P2);
Sob estas condies, cada objeto desta classe ser uma
coordenada neste plano: Agora podemos entender como acontece a invocao da
funo que dene o operador. Observe que P1 contm o
class ponto { int x,y; public: ponto(int a, int b) { x = a; y operador que recebe P2, fazendo o clculo e devolvendo
= b; } }; uma cpia do objeto resultante para P3. A sintaxe es-
conde o mecanismo para tornar o cdigo mais simples de
Se quisermos operar estes objetos no teremos como ser entendido quando tiver que ser lido.
faz-lo, pois no h meios de operar os objetos do tipo
ponto. Nenhuma operao possivel, pois a linguagem
no dene como oper-los. Cabe ao programador dizer

71
Captulo 28

Alocao dinmica de memria

28.1 Alocao dinmica de mem- que vamos alocar memria para o array na altura da com-
pilao, e o compilador necessita de saber exatamente a
ria quantidade de memria que deve reservar porm se a
varivel o size declarator, o compilador no sabe quanta
O compilador reserva espao na memria para todos os memria deve reservar para alocar a varivel, pois o seu
dados declarados explicitamente, mas se usarmos pontei- valor pode mudar.
ros precisamos reservar o espao necessrio e colocar o
endereo inicial nos mesmos. Para isto, podemos usar
o endereo de uma varivel denida previamente ou re- 28.2 Operador new
servar o espao necessrio no momento que precisemos.
Este espao que precisamos reservar em tempo de exe-
Reformulando o exemplo anterior agora com dados din-
cuo chamada de memria alocada dinamicamente.
micos.
Refere-se possibilidade de termos o nosso programa a
#include <iostream> using namespace std; int main () {
correr e o utilizador ter de inserir dados e como tal no
int numTests; cout << Enter the number of test scores:";
sabemos exatamente a quantidade de dados que o utiliza-
cin >> numTests; int * iPtr = new int[numTests];
dor vai colocar, portanto temos de arranjar uma memria
//colocamos um ponteiro no inicio da memria dinmica
que nos permita lidar com esta indeterminao quanto
for (int i = 0; i < numTests; i++) { cout << Enter test
quantidade de dados inseridos.
score #" << i + 1 << " : "; cin >> iPtr[i]; } for (int i = 0;
Este o caso em que no sabemos no momento da pro- i < numTests; i++) cout << Test score #" << i + 1 << "
gramao a quantidade de dados que devero ser inseri- is "<< iPtr[i] << endl; delete [] iPtr; return 0; }
dos mas o programa j est a correr. tentar respon-
der a perguntas: quantas pessoas existem na tua turma?
Ou seja conseguimos criar um array onde o utilizador
Quantas letras vamos escrever, etc. Em vez de estarmos
a denir o tamanho do array e que depois coloca o valor
a prever um limite superior para abarcar todas as situa-
para cada um dos elementos.
es, temos esta possibilidade do dinmico. Alm de que
colocar no momento da programao cria reserva de me- O operador new retorna o endereo onde comea o bloco
mria por isso, estaramos a reservar memria para um de memria. e como retorna um endereo vamos coloc-
limite que possivelmente no iramos ter necessidade. O lo num pointer.
exemplo tpico disto os processadores de texto. em que Necessitamos do uso do pointer que dever ser do mesmo
no sabemos a quantidade de letras que o utilizador vai tipo que o tipo de varivel que alocado dinamicamente.
escrever. int * iPtr = new int[numTests];
Vamos voltar a uma ponta solta num dos captulos anteri-
ores, onde queramos fazer com que o utilizador dissesse Temos termo NEW. Que um operador cuja funo
quantos elementos do array que se deveria utilizar. J alocar dinamicamente memria
dissemos antes que o declarador do n de elementos do
array tem de ser ou uma constante ou um literal, mas no Temos o tipo da varivel alocada dinamicamente
pode ser uma varivel. Isso d erro. Aqui vai o exemplo
desse erro: Repare que NO temos o nome do array
#include <iostream> using namespace std; int main Uma vez que o array ca sem nome para nos refe-
() { int numTests; cout << digite o numero de testes rirmos a cada elemento do array teremos de usar o
: "; cin >> numTests; int testScore[numTests]; return 0; } pointer.

A razo da exigncia de ter uma constante (ou literal) Podemos inicializar de duas maneiras:

72
28.4. RETORNANDO UM PONTEIRO PARA UMA VARIVEL LOCAL 73

int *IDpt = new int; *IDpt = 5; E agora no conseguimos apagar esse objeto por que ele
no tem nome e a nica maneira que tnhamos para sa-
ou ber onde ele estava era atravs do ponteiro que terminou
quando termina a funo pois ele local.
int *IDpt = new int(5); //Allocates an int object and
Ento medida que o programa continua a operar mais
initializes it to value 5. char *letter = new char('J');
e mais memria ser perdida do Heap (free store). se o
programa continuar o tempo suciente, deixaremos de ter
memria disponvel e o programa deixar de operar.

28.3 Operador Delete - Memory


Leak 28.4 Retornando um ponteiro para
uma varivel local
O tempo de vida de uma varivel criada dinamicamente
o tempo de execuo do programa. Se um ponteiro #include <iostream> using namespace std; char *
aponta para uma varivel dinmica e ca out of scope, jsetName(); int main (void) { char* str = setName();
no conseguiremos acessar essa memria criada dinami- //ponteiros para a funo cout << str; //imprimo o valor
camente. Fica indisponvel. A isso se chama Memory do ponteiros? return 0; } char* setName (void) { char
Leak name[80]; cout << Enter your name: "; cin.getline
Explicando: se alocamos memria dinamicamente den- (name, 80); return name; }
tro de uma funo usando um ponteiro local, quando a
funo termina, o ponteiro ser destrudo, mas a mem- O que se passou aqui que o ponteiro que sai da funo
ria mantm-se. Assim j no teramos maneira de cha- setName aponta para o array local cuja vida acaba quando
mar essa memria porque ela no tem nome! Apenas a funo termina de executar. A soluo estender o
tnhamos o endereo que estava no ponteiro. tempo de vida. Uma soluo era tornar esse array global,
Portanto, se realmente no necessitamos mais dos dados mas existem alternativas melhores.
que esto nessa memria dinmica, em vez de eles esta-
rem a ocupar espao vamos apag-los! Necessitamos de
libertar essa memria atravs do operador delete este 28.5 Retornando um Ponteiro a
operador entrega ao sistema operacional a memria re-
servada dinamicamente. uma Varivel Local Esttica
A sintaxe
Uma dessas alternativas
delete [] iPtr;
#include <iostream> using namespace std; char *
setName(); int main (void) { char* str = setName(); cout
Este delete operator no apaga o ponteiro mas sim a me- << str; return 0; } char* setName (void) { static char
mria onde o ponteiro aponta. name[80]; //crio como static cout << Enter your name:
dynamic memory allocation funciona porque a memria "; cin.getline (name, 80); return name; }
no reservada no momento da compilao, mas antes
na execuo. Em vez de ser no STACK (compilao) a A diferena que usamos a palavra static.
memria reservada no HEAP (execuo). O heap uma
O ponteiro do setName aponta para o array local, e como
parte da memria que usada como memria temporria.
foi utilizado o static, ele perdura at m da funo, ter-
Pergunta: onde que ca situado o Heap? minando apenas quando o programa acaba.
Vamos explicar melhor todo este processo: pois isto tem
de entrar na cabea!
void myfunction() { int *pt; int av; pt = new int(1024); 28.6 Retornando um Ponteiro a
.... .... //No delete } int main() { while (some condition uma Varivel Criada Dinami-
exists) // Pseudo-code { myfunction(); } exit 0; }
camente
quando a funo myfunction chamada a varivel av
criada no stack e quando a funo acaba a varivel Outra alternativa, talvez melhor
retirada do stack. O mesmo acontece com o ponteiro pt, #include <iostream> using namespace std; char *
ele uma varivel local. ou seja quando a funo acaba o setName(); int main (void) { char* str= setName(); cout
ponteiro tambm termina e retirado do stack. Porm o << str; delete [] str; //fao o delete para evitar o memory
objeto alocado dinamicamente ainda existe. leak return 0; } char* setName (void) { char* name =
74 CAPTULO 28. ALOCAO DINMICA DE MEMRIA

new char[80]; //crio ponteiro chamado de name e dou o neste exemplo libertmos a memria dinmica, mas o
valor do endereo da memoria dinmica cout << Enter ponteiro continua isto um bug tremendo, e muito di-
your name: "; cin.getline (name, 80); return name; } fcil de detectar. o programa continua a correr e a seco
de memria pode ser usada por outro objeto dinmico.
Isto funciona porque o ponteiro retornado da funo set- acontece que essa memoria estar corrompida se conti-
name aponta para o array cujo tempo de vida persiste. O nuar a usar o myPointer. a melhor maneira depois do
address do ponteiro local atribudo no main a outro pon- delete fazer apontar para zero, faz-lo um ponteiro nulo.
teiro no main str. Depois este ponteiro usado at ao se tentarem usar o ponteiro iremos ter a run time excep-
tion e o bug pode ser identicado
m da execuo do programa. Este um exemplo onde
diferentes ponteiros apontam para o mesmo endereo. Assim, corrigindo o cdigo anterior caramos com:
Mas ter ateno que se zermos o delete atravs de um int *myPointer; myPointer = new int(10); cout << The
ponteiro, ter cuidado com o segundo ponteiro que aponta value of myPointer is " << *myPointer << endl; delete
para a memoria que acabou de ser deslocada. myPointer; myPointer = 0; *myPointer = 5; //Essa
instruo vai causar uma run-time exception, agora. cout
<< The value of myPointer is " << *myPointer << endl;
28.7 Alocar dinamicamente Arrays
(Vetores)
28.9 Vericar a existncia de me-
Ora o que zemos antes com variveis, vamos ter de fazer
com arrays.
mria para dinmica
int *pt = new int[1024]; //Aloca um Array (Vetor)
Na alocao dinmica temos de nos certicar de que a
de 1024 valores em int double *myBills = new dou-
alocao no heap foi feita com sucesso e podemos ver
ble[10000]; /* Isso no signica que temos o valor
isso de duas maneiras:
10000, mas sim que alocamos 10000 valores em double
para guardar o monte de milhares de contas que recebe-
mos mensalmente. */ Uma so as excees (este o mtodo defaut)

bobby = new int [5]; // se isso falhar, lanada uma


Notar a diferena:
bad_alloc (exception)
int *pt = new int[1024]; //Aloca um vetor que pode ter
1024 valores em int diferentes int *pt = new int(1024);
vamos ver este caso quase no ultimo capitulo- isto uma
//Aloca um nico int com valor de 1024 (uma varivel
captulo avanado
inicializada)

nothrow, aqui no caso de no se conseguir a mem-


a melhor maneira para alocar um array dinamicamente ria retorna um ponteiro nulo, e o programa continua.
usar o loop
int *bu = new int[1024]; for (i = 0; i < 1024; i++) bobby = new (nothrow) int [5];
{ *bu = 52; //Assimila o valor 52 para cada ele-
mento bu++; } //ou se quisermos desta maneira
int *bu = new int[1024]; for (i = 0; i < 1024; i++) supostamente este mtodo pode ser tedioso para grandes
{ bu[i] = 52; //Assimila o valor 52 para cada elemento } projetos
Vamos ver um exemplo com o caso de nothrow
para utilizar o delete em arrays // rememb-o-matic #include <iostream> using names-
delete[] pt; delete[] myBills; pace std; int main () { int i,n,* p; cout << How many
numbers would you like to type? "; cin >> i; p= new
(nothrow) int[i]; //crimos I variaveis na execuo if (p
== 0) cout << Error: memory could not be allocated";
else { for (n=0; n<i; n++) { cout << Enter number: ";
28.8 Dangling Pointers cin >> p[n]; } cout << You have entered: "; for (n=0;
n<i; n++) cout << p[n] << ", "; delete[] p; } return 0; }
int *myPointer; myPointer = new int(10); cout <<
O valor de myPointer e " << *myPointer << endl;
delete myPointer; *myPointer = 5; cout << O valor de
myPointer e " << *myPointer << endl;
Captulo 29

Excees

Uma exception um erro que ocorre em tempo de exe-


cuo. Podemos lidar com estes erros e criar rotinas para
muitos deles, o que nos permite automatizar muitos erros
que antes teriam de ser emendados mo.

29.1 Standard Exceptions


A biblioteca de C++ contm exceptions j denidas para
erros comuns. Elas so divididas em dois setores: Erros
lgicos e Erros de tempo de execuo.
Aqui vemos um exemplo de cdigo usando exceptions de
erros lgicos:
#include <iostream> #include <stdexcept> //
std::invalid_argument #include <bitset> #include
<string> int main (void) { try { // O construtor de
bitset joga uma invalid_argument se inicializado com
uma // string contendo caracteres diferentes de 0
e 1 std::bitset<5> mybitset (std::string(01234));
} catch ( const std::invalid_argument& ia ) { std::cerr
<< Invalid argument: " << ia.what() << '\n'; } return 0; }

75
Captulo 30

Namespace

O propsito dos namespace localizar os identiers (os


nomes) por forma a evitar que haja apenas um, para evi-
tar colises. Por exemplo eu poderia criar uma funo
com um determinado nome e depois vir a saber que esse
mesmo nome existia na biblioteca. E isto pode ocorrer
bem freqentemente quando temos vrios programadores
contribuindo para o mesmo projeto e ainda mais quando
se recorre a bibliotecas para usar cdigo criado por ou-
tros.
O que o namespace permite continuar a termos o
mesmo nome mas ir fazer a diferenciao pela deteco
do contexto de aplicao para cada nome.

76
Captulo 31

Templates

Os templates permitem a criao de cdigo reusado, tiating.


usando templates possvel criar funes e classes ge- h quem prera ter a declarao do template da seguinte
nricas. Assim o tipo de dados usados pelas funes so forma
parmetros. Podemos criar um template para soma, e de-
pois enviamos que tipo de dados queremos somar, pode- template <class X> void swapargs(X &a, X &b)// This
mos at utilizar a sobrecarga de operadores para tal m. is a function template. { X temp; temp = a; a = b; b =
temp; }

O que se torna bem parecido com o modelo utilizado an-


31.1 Funes genricas teriormente.
Uma funo com dois tipos genricos:
template <class Ttype> ret-type func-name(parameter
list) { // body of function } #include <iostream> using namespace std; template
<class type1, class type2> void myfunc(type1 x, type2 y)
{ cout << x << ' ' << y << '\n'; } int main() { myfunc(10,
vamos dar o exemplo
hi); myfunc(0.23, 10L); system (pause); return 0; }
// Function template example. #include <iostream>
using namespace std; template <class X> void swa-
Repare que temos dois tipos de dados diferentes na
pargs(X &a, X &b)// This is a function template. { X
mesma funo.
temp; temp = a; a = b; b = temp; } int main() { int i=10,
j=20; double x=10.1, y=23.3; char a='x', b='z'; cout <<
Original i, j: " << i << ' ' << j << '\n'; cout << Original
x, y: " << x << ' ' << y << '\n'; cout << Original a, b: " 31.2 Sobrecarregando explicita-
<< a << ' ' << b << '\n'; swapargs(i, j); // swap integers mente uma funo genrica
swapargs(x, y); // swap oats swapargs(a, b); // swap
chars cout << Swapped i, j: " << i << ' ' << j << '\n';
apesar de uma funo genrica poder ser overload au-
cout << Swapped x, y: " << x << ' ' << y << '\n'; cout
tomaticamente se necessrio, ns podemos explicitar. a
<< Swapped a, b: " << a << ' ' << b << '\n'; system
isso chamamos deexplicit specialization
(pause); return 0; }

Aqui criamos uma template para uma funo que troca


os valores, e essa funo pode ser usada quer tendo ints,
doubles ou chars. ns utilizamos o X como data type.
neste caso temos swapargs() como uma funo genrica.
O compilador automaticamente cria 3 verses para a fun-
o swapargs(). portanto os templates no so bem fun-
es que funcionam para as vrios tipos, mas antes os
templates permitem poupar escrita ao programador para
no ter de especicar cada tipo.
template function ou generic function ( uma denio
de uma funo precedida pela statement template
especializao == quando o compilador cria a verso
especica da funo. tambm chamada de generated
function. o ato de gerar a funo referido como instan-

77
Captulo 32

Containers

list

set
unordered_set

map
unordered_map

78
Captulo 33

Compilao

Compilao o processo de traduo do programa es- guardadas num arquivo a parte, chamado de object le
crito em uma linguagem de programao para um for- e tem a extenso .o ou .obj dependendo do compilador.
mato no qual o computador entenda. A compilao gera Existem diferentes compiladores para diferentes lingua-
um cheiro - arquivo em portugus brasileiro - binrio gens de programao. Essa traduo feita se o cdigo
(executvel) a partir do cdigo fonte. estiver na linguagem que o compilador compilar. Exis-
tem regras de escrita e de gramtica. No caso de existir
um erro de sintaxe, ento dar um erro de compilao.
33.1 A traduo do cdigo para o
computador
33.4 Linker
Em C e C++ so 3 os programas usados para fazer a tra-
duo do cdigo fonte (que so as linhas de cdigo que Apesar do nosso object le ter as instrues em lin-
o programador escreve) num cheiro executvel, que o guagem mquina, o computador ainda no poder correr
computador pode executar: como um programa. A razo que necessrio outro
cdigo da biblioteca, que o cdigo do run-time library,
1. Preprocessor - pr-processador que para as operaes comuns tipo a traduo o input
do teclado ou a capacidade para interagir com hardware
2. Compiler - compilador externo tipo o monitor para apresentar uma mensagem.
3. Linker Estas bibliotecas run-time costumam j estar instaladas
com o sistema operacional, caso isso no acontea tere-
mos de fazer o download delas.
33.2 Pr-processador Ento o resultado da combinao do object le com
as partes necessrias da biblioteca run-time fazem nal-
Este um programa que busca no cdigo fonte no c- mente a criao de um cheiro executvel com a extenso
digo que escrevemos por diretivas que foram dirigi- .exe
das a ele, ou seja linhas iniciadas com #, assim o pr-
processador sabe que aquela instruo dirigida para ele.
No exemplo tnhamos: 33.5 Processo de compilao
#include <iostream>
Em primeiro lugar, vamos escrever um cdigo que est
Ento o pr-processador inclui cheiros localizados no -
na linguagem C++ e vamos gravar esse cdigo todo num
cheiro iostream. Ento tnhamos o cdigo fonte que de-
cheiro, que uma quantidade de memria no computa-
pois transformado num outro cdigo fonte de acordo
dor. Esse cheiro ca com a terminao .CPP ou .CP
com as diretivas pr-processadas.
ou C.. Chama-se a este conjunto de linhas que escreve-
Essencialmente, o pr-processador um processador de mos de, cdigo fonte ou source code (pode ter a termi-
macros para uma linguagem de alto nvel.[1] nao .c, .cpp, e .cc - estas extenses dependem do
compilador que se utiliza). Esse source code de al-
guma forma crptica e para algum que no saiba de c++
33.3 Compilador no entanto aquilo que neste momento chamamos de hu-
mam readable form.
Compilador um programa que pega cdigo fonte pre- Para tornar o nosso source code num programa usamos
processado e o traduz em instrues de linguagem de m- um compilador que ir produzir um object le. Este
quina, linguagem que o computador entende. Estas so cheiro tem normalmente a extenso. OBJ porm ainda

79
80 CAPTULO 33. COMPILAO

no temos um programa executvel. Para isso vamos uti-


lizar o linker. Uma das vantagens do c++ que usufrui de
uma estrutura multi-le. A linguagem permite compila-
o separada, onde partes do programa total podem estar
numa ou mais source les e estes podem ser compilados
independentemente de cada um. A ideia que o processo
de compilao produz les que depois podem ser linked
together usando um editor de link ou loads que o sistema
provem.
Os programas feitos em c++ so tipicamente cheiros
.OBJ ligados uns aos outros com uma ou mais libraries.
Estas so uma coleo de linkable les que ns crimos
ou que foram fornecidas (vm com o compilador ou com-
pramos).
Depois de se fazer este linking que obtemos o arquivo
executvel. No Windows, ele tem terminao .exe. As-
sim, o sistema operacional reconhece o programa como
independente.
Os compiladores atuais incluem tambm pr-
compiladores, (ou pr-processadores) (antes eram
software independente, extra), estes pr-compiladores
vo fazer alteraes ao cdigo fonte, que basicamente
consistem em eliminar pedaos de cdigo que escreve-
mos, e/ou substituir pedaos de cdigo que escrevemos
por outro (copy-paste), enm, alterar o cdigo fonte
por outro cdigo fonte. Depois que se compila.

[1] http://www.dca.fee.unicamp.br/cursos/EA876/apostila/
HTML/node150.html O pr-processador C
Captulo 34

Lista de Palavras Reservadas do C++

Estas so as palavras reservadas do c++:

Maiores detalhes podem ser encontrados em: http:


//en.cppreference.com/w/cpp/keyword

81
Captulo 35

Lista de Sequncias de Escape

Estes so caracteres que so difceis de serem expressos


de outra forma em um cdigo fonte. Todos eles so pre-
cedidos de uma barra invertida. A Tabela 1 apresenta a
lista de sequncias de escape.
Tabela 1 - Lista de Sequncias de Escape em C++

82
Captulo 36

Tabela ASCII

Programa que gera a tabela ASCII do C++ (programa es-


crito em c++). Nenhum dos 2 programas mostra a ta-
bela inteira. O programa mostra alguns caracteres que o
programa 2 no mostra. De modo geral, faltam alguns
caracteres.

36.1 Programa 1
#include <stdio.h> #include <iostream> using names-
pace std; int main() { //CARACTER " " (ENTER)
= DECIMAL 10 HEXADECIMAL A; int s = 127;
cout<<" CARAC DEC HEX\n\n"; for ( char i =
127; i<127; i++ ) { cout<<" "<<i<<" "<<s<<" ";
printf("%X,s); cout<<"\n"; s++; } cout<<"\n CARAC
DEC HEX\n\n"; cout<<" \x122 ENTER \x122 10
A\n\n"; system (PAUSE); return 0; }

36.2 Programa 2
#include <stdio.h> #include <iostream> int main()
{ int x; printf(" DEC\tHEX\tA DEC\tHEX\t);
printf(" DEC\tHEX\n); for(x=173;x<360;x++)
{ printf("%c %3i\t%2X\t,x,x,x); printf("%c
%3i\t%2X\t,x+32,x+32,x+32); printf("%c
%3i\t%2X\t,x+64,x+64,x+64); printf("%c
%3i\t%2X\n,x+96,x+96,x+96); } system (PAUSE);
return 0; }

83
Captulo 37

C++11

Origem: Wikipdia, a enciclopdia livre. Regular expressions library: http://en.cppreference.


C++11, anteriormente conhecido por C++0x o novo pa- com/w/cpp/regex
dro para a linguagem de programao C++. Ele substi- Atomic operations library: http://en.cppreference.
tui o antigo padro do C++, o ISO/IEC 14882, que foi pu- com/w/cpp/atomic
blicado em 1998 e atualizado em 2003. Estes predecesso-
res foram informalmente chamados C++98 e C++03. O Thread support library: http://en.cppreference.
novo padro incluir muitas adies ao ncleo da lingua- com/w/cpp/thread
gem (sua implementao principal), e estender a biblio-
teca padro do C++, incluindo a maior parte da biblioteca
do chamado C++ Technical Report 1 um documento
que prope mudanas ao C++ com exceo das fun-
es matemticas especcas.
Esse nome uma referncia ao ano no qual o padro ser
lanado. O comit pretendia introduzir o novo padro em
2009,1 a partir do que o ento chamado C++0x passaria
a se chamar C++09, o que signica que o documento
deveria estar pronto para a raticao dos membros do
comit at o nal de 2008. Para cumprir o prazo, o co-
mit decidiu focar seus esforos nas solues introduzi-
das at 2006 e ignorar novas propostas.2 porm ele car
pronto apenas em 2010.
Linguagens de programao como o C++ utilizam um
processo evolucionrio para desenvolverem suas deni-
es. Tal processo inevitavelmente culmina em proble-
mas de compatibilidade com cdigo pr-existente, o que
ocasionalmente aconteceu durante o processo de desen-
volvimento do C++. Entretanto, de acordo com o ann-
cio feito por Bjarne Stroustrup inventor da linguagem
C++ e membro do comit o novo padro ser quase
completamente compatvel com o padro atual.3
Novas classes:

std::array

std::tuple

std::foward_list

std::unordered_set

std::unordered_multiset

std::unordered_map

std::unordered_multimap

84
37.1. FONTES DOS TEXTOS E IMAGENS, CONTRIBUIDORES E LICENAS 85

37.1 Fontes dos textos e imagens, contribuidores e licenas


37.1.1 Texto
Programar em C++/Objetivo Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Objetivo?oldid=212683 Contribuidores:
Marcos Antnio Nunes de Moura, SallesNeto BR, Wbrito, He7d3r, He7d3r.bot e Contribuidor~ptwikibooks
Programar em C++/Por que C++? Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Por_que_C%2B%2B%3F?
oldid=244119 Contribuidores: Marcos Antnio Nunes de Moura, Jorge Morais, SallesNeto BR, Wbrito, He7d3r, He7d3r.bot, Abacaxi
e Annimo: 2
Programar em C++/Diferenas entre C e C++ Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Diferen%C3%A7as_
entre_C_e_C%2B%2B?oldid=276154 Contribuidores: Marcos Antnio Nunes de Moura, Master, He7d3r, RadiX, He7d3r.bot, Fabio
Basso, Abacaxi, Torneira e Annimo: 2
Programar em C++/Introduo Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Introdu%C3%A7%C3%A3o?oldid=
267436 Contribuidores: Marcos Antnio Nunes de Moura, Rautopia, He7d3r, He7d3r.bot, Abacaxi, Mappim e Annimo: 4
Programar em C++/Al, Mundo! Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Al%C3%B4%2C_Mundo!?oldid=
267384 Contribuidores: Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Edudobay, Marcelo-Silva, Wbrito, Albmont, Rautopia,
Petrusz1, Renatofq, He7d3r, Focli, Carlosmacapuna, He7d3r.bot, Sygmn, Abacaxi e Annimo: 15
Programar em C++/Variveis e constantes Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Vari%C3%A1veis_e_
constantes?oldid=238714 Contribuidores: Marcos Antnio Nunes de Moura, Jorge Morais, Rautopia e He7d3r.bot
Programar em C++/Ponteiros Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Ponteiros?oldid=442421 Contribuido-
res: Marcos Antnio Nunes de Moura, Jorge Morais, Albmont, He7d3r.bot, Jonathan Queiroz, Codeks, Abacaxi, Kleberlyra e Annimo:
4
Programar em C++/Vetores Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Vetores?oldid=438517 Contribuidores:
Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Edudobay, Marcelo-Silva, Wbrito, Master, Raylton P. Sousa, He7d3r.bot, Aba-
caxi, Matiia e Annimo: 9
Programar em C++/Estruturas Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Estruturas?oldid=276333 Contribui-
dores: Marcos Antnio Nunes de Moura, Albmont, He7d3r.bot, Defender, Abacaxi e Annimo: 7
Programar em C++/Operadores Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Operadores?oldid=291541 Contri-
buidores: Marcos Antnio Nunes de Moura, He7d3r.bot, Abacaxi e Annimo: 1
Programar em C++/Deciso e controle de uxo Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Decis%C3%A3o_e_
controle_de_fluxo?oldid=266793 Contribuidores: Marcos Antnio Nunes de Moura, He7d3r.bot, Abacaxi e Annimo: 6
Programar em C++/Estruturas de repetio Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Estruturas_de_repeti%
C3%A7%C3%A3o?oldid=266523 Contribuidores: Marcos Antnio Nunes de Moura, He7d3r, He7d3r.bot, Lucas Daltro, Diegobza, Aba-
caxi, LlamaAl e Annimo: 1
Programar em C++/Funes Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Fun%C3%A7%C3%B5es?oldid=
249232 Contribuidores: Jonas AGX, Abacaxi e Annimo: 1
Programar em C++/Referncias de dados Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Refer%C3%AAncias_de_
dados?oldid=239660 Contribuidores: Marcos Antnio Nunes de Moura, Albmont, He7d3r.bot, Codeks e Annimo: 5
Programar em C++/Entrada e sada de dados Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Entrada_e_sa%C3%
ADda_de_dados?oldid=266602 Contribuidores: Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Edudobay, Marcelo-Silva,
Wbrito, Albmont, He7d3r.bot, Jonathan Queiroz, Jeferson90, Abacaxi, Torneira e Annimo: 13
Programar em C++/Entrada e sada de dados 2 Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Entrada_e_sa%C3%
ADda_de_dados_2?oldid=256748 Contribuidores: Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Edudobay, Marcelo-Silva,
Wbrito, Diego.g.a, Raylton P. Sousa, He7d3r.bot, Abacaxi e Annimo: 15
Programar em C++/Manipulando strings Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Manipulando_strings?
oldid=423325 Contribuidores: Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Marcelo-Silva, Wbrito, Albmont, He7d3r,
He7d3r.bot, Fabiobasso, Abacaxi e Annimo: 14
Programar em C++/Classes Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Classes?oldid=389901 Contribuidores:
Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Marcelo-Silva, Wbrito, Albmont, He7d3r.bot, Jeferson90, Abacaxi, Hudsonkem,
Kelvinsteiner e Annimo: 15
Programar em C++/Encapsulamento Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Encapsulamento?oldid=
214125 Contribuidores: Marcos Antnio Nunes de Moura, MGFE Jnior, He7d3r.bot e Annimo: 2
Programar em C++/Herana Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Heran%C3%A7a?oldid=214299 Con-
tribuidores: Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Marcelo-Silva, Wbrito, Albmont, He7d3r.bot e Annimo: 10
Programar em C++/Polimorsmo Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Polimorfismo?oldid=274756 Con-
tribuidores: Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Marcelo-Silva, Wbrito, Albertguedes, He7d3r.bot, Abacaxi, Torneira
e Annimo: 4
Programar em C++/Friend Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Friend?oldid=255619 Contribuidores:
Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Marcelo-Silva, Wbrito, He7d3r.bot, Abacaxi e Annimo: 6
Programar em C++/Classes internas Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Classes_internas?oldid=212708
Contribuidores: Marcos Antnio Nunes de Moura e He7d3r.bot
Programar em C++/Sobrecarga de operadores Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Sobrecarga_de_
operadores?oldid=271234 Contribuidores: Marcos Antnio Nunes de Moura, Raylton P. Sousa e Annimo: 5
86 CAPTULO 37. C++11

Programar em C++/Alocao dinmica de memria Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Aloca%C3%


A7%C3%A3o_din%C3%A2mica_de_mem%C3%B3ria?oldid=291339 Contribuidores: Marcos Antnio Nunes de Moura, Daveiro, Jorge
Morais, Marcelo-Silva, Wbrito, Petrusz1, He7d3r, Abacaxi, Matiia e Annimo: 14
Programar em C++/Excees Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Exce%C3%A7%C3%B5es?oldid=
422315 Contribuidores: Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, SallesNeto BR, Marcelo-Silva, Wbrito, He7d3r.bot
e Annimo: 5
Programar em C++/Namespace Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Namespace?oldid=203888 Contri-
buidores: Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Marcelo-Silva, Wbrito, He7d3r.bot e Annimo: 3
Programar em C++/Templates Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Templates?oldid=271965 Contribui-
dores: Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Marcelo-Silva, Wbrito, He7d3r.bot, Abacaxi e Annimo: 6
Programar em C++/Containers Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Containers?oldid=267423 Contribui-
dores: Abacaxi e Annimo: 1
Programar em C++/Compilao Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Compila%C3%A7%C3%A3o?
oldid=266790 Contribuidores: Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, SallesNeto BR, Edudobay, Marcelo-Silva, Wbrito,
Master, Renatofq, He7d3r.bot, Jonas AGX, Abacaxi e Annimo: 3
Programar em C++/Lista de Palavras Reservadas do C++ Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Lista_
de_Palavras_Reservadas_do_C%2B%2B?oldid=266289 Contribuidores: Marcos Antnio Nunes de Moura, He7d3r.bot, Lucas Daltro,
Abacaxi e Annimo: 1
Programar em C++/Lista de Sequncias de Escape Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Lista_de_Sequ%
C3%AAncias_de_Escape?oldid=253634 Contribuidores: Abacaxi e Yoroi~ptwikibooks
Programar em C++/Tabela ASCII Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Tabela_ASCII?oldid=265804
Contribuidores: He7d3r, Abacaxi, Torneira e Annimo: 1
Programar em C++/C++11 Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/C%2B%2B11?oldid=267422 Contribui-
dores: Abacaxi e Annimo: 1

37.1.2 Imagens
Ficheiro:Nuvola_apps_konsole.png Fonte: https://upload.wikimedia.org/wikipedia/commons/2/24/Nuvola_apps_konsole.png Licena:
LGPL Contribuidores: http://icon-king.com Artista original: David Vignoni / ICON KING
Ficheiro:Recycle001.svg Fonte: https://upload.wikimedia.org/wikipedia/commons/4/44/Recycle001.svg Licena: Public domain Contri-
buidores: Originally from en.wikipedia; description page is (was) here Artista original: Users Cbuckley, Jpowell on en.wikipedia
Ficheiro:Wikipedia-logo.png Fonte: https://upload.wikimedia.org/wikipedia/commons/6/63/Wikipedia-logo.png Licena: GFDL Con-
tribuidores: based on the rst version of the Wikipedia logo, by Nohat. Artista original: version 1 by Nohat (concept by Paullusmagnus);

37.1.3 Licena
Creative Commons Attribution-Share Alike 3.0