Você está na página 1de 93

Programar em C++

Contedo
1

Objetivo

Por que C++?

Diferenas entre C e C++

Introduo

4.1

Pensando no cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.2

Dois modos de programar

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.3

Um pouco sobre orientao a objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.3.1

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4.4
5

Al, Mundo!

5.1

Ol mundo! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.2

Entrada de dados e comentrios no cdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.2.1

Comentrios no programa

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.2.2

Incluindo cabealhos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.2.3

Namespace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.2.4

Funo main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.2.5

Entrada e sada (cin/cout)

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10

5.2.6

funo system(pause) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10

5.2.7

Retornando valor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

10

Variveis e constantes

11

6.1

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11

6.1.1

Simblicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11

6.1.2

Literais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11

6.1.3

Enumeraes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

11

6.2

Paradigmas da Programao:

Constantes

Variveis

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

6.2.1

Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

6.2.2

Modicadores

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12

6.2.3

Nomeando tipos

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

13

Ponteiros

15
i

ii
8

CONTEDO
Ponteiros

16

8.1

O operador * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16

8.2

O operador & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16

8.3

O ponteiro this . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16

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
12.1 Compatibilidade

26
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.2 Como C++ interpreta os operadores

26

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33

15.4.3 O Comando continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33

15.4.4 Incrementar/decrementar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

33

15.5 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

34

15.4.2 O Comando break

16 Funes
16.1 Sobrecarga de funes

35
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

16.2 Parmetros default (padro)

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

17 Referncias de dados
17.1 Variveis de referncia

35
35
37

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

37

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

37

17.2 Passagem de parmetros

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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

18.3.2 A funo cin.get()

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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

19.7 Usando o Construtor

19.14Manipuladores

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

21 Classes
21.1 Classes

52
53

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53

21.1.1 Origem (atributos) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53

21.1.2 Funes membro (Mtodos) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53

21.1.3 Conceituao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53

21.2 Declarando classes

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

53

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

54

21.4 Denio de classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

55

21.5 Especicadores de acesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

21.6 Construtores

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

21.6.1 Conceito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

56

21.3 Instanciando objetos

CONTEDO

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

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

59

22.3 Escopos globais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

60

22.2.2 Denindo acessos

23 Herana

61

23.1 Conceito
23.2 Sintaxe

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

61

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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
24.1 Conceito

66
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
27 Sobrecarga de operadores
27.1 Modicando operadores

70
71

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

71

vi

CONTEDO
27.2 Denindo novas operaes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

28 Alocao dinmica de memria

71
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
29.1 Standard Exceptions

75
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

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, contribuidores e licenas de texto e imagem . . . . . . . . . . . . . . . . . . . . . . . . .

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 apresentar os fundamentos desta linguagem, de modo que o estudante possa desenvolver diferentes tipos de softwares em
alto e baixo nvel para os diversos ambientes existentes,
desde aplicaes para GNU/Linux ou Windows at programas para microcontroladores, alm de fornecer a base
para os estudos avanados de C++.
Por ser um livro especco sobre a linguagem C++, altamente recomendvel que o leitor tenha conhecimentos
prvios sobre a linguagem C.
Espera-se que este livro aborde:
Aspectos tericos
Aspectos prticos
Os erros comuns
Para tanto cada tpico dever ter uma explicao terica,
citar os erros mais comuns e exerccios.

Captulo 2

Por que C++?


Compiladores;

Imagine que voc deve fazer um programa para fazer a


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 linguagem quando voc pondera.

Programas de redes.

O problema maior que se eu tiver que mudar o proAt 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


C++", depois vai ser mais fcil de entender o cdigo, reaproveitar em outras coisas e ainda vai ser
mais fcil de expandir para outros modelos de relgio.

2 em 1990;
3 em 1998 a que deu origem ao ANSI \ ISO standard a que cou comummente denominada de Standard C++. Esta verso suportada por todos os
compiladores C++ famosos incluindo Microsofts
Visual C++, Borlands C++ Builder e GCC. Esta foi
revista em 2003.

E assim o que podemos perceber como C++ poderosa,


exvel e abrangente. Ela pode ser usada para programar
qualquer tipo de hardware, desde os mais simples at os
mais complexos. Alm disso, C++ uma linguagem que
gera programas em cdigo de mquina, que funcionam
com ou sem a participao de sistemas operacionais no
dispositivo.

C++ considerada uma linguagem que est entre


linguagem de alto nvel (em ingls, high level language)
e linguagem de baixo nvel (em ingls, low level language). Dito de outra forma, uma linguagem que est
prxima da linguagem humana (linguagem de alto nvel),
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 vrios melhoramentos;
Deu origem a grandes linguagens como Java e D;
a porta para a programao orientada a objetos;
C++ pode virtualmente ser efetivamente aplicado a
qualquer tarefa de programao;
H vrios compiladores para diversas plataformas
tornando a linguagem uma opo para programas
multiplataforma.
A linguagem C++ utilizada em projetos como:
2

Captulo 3

Diferenas entre C e C++


Quem sabe programar em C++, capaz de programar C,
devido semelhana entre as linguagens e o fato do C++
ser uma extenso do C. Contudo o C no completamente um subconjunto do C++. Grande parte de cdigo
C pode ser perfeitamente compilado em C++, mas existem algumas pequenas diferenas sintticas e semnticas
entre as linguagens que tornam alguns trechos de cdigo
C vlidos em cdigo C++ invlido, ou cdigos que exibem comportamentos diferentes em cada linguagem.

deixar claro que os dois modos so diferentes. Usar estes dois modos de programar ao mesmo tempo uma das
facilidades que o C++ permite, enquanto que outras linguagens orientadas a objetos como Java, Eifel, etc, no
permitem.

Algumas diferenas bsicas:


O C permite a converso implcita entre o tipo de
dado void* para ponteiros para outros tipos, algo
que o C++ no permite.
O C permite que constantes de caracteres sejam inseridas em chamadas de funes com parmetros
tipo char*, em C++ preciso declarar o parmetro como const char *;
Alm destas pequenas diferenas, C++ tem um conjunto
de caractersticas que a torna fundamentalmente diferente
de C. Esse conjunto, torna possvel programar em C++
de um modo totalmente diferente do modo de programar
da linguagem C. O que traz a diferena o modo da
orientao na montagem do cdigo.
Chamamos o modo de programar em C de orientado
a procedimentos e chamamos o modo do C++" de orientado a objetos. Muitas pessoas confundem as coisas
quando comeam a programar usando um compilador
C++, pois esta linguagem permite programar nos dois
modos. Essa uma das caractersticas que a torna mais
exvel.
Apesar de C++ permitir programar em modo orientado
a procedimentos, podemos dizer que nestes casos estamos programando em C, usando um compilador C++.
Quando usamos C++ programamos em modo orientado
a objetos. Devido a estas caractersticas, o C++ permite
programar em modo misto, ou seja, escrevendo partes do
cdigo orientadas a procedimentos e outras orientadas a
objetos.
As diferenas entre os dois modos de programar sero esclarecidas nos captulos subsequentes. Por hora nos basta
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
quem no tem muita experincia, mas o uso de um ou do
outro implica em caractersticas prprias para cada caso.
Logo, preciso entender bem os conceitos antes de denir se um cdigo procedural ou orientado a objetos.

Considerando o conjunto de operaes e eventos que


nosso programa deve executar temos diversas maneiras
de criar o cdigo, porm o mais difcil criar um cdigo
eciente, rpido e compacto. Na verdade, diversos fatores podem interferir nestes aspectos da programao, entre eles, a escolha do compilador, o mtodo de estruturar
o cdigo, a orientao do mesmo, etc... Em termos gerais, um cdigo torna-se mais prximo do ideal a medida
que suas partes tornam-se mais simples de se analisar e
quando todos os processos esto bem denidos e especializados. Quando temos um cdigo que contm muito
mais excees do que regras, este precisa de uma reestruturao.

O modelo sequenciado procedural bem simples de implementar, porm, aumenta a complexidade para tarefas mais bem trabalhadas e sosticadas. Isto ocorre devido a estrutura do modelo, que exige rotinas cada vez
mais extensas. No raramente possvel encontrar rotinas que, em alguns casos, tornam-se comparveis a programas completos, usando como referncia o nmero de
linhas de instrues. O uso deste modelo, muitas vezes
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 sigonalidades 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 completaA orientao dene o modo de abordar o problema para
mente a forma de criar o programa quando usamos os retentar 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 preoe genrica, possibilitando a reutilizao do cdigo em dicupa em fornecer meios para resolver o problema
versas situaes diferentes.
sem contabilizar, a princpio, os dados que sero
usados durante o processo.

Vejamos como as funcionalidades da linguagem C++ podem 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 elementos principais na anlise do problema.

4.2 Dois modos de programar


Observando o modo de programar que as linguagens oferecem desde os primrdios da computao, podemos notar vrios mtodos que foram sendo superados e outros
que se estabelecem por um momento. O modo de programar mais usual e bem mais difundido conhecido como
modelo estruturado sequencial. Em sntese, refere-se
a forma de programar onde uma instruo segue a outra
numa sequncia que inicia e termina em um uxo parcialmente previsvel.

Este livro traz uma viso dos problemas sob a ptica da


orientao a objetos, enquanto que o livro "Programar
em C" traz a anlise sob a ptica da orientao a procedimentos. Isto no quer dizer que devamos escolher a
orientao a objetos como o modo mandatrio de programao, mas que podemos contar com seus recursos
sempre que esta escolha facilite a resoluo do problema.
Portanto, cabe sempre uma anlise para denir se o problema melhor tratado por uma abordagem orientada a
A programao estruturada ainda pode ser classicada objetos ou a procedimentos.
4

4.4. OBJETOS

4.3 Um pouco sobre orientao a 4.3.1 Paradigmas da Programao:


objetos
Desde o incio da programao, j passamos pelos seA programao orientada a objetos um paradigma
de programao que visa organizao, produtividade e
sustentabilidade.
A apresentao dos conceitos de orientao a objetos
bastante abrangente, o que implica na abordagem de
diversos aspectos, como modelagem, estudo de performance de modelos, aplicabilidade de tcnicas, estruturao de objetos, otimizao, manuteno do cdigo, entre
outros. Por este motivo, nosso objetivo aqui no apresentar a orientao a objetos em sua totalidade. Para um
estudo mais detalhado do tema sugerimos o livro POO,
que trata especicamente deste tema. O objetivo aqui
apresentar como a orientao a objetos se aplica na linguagem C++, porm os conceitos aqui apresentados devem ser sucientes para a estruturao de programas de
bom nvel.
A ideia principal por traz do modelo de programao
orientado a objetos est em transformar entidades do
mundo real em identicadores dentro do programa (objetos), trabalhando-os como entidades da linguagem que
possuem caractersticas e operaes prprias. Esta abordagem transforma o programa em um meio de simulao de situaes virtuais por meio de entidades de cdigo
que tem comportamento predenido. Esta abstrao
uma aliada do programador por permitir idealizar sistemas mais sosticados de uma maneira bastante intuitiva.

guintes paradigmas:
No estruturada - exemplos:
FORTRAN, BASIC (anos 50-60)

COBOL,

Procedimental ou Procedural - exemplos: C,


Pascal (anos 70)
Modular - exemplo: Modula II (anos 80)
Abstrao de tipos de dados - exemplo: Ada (anos
80)
Programao Orientada a Objetos - exemplos:
C++, Java, Delphi (Object Pascal) entre outras. (dcadas 80-90-2000)

4.4 Objetos
Objeto , genericamente, uma entidade de armazenamento e manipulao de dados. O mesmo deve ser criado
para processar os dados que armazena e recebe, sendo
sensvel a entradas do programa principal para fornecer as
sadas esperadas pelo mesmo. Por estes motivos o objeto
deve ser pensado como uma entidade de dados autnoma,
encarregada de processar todos os dados que mantm.

Da mesma forma que podemos usar tipos de dados nativos da linguagem podemos criar nossos tipos de dados.
Todas as linguagens orientadas a objetos contm os prin- Na linguagem C podemos criar tipos de dados composcpios 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 ende caractersticas dadas a um grupo de indivduos, ou
volvidos no processamento de uma ao. Por
seja, grupo de objetos. Por este motivo, classe a deniexemplo, quando usamos um telefone, no preo de tipo de objeto.
cisamos lidar diretamente com o circuito inEm C++ as classes de objetos so criadas atravs da palaterno; a interface do telefone cuida desse provra chave class. Esta nomenclatura usada por muitas oublema.
tras linguagens de programao mais caracteristicamente
restritas a orientao a objetos. Estes aspectos facilitam
Polimorsmo
um pouco o aprendizado por programadores j familiariIsso permite o uso de uma nica interface
zados com estas linguagens quando iniciam a programauma nica forma de uso para objetos de tio em C++.
pos diferentes; em particular, a mesma interO 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
conter;
Herana
Como o nome sugere, isso permite que uma
classe herde de outra suas caractersticas, podendo tambm introduzir suas prprias ou alterar as caractersticas herdadas. O uso de herana acaba poupando trabalho e melhorando
a organizao do cdigo.

Criar a classe de objetos;


Declarar (instanciar) o objeto.
A denio de uma classe de objetos deve ser feita de
forma a tornar, preferencialmente, todos os dados protegidos de interferncias de cdigos externos ao objeto.

6
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 4. INTRODUO

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 sistemas Microsoft. No entanto, se est usando Windows
necessrio adicionar esta linha, caso contrrio o computador escreveria Ol mundo!" e fecharia o programa antes
que pudssemos ler qualquer coisa. Uma forma elegante
de lidar com estas peculiaridades do Windows usar predenies, de forma que o programa seja portvel para
qualquer sistema operacional:

comum, no aprendizado de uma linguagem de programao, que seu primeiro programa faa com que o
computador exiba "Ol mundo!". Na linguagem C++
este primeiro programa j introduz muitos conceitos sobre a linguagem. Veja o cdigo do nosso primeiro programa:

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


#if dened(_MSC_VER) // estas linhas sero executadas
cout << Ol mundo!"; return 0; }
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
Em sistemas parecidos com UNIX, como GNU/Linux ou
logo de incio nos prender a todos os detalhes.
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 interface grca. Por isso, para esses sistemas um comando
{ cout << Ol mundo!"; return 0; }
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 seguido do operador << e da frase que se quer informar
entre aspas: Ol mundo!", intuitivamente, isso nos leva
a ideia de que a sequncia de caracteres ser levada ao
cout.

5.2 Entrada de dados e comentrios no cdigo

return 0;

Comentrio um recurso muito til em programao.


Ele permite que o programador adicione texto ao proEste comando termina o programa, o estudaremos melhor grama para facilitar o entendimento do programa por
parte de outros programadores, ou at dele mesmo. Os
no captulo sobre funes e retornos.
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 envoc 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

CAPTULO 5. AL, MUNDO!

5.2.1

Comentrios no programa

Observemos esta linha:

5.2.2 Incluindo cabealhos


#include <iostream>

O smbolo # uma chamada de ateno ao compilador


a dizer que aquela linha para o preprocessador, depois
temos o "include" (que basicamente diz para incluir cEsta 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 necesEste cdigo que ser includo chamado de cabealho
sidade do cdigo criado pelo programador.
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 cdo 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
caracteres, etc...
linguagem C++.
// Este um comentrio de uma linha

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 anexos, algumas bibliotecas que existem juntamente com as
ao m da linha.
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 cono que faz eliminar tudo o que encontrar entre a sequn- junto de cdigos que algum fez antes. As que enuncia 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 lintar 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
utilizar o cout.
j tm muito tempo nisto:
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 comque o nosso programa, e o que faz numa forma pilador usa como padro para os includes). Se tivssegeral;
mos o cheiro/arquivo iostream envolvido em "" signicaria que o preprocessador deveria procur-lo dentro de
Outra fazer comentrios a cada funo que aparece uma lista de diretrios de incluso, includes, iniciando
pelo diretrio atual.
no cdigo a explicar;
Outra comentar uma linha mais obscura, mais difcil de entender, que no bvia;

As bibliotecas so compostas por 2 partes: um ndice de


todas as funes e denies e declaraes, o cabealho,
e depois a denio de todas as funes existentes no ndice, arquivos de cdigo.

A outra no comentar tudo. O comentar deve ser As diretivas de preprocessamento no terminam com o
ponto e vrgula como nas instrues.
para sobressair.
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

Observando esta linha, alguns tradicionais programado- O int signica que a funo vai retornar um inteiro. Exisres em linguagem C, tm uma novidade: namespaces so tem outros tipos de dados como, por exemplo, os seguinespaos 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
int que a abreviatura de inteiro;
contam com inmeros arquivos.
O C++ usa os namespaces para organizar os diferentes
nomes usados nos programas. Cada nome usado no cheiro/arquivo biblioteca "standard iostream" faz parte
do "namespace" chamado de std.
O objeto de sada padro, cout, est denido dentro do
namespace std, ele um objeto da classe ostream
"output stream", para acess-lo temos que referenci-lo
como "std::cout". Para evitar que tenhamos que informar "std::" todas as vezes que precisarmos usar os recursos deste namespace, podemos informar que estamos
usando-o dentro do arquivo atual, conforme vemos na linha declarada no incio deste tpico.
O namespace permite que as variveis sejam localizadas em certas regies do cdigo. Declarar o namespace
std permite que todos os objetos e funes da biblioteca
"standard input-output" possam ser usados sem qualquer
qualicaes especcas, desta maneira, no mais necessrio o uso de "std::".

char que a abreviatura de caratere;


oat que a abreviatura de "oating point number",
ou seja, uma representao para nmero real.
Vejamos um exemplo:
Quando criamos uma funo soma, obviamente s para
ilustrao pois isso no necessrio, podemos fazer:
int soma(int a, int b) { return a + b; }
Agora imagine que tenhamos que somar 2 e 3, colocando
o resultado em outra varivel chamada valor, para isto
faremos:
valor = soma(2, 3);

Este um conceito avanado que podemos explorar mais, Primeiro analisamos qual o resultado e depois substituvamos 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


programa a partir do sistema operacional a funo main.
Por isso mesmo ela obrigatria em qualquer programa.
Se no existisse uma "main function", no haveria entrada
para que o sistema iniciasse o programa.

O ponto e vrgula funciona como ponto nal, separa as


instrues e contextos. Repare que apenas as funes, ou
melhor, as denies de funes e as diretivas de preprocessamento que no tm o ";"

que entram e o que ela deve fornecer a quem lhe chamou. Pode-se dizer que, tal qual uma funo matemtica, a funo em C/C++ poder ser substituda, depois
de sua execuo, pelo valor que ela retorna, este valor
ser especicado antes do nome da funo na declarao
da mesma, conforme vemos no incio deste tpico.

No nosso exemplo existem 2 instrues no corpo da funo. As instrues so executadas por ordem: do topo at
ao m a menos que existam funes que alterem o uxo
da leitura ou que existam cdigos de controle de execuo "execution control codes", que alteram o caminho de
execuo.

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 programa simplesmente usando o seu nome. As funes declaradas como membros de uma classe de objetos podem realmente o ";" que faz a terminao das instrues.
Ao encontrar as chaves "{}", o compilador reconhece
ser chamadas de mtodos.
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 agrupaas 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.

10

5.2.5

CAPTULO 5. AL, MUNDO!

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
header e o namespace std. As informaes sero direcionadas atravs do iostream, um subsistema de entrada
e sada da biblioteca padro. O que este objeto nos permite enviar o que temos entre aspas para a sada (out),
que o monitor neste caso.

5.2.6 funo system(pause)


system (pause);

A maioria dos compiladores quando esto executando em


modo grco fecha o console de sada assim que o programa naliza. Isto impede que possamos ver o que aconQuem 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,
este co usualmente o monitor, a abstrao do elemento de sada como j informamos no incio deste captulo,

mando

destinado
a
sistemas
da
Microsoft
.
Coloquei
padro observada na presena de um objeto que repreesta linha para que o programa no nalizasse sem que
senta a sada fsica de dados para o meio externo.
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
em linha de comando, assim basta compilar o programa
para o "output stream" do seu lado esquerdo.
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
operativo/operacional iniciou a execuo do mesmo, este
cout<< hex << n;
retorno recebido pelo sistema, comum que valores diferentes de zero sejam interpretados como erro do proO resultado seria impresso em hexadecimal;
grama.
Para entrada de dados temos:
Esta instruo manda retornar o valor zero para o sistema
operativo/operacional (Windows, Unix, ...). Este zero recin >> a;
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 ditemos outro objeto para entrada atravs do teclado, este ferente das normais. Por isso que o programa diz ao sisobjeto 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 imprimir no/na ecr/tela a frase Voc digitou o nmero: ",
depois vai buscar o valor que est naquela rea de memria a que chamamos de a e por 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 funcionalidades bem denidas substitudas por nomes que as identiCompatvel 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 va1. Resguarda da inviolabilidade de valores apontados lor do vetor de trs coordenadas podemos usar a constante
PRINT_VECTOR.
por ponteiros;
2. Auxlio na compreenso das caractersticas de fun6.1.2
es, durante a implementao.

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 diretamente no cdigo atravs de seu valor signicativo. Por
Constantes simblicas podem ser criadas com as diretiexemplo, 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 preprocessador no estgio anterior compilao. Por exemplo:
Tambm podemos denir valores para caracteres ou ca#dene BUFFER_LENGTH 2048 ...
data[BUFFER_LENGTH];

...

...

char deias de caracteres, como segue:

'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 combudo.
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 composValores enumerados so muito recorrentes nos ambientes
tos, por exemplo:
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
enum seq {A,B,C,D}; seq x;
screen[MASTER_LENGTH];

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;
Porm, observamos uma diferena: a palavra enum pode
ser dispensada na declarao da varivel, enquanto que
em C obrigatrio,apesar desta pequena diferena a funcionalidade do recurso a mesma, ou seja, pode-se denir variveis que assumem estritamente os valores presentes na declarao de enumerao.
Este recurso torna-se til na padronizao de valores a serem usados como entrada de funes, por exemplo. Pode
ser considerada como uma funcionalidade mnemnica,
seu uso no altera o cdigo nal caso modiquemos o
programa para que use variveis inteiras ou strings de
mesmo valor do enum.
A seguinte sintaxe:
seq x = 3;
No permitida, mesmo que o valor presente no enum
seja avaliado como 3 pelo compilador em tempo de compilao. Isso pode parecer confuso, mas lembre-se de
que os valores sero atribuidos pelo compilador, logo isso
evita que o mesmo programa seja compilado em ambientes diferentes e tenha comportamento diferente.

linguagem C, porm seu tamanho na memria depende


da capacidade de otimizao do compilador usado. Tipicamente os compiladores para computadores usam uma
varivel do tamanho de char para representar o valor, o
que poderia ser considerado um desperdcio, mas devido
abundncia de memria no chega a ser inadequado.
Porm em sistemas pequenos h compiladores que armazenam o valor booleano em apenas um bit. Obviamente, se o processador possuir recursos de manipulao
de bits isso muito til e pode ser usado como um fator
de melhoria da qualidade do software desenvolvido. Em
outros ambientes, onde a manipulao de bits traga prejuzo para o desempenho usa-se a estratgia padro de
desperdiar um pouco de espao em favor de uma agilidade maior nas operaes. Portanto, embora as variaes
de utilizao do espao sejam muitas, o compilador sempre far a mais apropriada para cada ambiente de utilizao da linguagem.

6.2.2 Modicadores

O C++ conta com os modicadores de amplitude


(short,long) presentes na linguagem C e modicadores de acesso, alguns exclusivos do C++, que esto diretamente ligados a caractersticas da POO (programao
orientada a objetos). Desta forma descreveremos apenas
os tipos relevantes exclusivamente para a programao
6.2 Variveis
na linguagem escopo do livro presente sem nos aprofundarmos 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 aprofundaque 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
C":
objetos.
static short long unsigned signed

6.2.1

Tipos

Como na linguagem C, os tipos nativos do compilador const


em uso so referenciados por:
A linguagem C++ introduz um novo modicador chachar int oat double
mado const, que tem comportamento variado dependendo 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 declautuante 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 podem ter processadores de 8, 16 ou 32 bits. Portanto, o O inteiro x no poder deixar de ter valor igual a 4. Qualcompilador 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 bvalor 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:
Neste caso, a funo acima recebe um valor inteiro atravs de um ponteiro, que no obrigatoriamente precisa
ser constante no escopo fora da funo, porm dentro da
mesma a varivel ser constante. Fazendo este simples
procedimento teremos como fazer com que um smbolo
seja varivel fora da funo e constante dentro da mesma,
de forma que dentro do escopo da mesma s faamos leituras do seu valor. O artifcio cria duas consequncias
importantes: a primeira a melhor legibilidade do cdigo, visto que ao usarmos uma funo teremos certeza
de que os valores no sero alterados dentro da funo;
a segunda que poderemos evitar erros inadvertidos de
atribuio de valores varivel quando da construo da
funo.

int x = 1265; void main_loop_optimized() { while( true


) { // fazer alguma coisa } }
Considerando que em um programa que foi desenhado
para ambiente multitarefa isso no pode ser considerado
verdadeiro, pois o programa pode estar esperando que
uma das tarefas modique o estado da varivel para prosseguir seu curso, a otimizao acima ser um desastre,
uma vez que a funo acima jamais ser encerrada.
Para evitar isso fazemos:
volatile int x = 1265; void main_loop() { while( x ==
1265) { // fazer alguma coisa } }

E o compilador no poder mais avaliar que o valor de


x pode ser otimizado para o valor corrente, pois informamos na declarao que o valor da varivel pode ser
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 conhecimento 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
uma varivel pode ter seu valor alterado por fatores diversos, e portanto, no pode ser otimizada. Usando-a o
programador informa ao compilador que no deve interferir na forma com que o programa foi escrito para acesso
a esta varivel. Desta forma impede que erros inseridos
por otimizao estejam presentes na verso nal do executvel.
O uso desta palavra implica em mudana no comportamento do compilador durante a interpretao do cdigo.
As classes de objetos do tipo volteis s podero ser acessadas por rotinas que declarem aceitar como entrada dados volteis, da mesma forma que apenas objetos volteis
podem acessar variveis volteis. Esta amarrao faz
com que o uso de tais variveis se torne mais seguro.

A palavra class atribui a um conjunto de tipos de dados o


estado de modelo de objeto. Este conceito fundamental
para o modo avanado de programar usando o C++. Com
este identicador declaramos objetos, da mesma forma
que declaramos estruturas.
Uma classe pode ser denida em um cabealho header,
da seguinte forma:
class nome_da_classe { <tipo_1> variavel_1; <tipo_2>
variavel_2; . . . <tipo_n> variavel_n; ----- <tipo_n>
nome_funcao ( <tipo_1> variavel_1, <tipo_2> variavel_2, <tipo_3> variavel_3 ...); };

O mais interessante de observar a presena de uma funo dentro da declarao acima. Ento poderamos perguntar: Por que colocar uma funo dentro de um tipo?
Podemos declarar variveis volteis da seguinte forma:
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
tipo. Desta forma podemos ter tambm as seguintes declaraes como vlidas, alm do uso padro da linguagem
C":
struct data{ int a; int b; int c; }; class object{ int a; char
b; long w; oat p; void getData(); }; ... ... ... ... void
func() { data x; object y; ... ... y.getData(); }
Como podemos ver na funo acima se a varivel x for declarada para uma estrutura data o uso da palavra struct
no obrigatrio, assim como tambm no o para outros tipos de dados compostos.

CAPTULO 6. VARIVEIS E CONSTANTES

Captulo 7

Ponteiros

15

Captulo 8

Ponteiros
Em linguagem C, podemos denir variveis ponteiro,
ou seja, variveis que armazenam o endereo de outras
variveis. Este recurso largamente explorado pela linguagem, embora que deva ser usado com cautela por iniciantes devido ao seu poder destrutivo. Como linguagem
"irm mais nova" o C++ tambm permite o uso de ponteiros, o que a distingue de muitas outras linguagens orientadas a objeto. Embora seja muito difundida a idia da
criao de linguagens que no suportem acesso a ponteiros, basicamente pressupondo que todos os programadores so inexperientes, a falta deste recurso limita as capacidades de interao de programas com o hardware. Em
outras palavras, a falta de um meio de manipular ponteiros faz a linguagem limitada ou dependente de fabricantes
de bibliotecas que acessem o hardware.
A disponibilidade do uso de ponteiros em C++ agrega um
poder a mais ao conjunto da linguagem, porm implica
em necessidade de cautela na elaborao de programas
que usam deste recurso. Certamente, nem todos os programadores precisam ser considerados inaptos, a priori,
atravs da supresso ou insero de complicadores de recursos criados explicitamente para for-los a no usar
dos recursos. Por isso, a linguagem C++ disponibiliza o
recurso para quem deseja utiliz-lo e tambm apresenta
diversos outros recursos que so alternativas ao uso de
ponteiros quando eles no so imprescindveis.

Exemplo:
int *px;
Muitas vezes, iniciantes podem se sentir confusos porque quando declaramos um ponteiro usamos o * e quando
atribumos endereos a ele no usamos o *. A conceituao bsica a seguinte:
Declaramos o ponteiro com *, para que o compilador identique que a varivel um ponteiro;
Usamos o ponteiro sem *, para acessar o endereo
que ele aponta na memria;
Usamos o ponteiro com *, para acessar o valor do
dado armazenado na posio de memria;

8.2 O operador &


Na linguagem C, o operador & tem duas funes bsicas, funciona como operador da funo lgica AND e
como operador de leitura de endereos. Para operaes
com vetores, isso usado da seguinte forma:
int a = 12; int *pa; ... ... pa = &a; ... ... *pa = 100;

Ou seja, declaramos a varivel a, depois declaramos um


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

8.3 O ponteiro this

Se p um ponteiro, *p o valor apontado por p, ou


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

8.3. O PONTEIRO THIS


linguagens que suportam orientao a objetos. Ele um
membro inerente a todos os objetos que instanciamos em
programas escritos em C++.
Faremos uma breve explanao a respeito de objetos para
esclarecer este tpico. Objeto so parecidos com estruturas, uma diferena bsica que estes possuem habilidades 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 objetos. Por ora vamos nos ater a um conceito fundamental
importante para a noo de ponteiros em C++, a identidade de um objeto.
Veja, temos uma estrutura de dados que est na memria,
os dados esto l (variveis x e y), porm as funes no
estaro l, pois se tivssemos que copiar uma funo para
cada estrutura que crissemos o programa tomaria um tamanho monstruoso. O que se faz apenas guardar o endereo da estrutura em um ponteiro especial, o ponteiro
this. Assim, o compilador poder criar uma nica cpia
de funo para todas as estruturas que criarmos e depois
quando a funo quiser manipular os dados de uma estrutura em particular, o far atravs do ponteiro this.
Examinemos os detalhes mais de perto... Digamos que
instanciemos um objeto A da classe Data:
Data A; A.set_x(2); A.set_y(7);
Para acessar estas funes o compilador far:
Data A; A.set_x(2); // { Data *this = &A; // return
this->x = 2; // } A.set_y(7); // { Data *this = &A; //
return this->y = 7; // }
Desta forma podemos perceber como diferentes conjuntos de dados podem ser manipulados pela mesma funo.
Quando declaramos uma funo dentro de uma estrutura
de dados esta rotina recebe um ponteiro com o endereo
do conjunto de dados que deve tratar toda vez que for invocada pelo programa. Assim, sempre acessar os dados
atravs deste ponteiro, o this. Como todos os objetos
precisam ser identicados por esse ponteiro, ele denido para qualquer objeto com o mesmo nome: this.

17

Captulo 9

Vetores

18

Captulo 10

Vetores e Matrizes
10.2 Matrizes

Faamos uma pequena reviso de conceitos:


Vetores e matrizes so variveis compostas homogneas, ou seja, so agrupamentos de dados que individualmente ocupam o mesmo tamanho na memria
e so referenciados pelo mesmo nome, geralmente
so individualizadas usando-se ndices.

Podemos imaginar que uma matriz um conjunto de vetores que ocupam uma determinada rea de memria referenciada por um nome comum. Matrizes de tipos primitivos so conseguidas atravs de associaes do operador [ ], como por exemplo:

char A[32][16]; int B[12][26][10];


Vetores distinguem-se das matrizes apenas pela caracterstica 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 getFDaEm 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 explicitamente, vetores de caracteres para denir cadeias de
Ou seja, podemos adotar a mesma sintaxe para criar matexto, o que conhecido como o mais trivial uso de vetrizes 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 sisdados.
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 programador, todas as caractersticas bsicas legadas aos tipos 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
Os vetores em C++ seguem a mesma notao da linguagem C, via de regra declara-se o tipo seguido de um asterisco. Para acessar o valor apontado pela varivel usa-se
um asterisco de forma semelhante, como pode ser visto
no trecho de cdigo abaixo:

Ou seja permite declarar muitas variveis de uma forma


bem simples, poupa escrita e bastante compreensvel.

int *x; int a = 3; x = &a; cout <<" O valor do contedo


da posio 0x"; // O valor da posio 0x23A0209112
cout << hex << x << de memria " << *x << endl; //
de memria 3

19

O nmero que est dentro de brackets [] o size declarator. Ele que vai permitir ao computador dizer quantas variveis a serem geradas e logo quanta
memria dever ser reservada. A memria reservada para as variveis vo ser todas seguidas, um int
a seguir ao outro
H uma forma para no dizer o valor deste size declarator, mas isso apenas acontece antes da compi-

20

CAPTULO 10. VETORES E MATRIZES


lao, ou seja o compilador que vai fazer esse preenchimento por ns, visualizando o nosso cdigo e
contanto os membros que colocmos. Isto um automatismo dos compiladores recentes. chama-se a
isto iniciao implcita que vamos ver nesta seco.

As variveis geradas pelos arrays vo ser todos do


mesmo tipo.

o ndex comea no zero e no no 1. A razo disto tem


a ver com oset que refere ao valor adicionado para o
endereo base para produzir a segunda address. Bem no
entendi bem! Eu explico de novo: O endereo (address)
do primeiro elemento do array, o mesmo do que o endereo base do prprio array. ah espera a, o que esto
a dizer que o endereo do array igual ao do primeiro
elemento do array. Assim o valor que teria de ser adicionado, ao endereo base do array, para conseguirmos
o endereo do primeiro elemento seria zero. Agora sim,
percebi!

Reparem que o valor do size declarator um nmero. literal, ele no vai mudar quando o programa estiver a correr. Por isso quando no soubermos o nmero de elementos o que fazemos?
Erro: Um erro comum esquecer que o index comea no
zero, e portanto quando se querem referir ao ltimo elemento, esquecem-se que tm de subtrair uma unidade. O
Veja uma tentativa:
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 dacin >> numTests; int testScore[numTests]; return 0; }
dos.

Se o array for declarado globalmente em vez de ser localIsto 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 dinmica 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. PoReparem que h uma diferena entre literais e constandemos 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]

10.5 Declarar constantes

= { 44.4, 22.3, 11.6, 33.3}; char grades[5] = {'A', 'B', 'C',


'D', 'F' }; string days[7] = {"Sunday, Monday, Tuesday, Wednesday,"Thursday, Friday, Saturday"};

Pergunta: O que que acontece se dermos mais valores


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 vavarivel
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 elemenExemplo:
tos no inicializados cam com os valores defaut, que no
caso dos ints 0 no caso dos oats 0.0 e nos caracteres
const int numTests = 3;
o caractere nulo ("\0). No entanto se no inicializarPortanto 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


Aqui o compilador faz o trabalho por ns, conta os elementos e preenche o nmero de elementos

21

10.10 Const Constant arrays


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
ateno ultima iniciao! Quando colocmos as aspas
duplas o compilador acrescenta o "\0 na array que cria!
No tem []!! Esta at costuma ser a preferida pelos programadores, ao estilo de strings (Na verdade as strings
so arrays de char mas vamos falar disso num capitulo
prprio)

10.11 Atribuir valores ao array

Podemos ter duas dimenses

Ou melhor ainda podemos usar uma constante, para tornar o nosso cdigo mais abstracto.

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


int testScore[3]; cout << Enter test score #1: "; cin >>
testScore[0]; cout << Enter test score #2: "; cin >> testScore[1]; cout << Enter test score #3: "; cin >> testScore[2]; cout << Test score #1: " << testScore[0] <<
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
= 0; i < 3; i++) { cout << Test score #" << i + 1 << ": "
10.8 Arrays de vrias dimenses
<< testScore[i] << endl; } return 0; }

tipo_da_varivel nome_da_varivel [altura][largura];

#include <iostream> using namespace std; const int


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 +
1 << ": "; cin >> testScore[i]; } for (i = 0; i < MAX; i++)
[tamN];
{ cout << Test score #" << i + 1 << ": " << testScore[i]
<< endl; } return 0; }
como tambm poderamos ter innitas

10.9 Iniciando

Lembram-se da histria de termos o endereo do array


igual ao endereo do 1 elemento do array?

oat vect [6] = { 1.3, 4.5, 2.7, 4.1, 0.0, 100.1 }; int matrx
[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; char str
[10] = { 'J', 'o', 'a', 'o', '\0' }; char str [10] = Joao"; char
str_vect [3][10] = { Joao, Maria, Jose };

#include <iostream> using namespace std; const int


MAX = 3; int main () { int testScore[3] = { 74, 87, 91 };
cout << testScore[0] <<"\n"; cout << testScore <<"\n";
//array base e no um elemento particular do array return
0; }

Peguemos no exemplo:
int a [2][3]={1,2,3,4,5,6,}
Na memria teramos as coisas assim. ou seja os elementos so seguidos e do mesmo tipo
Portanto ter int a [2][3] equivalente a ter int a [6] o nome
que se d que diferente.
Pergunta: ser pedido espao par 6 ints ou antes um espao com o tamanho de 6 ints? Como ns sabemos que
os arrays os elementos tm endereos de memoria consecutivos, por isso, no podem ser pedidos 6 ints, pois se
fosse esse o caso, poderia acontecer que eles no cassem
juntos.

Pois bem vemos que quando mandamos imprimir o array,


ele d um endereo. Pois o valor do nome do array o
endereo do array.

10.12 Arrays como statements de


funes
Pegando no programa
#include <iostream> using namespace std; const int
MAX = 3; int main () { int testScore[MAX]; for (int i
= 0; i < MAX; i++) { cout << Enter test score #" << i +

22
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 assignValues(int[], int); void displayValues(int[], int); const int
MAX = 3; int main () { int testScore[MAX]; assignValues(testScore, MAX); displayValues(testScore, MAX);
return 0; } void assignValues(int tests[], int num) { for
(int i = 0; i < num; i++) { cout << Enter test score #" <<
i + 1 << ": "; cin >> tests[i]; } } void displayValues(int
scores[], int elems) { for (int i = 0; i < elems; i++) { cout
<< Test score #" << i + 1 << ": "<< scores[i] << endl; }
}

10.13 Arrays como argumentos de


funes
// arrays as parameters #include <iostream> using namespace std; void printarray (int array[], int length) /*funo
com 2 argumentos,um deles um array */ { for (int n=0;
n<length; n++) cout << array[n] << " "; cout << "\n"; }
int main () { int a[] = {5, 10, 15}; printarray (a,3); //passo
array como argumento return 0; }
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}; doubleThem(myInts, 10); //passei o array base for (a=0;
a<10; a++) { cout << myInts[a] <<\t; } return 0; }
void doubleThem(int a[], int size) { int i; for (i = 0; i <
size; i++) { a[i] = 2 * a[i]; } }

CAPTULO 10. VETORES E MATRIZES

Captulo 11

Estruturas
11.1 Breve reviso
11.1.1

apropriado, geralmente, dentro de algum bloco de cdigo onde venha a ser usado. Podemos ver logo abaixo, o
exemplo de uma declarao de estrutura:

Conceito

struct Estrutura { int Inteiro; double PontoFlutuante;


Da linguagem C tambm temos o conceito de estrutura, char Caracteres[10]; }; int main() { Estrutura MinhaVado 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 dados de diversos tipos diferentes, com tamanhos diferentes. 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 usaele 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 tregem. 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 manipulados 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 memria. Todas as outras formas de tratar os dados devem ser As estruturas em C++ funcionam de modo anlogo ao
apresentado em linguagem C. A diferena, a princpio,
providas pelo cdigo do programa.
notvel entre elas nas duas linguagens que em C++" o
especicador struct no precisa ser escrito quando criamos a estrutura:

11.1.2

Implementao

Em C, para criar uma estrutura de dados chamada st, dePara 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:
Estrutura st;
isso temos a seguinte sintaxe:
struct Estrutura { <Tipo A> NomeVariavelA; <Tipo A>
NomeVariavelA2; <Tipo A> NomeVariavelA3; <Tipo
B> NomeVariavelB; <Tipo C> NomeVariavelC; <Tipo
D> NomeVariavelD; ... ... <Tipo Z> NomeVariavelZ; }
[<NomeVariavelComposta>];

Este simples detalhe revela uma caracterstica importante


das estruturas em C++: Nesta linguagem as estruturas
so tratadas como tipos primitivos de objetos. Elas tm
caractersticas semelhantes s classes, que veremos nos
captulos subsequentes.

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 ob23

24
jeto que as estruturas mantm nesta linguagem. Objetos
devem ter propriedades (variveis) e mtodos (funes
membro), por isso temos a possibilidade de criar funes
dentro do corpo das estruturas, com a nalidade de lidar
com os dados que elas mantm.

11.3 Construtores

CAPTULO 11. ESTRUTURAS


Repare que demos valores defaut s variveis. Agora no
estamos no caso de ter p1.name=??? Por mais instncias
que criemos eles vo ter sempre valores padro.
Constructor com argumentos
Termos um constructor sem argumentos um melhoramento face ao defaut constructor pois agora temos valores
defaut para as variveis membro. Porm seria melhor se
consegussemos inicializar as variveis membro com valores dados pelo utilizador enquanto o programa estivesse
e a correr. E realmente podemos fazer se passarmos argumentos.

Os construtores so funes que so criadas automaticamente sempre que tentamos criar um objeto. Eles funcionam da mesma maneira que construtores de classe. A
esses que so criados automaticamente so os chamados
de defaut.
#include <iostream> #include <string> using namespace
std; const int MAX = 3; struct Person { string name; int
Se escrevermos o cdigo:
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 "
<< p1.height << endl; system (pause); return 0; }
The persons name is and height is 858993460
Aqui criado um defaut constructor no momento em que
Repare que os argumentos do construtor tm de estar na
criamos a instncia p1 ie com a linha Person p1;
ordem esperada
Como as variveis membro no foram iniciadas, o valor
de name est vazio e o na varivel height est um valor
Separar o construtor prototype da implementao
qualquer que lixo!
Constructor sem argumentos
Podemos ter um construtor sem argumentos que ao contrrio do defaut constructor designa valores defaut s variveis membro.
struct Person { string name; int height; Person() //construtor sem argumentos { name = No name assigned";
height = 1; } };

O nome do construtor sempre igual ao nome da


estrutura, sem exceo.
O construtor no retorna qualquer valor, sem exceo
Refazendo o nosso exemplo
#include <iostream> #include <string> using namespace
std; const int MAX = 3; struct Person { string name; int
height; Person() { name = No name assigned"; height =
1; } }; int main () { Person p1; cout << The persons
name is "<< p1.name << " and height is " << p1.height
<< endl; system (pause); return 0; }

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


std; const int MAX = 3; struct Person { string name;
int height; Person(); //construtor sem argumento Person(string, int); //construtor com dois parmetros, apenas
necessrio dizer o tipo dos parmetros o nome no
necessrio) }; Person::Person() { name = No name
assigned"; height = 1; } Person::Person(string s, int h)
{ name = s; height = h; } int main () { int metro; string
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
is " << p1.height << endl; system (pause); return 0; }

Vamos ver a funo main(): declarmos 2 variveis


uma int e outra string. Pedimos para a pessoa escrever o nome e colocmos o valor na varivel string,
depois pedimos a altura e colocmos na varivel int.
Depois chammos o construtor com dois argumentos e passamos as variveis anteriores como argumentos. Por m mandmos imprimir os valores das
variveis membro da estrutura.
Repare que para denirmos fora o construtor recorremos ao operador scope ::

11.3. CONSTRUTORES
Person::Person() Person::Person(string s, int h)

Repare que no prototype dos construtor apenas tivemos de dizer o tipo dos parmetros

25

Captulo 12

Operadores
Os operadores realizam, como o nome sugere, operaes
entre dois tipos de dados. Existem muitos operadores,
mas citaremos aqui os fundamentais e, conforme as necessidades dos tpicos posteriores, citaremos todos os demais.

12.1 Compatibilidade
Os operadores padres da linguagem C podem ser usados de forma semelhante na linguagem C++. Aliadas s
funcionalidades tradicionais do C podemos criar operaes diferentes para os operadores. Esta funcionalidade
conhecida como sobrecarga de operadores e ser descrita
em captulo posterior.

12.2.1 Entendendo o operador


Basicamente, temos dois tipos de implementao para
operadores, o tipo global e o tipo membro de classe. Os
dois tipos so usados regularmente nas implementaes
mais comuns. Analisaremos o tipo global, uma vez que
ainda no temos uma noo de classes suciente para
abordar o tipo membro de classe.
Digamos que temos uma estrutura ponto, como denida
abaixo:
struct Ponto { int x; int y; };
Uma vez que tenhamos denido um ponto, nada mais natural que queiramos somar, subtrair, enm operar, pontos diferentes de acordo com nossas necessidades. Para
isso podemos criar operadores para fazer isso, da seguinte
forma:

12.2 Como C++ interpreta os operadores

Observamos a quantidade de parmetros, o retorno


e a forma de chamar o operador que queiramos denir e criamos uma funo que execute a operao
desejada;

Para dar uma base de entendimento para a sobrecarga de


operadores iremos introduzir o modo como o compilador
C++ entende os operadores. Este modo de interpretar os
operadores implementado para dar suporte aos recursos
de POO da linguagem. O entendimento do modo de funcionamento do mecanismo de compilao pode diminuir
as dvidas que surgem no estudo de operadores em C++.
importante entender que a linguagem deve servir de
base para a criao de entidades de dados autnomas e
operveis. Logo, o compilador deve ser generalista ao
enxergar operaes com tipos primitivos e tipos criados
pelo programador (classes). Por estes fatores, o compilador utiliza-se de uma interface funcional para implementao dos recursos de operadores.
Os operadores so tratados como funes, de forma a
possibilitar a alterao do seu comportamento em determinados casos. Os operandos so tratados como argumentos de funes, enquanto que o resultado da operao
tratado como retorno da funo do operador. Esta interface faz com que possamos programar o comportamento
das operaes e alter-las quando nos seja conveniente.

Inserimos o cdigo da referida funo dentro de uma


chamada de operador, usando a palavra reservada
operator seguida do operador que desejamos denir:

Ponto operator+ ( Ponto a, Ponto b ) { Ponto soma;


soma.x = a.x + b.x; soma.y = a.y + b.y; return soma; }
E assim, o operador entendido como uma funo, sendo
a sobrecarga um processo de denio da operao a
ser executada. Recebe esse nome porque todo operador
j existe e a denio de uma nova funcionalidade apenas adiciona (sobrecarrega) as habilidades anteriores do
operador. Embora isto seja comum, bom lembrar que
operaes de tipos primitivos no podero ser modicadas, restando apenas a funcionalidade de criar operadores
para nossos tipos (classes).

26

12.3. OPERADORES ARITMTICOS

12.2.2

Os argumentos

27
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 intuitiva. 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,
o resto da diviso inteira. por isso que no nosso exemplo
c = operator+( a, b );
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 uturaes matemticas entre dados. So 5 operadores arit- ante ou entre ponto utuante e inteiros/caracteres. Isso
efetuar a diviso at que o resto seja zero, ou quando o
mticos em C++:
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 dioat 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 tambm pode realizar operaes aritmticas com os tipos
char e wchar_t.
O retorno da operao ser tambm um nmero (real, inteiro ou at mesmo um caracter, conforme os tipos dos
operandos).

12.3.2

Diviso inteira e diviso real

Existe, para a linguagem, diferena entre uma diviso entre nmeros inteiros e entre nmeros reais (ponto utuante). 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!";

14.1 Deciso em C++

Mas se voc quiser que o computador execute vrias linhas aps o if se este for verdadeiro? Basta usar chaves:

Em C++ os mtodos de tomada de deciso presentes na


linguagem C esto disponveis para as tarefas mais corriqueiras que o programa deve executar. Alm desta forma
de controle de decises, C++ prov certas funcionalidades relacionadas a objetos que modicam a forma como o
cdigo estruturado e, por consequncia, decidem como
o programa deve se comportar em determinadas situaes. Examinemos os mtodos bsicos e analisemos de
forma simples as estruturas de deciso presentes no modelo de programao orientado a objetos, para entender
como isso poder nos ajudar a tornar o cdigo mais bem
construdo.

if(variavel) { cout << A varivel verdadeira...\n"; cout


<< E continua executando << at que seja fechado o
if << " com o }"; }

else
tambm possvel usar o bloco else para o computador
executar vrias linhas de cdigo caso uma condio tenha
o valor booleano falso. Por exemplo:

if(temperatura < 20) { cout << Est frio"; } else { cout


De modo geral, a maioria das linguagens de programao << Est calor"; }
existentes utiliza-se das estruturas if-else ou switch-case.

14.1.1

Assumindo que a varivel temperatura tem tipo inteiro


(int), se esta contiver um valor, por exemplo, 20, ser
apresentada na tela a mensagem Est calor, uma vez
que 20 < 20 uma expresso contradio, logo tem o
valor booleano falso.

if-else

if
Se voc quer que o software execute um determinado comando somente em certas situaes, utilize if para determinar isto. O programa vai, ento, executar a primeira
linha de cdigo aps o if, se a declarao entre parnteses for verdadeira. Exemplo:

Podemos ainda encadear vrios else, e obter ainda mais


possibilidades:

if(deposito < 20) { cout << Depsito de gasleo inferior


a 20%"; } else if(deposito < 50) { cout << Tem menos
de metade do depsito"; } else { cout << Ainda tem
#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 distinguir por mais nveis, bastaria acrescentar mais } else A sintaxe :
if(...condio...) { para distinguir os diferentes patamares.
[Relational expression] ? [statement if true] : [statement if false]
De notar que, cada caso avaliado individualmente, por
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.

14.1.2

switch

H quem goste de usar este operador porque poupa escrita, 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)
{ int num; cout << Enter a whole number: "; cin >>
e construo diferente
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
pode alterar durante a vida do programa), neste
exemplo A, B,
O defaut serve para a condio de todas as avaliaes
dos casos anteriores der falsa. ( tipo o else)

a>b ? a : b // returns whichever is greater, a or b.

14.2 O Comando goto

O goto realiza um salto para um local especicado. Este


O break serve para terminar o switch, caso contrlocal 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 ternome_do_rtulo: .... goto nome_do_rtulo; ....
minar o switch.
// 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
Repare no rtulo.
fazer coisas como:
Nota: Evite o uso de goto quando for possvel usar esif (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 obrigatoriamente 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


int exit (int exitcode);
Esta funo usada por alguns sistemas operativos e podem ser usadas para chamar programas. Por conveno
o cdigo 0 se sada signica que o programa terminou
normalmente, como previsto, se vier com outro nmero
signica que houve um erro e algo de inesperado sucedeu.

31

Captulo 15

Estruturas de repetio
Laos (loops em ingls), ou estruturas de repetio, so
comandos existentes nas linguagens de programao destinados a executar uma ou mais instrues quantas vezes forem necessrias. Cada ciclo de um loop chamado
de iterao. Podemos ter tambm loops dentro de outro
loop.

15.2 Do-While
O lao do-while um while invertido, onde voc coloca
as instrues a serem repetidas antes da vericao da
condio de execuo. Isso signica que os comandos do
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


computador a executar determinadas instrues enquanto
uma condio for verdadeira. Isso faz com que um comando seja executado uma vez a cada vericao da condio. De modo geral o comando sempre deve ser elaborado de forma que se leve a condio de execuo a ser
falsa em algum momento, de forma a interromper o lao
para que o resto do programa entre em execuo.

Onde condio a condio de execuo do lao dowhile. Os comandos pertencentes ao lao somente deixaro de se repetir quando a condio for falsa.

15.1.1

Sintaxe

O algoritmo abaixo mostra como seria o algoritmo exemplo usado na seo do lao while convertido para o uso
do lao do-while.
#include <iostream> using namespace std; int main() {
int contador; // Declara a varivel contador. contador=1;
// contador recebe o valor 1. do { cout << contador <<
endl; // Imprime contador. contador++; // Incrementa
contador em uma unidade. } while (contador<=10); //
Enquanto contador for menor ou igual a 10. return 0; }

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
na tela do nmero 1 ao nmero 10. Perceba o uso de
uma varivel inteira intitulada contador. Esta varivel
utilizada para armazenar um valor a ser impresso bem
como participar da condio de execuo do lao. Assim
que a varivel atingir o valor 11 o programa segue para o
comando logo aps o lao.

Como o uso de uma varivel como contador nos laos


algo frequente, foi criado um outro lao que traz em sua
estrutura campos para abrigar os comandos de atribuio
de valor inicial e incremento/decremento do contador. O
nome deste lao for, para em ingls.

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 parada. Esta condio vericada logo no incio do
lao, imediatamente aps a concluso do parmetro1 e a cada passo quando o <comando> executado.

Exemplo 1:
while (condio) comando1; // Este comando faz parte
do lao. comando2; // Este comando no faz parte do
lao.

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 contagem 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 diferente. 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 saltar uma determinada iterao do loop, enquanto o break
for (int num =1; ; num++) { cout << num << " "; }
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 (counnum++; }
ter++ < num) { if (counter % 13 == 0) continue; total
+= 3; } cout << Total for " << num << " items is $" <<
total; return 0; }

15.4 Dicas
15.4.1

Bloco de Comandos

Neste exemplo quando o conter for mltiplo de 13, a instruo 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 comandos 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
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 instruo
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 15. ESTRUTURAS DE REPETIO

Captulo 16

Funes
Funo, do latim functio, onis, representa na computao, um pequeno algoritmo com uma funo simples e
bem denida. como se cada funo fosse um micro
programa, ou um tijolo na construo do programa principal. O uso de funes facilita muito o desenvolvimento,
pois, divide o problema principal em pequenos problemas mais simples. Essa tcnica se chama, Dividir para
conquistar.
A experincia mostra que o uso de funes facilita e acelera a criao e manuteno de sistemas.
Todo programa em C++ tem pelo menos uma funo, o
main. Veja o exemplo do programa em C++:
#include <iostream> //Biblioteca com funes de entrada e sada de dados using namespace std; int main
(void) //Funo principal do programa { cout << Ol
mundo!"; //cout tambm uma funo, e precisa ser
importada da biblioteca iostream //Esta funo main
retorna um valor int, ou inteiro, por isso faz a operao
de retornar 0 return 0; }

A funo no pode ser overloaded apenas com diferentes


tipo de retorno de funo (ie, uma funo retornar ints e
a outra retornar oats) ento os parmetros que interessam.
#include <iostream> using namespace std; void ConvertFToC(double f, double &c); void ConvertFToC(oat
f, oat &c); void ConvertFToC(int f, int &c); int main()
{ double df, dc; oat , fc; int i_f,i_c; //if is a reserved
word df = 75.0; = 75.0; i_f = 75; // The compiler resolves the correct // version of ConvertFToC based on // the
arguments in each call cout << Calling ""double"" version << endl; ConvertFToC(df,dc); cout << df << " ==
" << dc << endl << endl; cout << Calling ""oat"" version << endl; ConvertFToC(,fc); cout << << " == "
<< fc << endl << endl; cout << Calling ""int"" version
<< endl; ConvertFToC(i_f,i_c); cout << i_f << " == "
<< i_c << endl << endl; system (pause); } void ConvertFToC(double f, double &c) { cout << In ""double""
version << endl; c = (f - 32.0) * 5. / 9.; } void ConvertFToC(oat f, oat &c) { cout << In ""oat"" version <<
endl; c = (f - 32.0) * 5. / 9.; } void ConvertFToC(int f,
int &c) { cout << In ""int"" version << endl; c = (f 32) * 5. / 9.; }

Do exemplo Ol mundo, vemos que toda funo em C++


tem um nome. O nome de uma funo junto com o tipo
de dados que retorna chamado assinatura da funo.
O que que acontece se tivermos um n diferente de argumentos entre a chamada e a denio?
int main (void) //Assinatura da funo main
A soluo aqui proposta quando no sabemos a quanEssa 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 devoid, 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 sonas 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
------------Cabealho--------------------------------*/ /*Denimos 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 especicado no prottipo e no na declarao da funo.

CAPTULO 16. FUNES

Captulo 17

Referncias de dados
17.1 Variveis de referncia

jamais alterar o valor do seu argumento x.

Em C++ podemos criar variveis que podem ser uma


alternativa para os ponteiros em algumas situaes. A
vantagem de no usar diretamente o endereo (valor de
ponteiro) em situaes onde no precisamos lidar diretamente com valores de memria torna a programao mais
segura e simplicada. Podemos deixar as operaes com
ponteiros apenas para quando for estritamente necessrio.

Diferentemente da linguagem C, a chamada a uma funo em C++ pode alterar o valor de uma varivel denida
antes da chamada da funo, mesmo sem esta varivel ser
explicitamente passada como um ponteiro. Este modo
chamado de passagem por referncia. Em termos mais
gerais, signica a passagem da varivel propriamente dita,
para o corpo interno da funo com outro nome, aquele
denido na lista de parmetros da funo.

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 declarnome 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 simples:
Temos em C++ o operador & que se comporta diferenteint 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 referncia 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
&x quando usado na declarao de varivel, cria
alterar o valor de a usando b.
uma referncia;
&x quando usado como parmetro na declarao de
uma funo faz com que suas chamadas transra o
argumento/parmetro passando-o de forma similar
a passagem de seu pointero. (Passagem por referncia).

17.2 Passagem de parmetros


Na linguagem C, durante a chamada de uma funo, os
argumentos (parmetros) tm seus valores copiados para
a rea de processamento da funo. Depois que os mesmos foram usados dentro do bloco de processamento da
funo, eles so descartados. A funo retorna o processamento para o bloco que a chamou trazendo apenas o
valor de retorno. A nica maneira de fazer com que a
funo modique o valor de alguma varivel denida no
bloco de programa que a chamou pass-la por um ponteiro com o seu endereo.

Em termos semnticos, ao passar a varivel para uma


funo onde o parmetro uma referncia, o endereo
da varivel atribudo ao endereo do parmetro. Desta
forma, o parmetro a mesma varivel passada, no trecho de cdigo onde a funo foi invocada, assumindo um
nome diferente dentro da funo.
Vejamos um exemplo usando a funo anterior:

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 seEm 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 referncorpo principal a varivel estar decrementada.
cia:

17.3 Exemplo: alterando o valor da


varivel usando referncia

#include <iostream> using namespace std; void Swap


(int &i,int &j) { int t=i; i=j; j=t; } int main () {
int a,b; a=5; b=10; cout<<a<<"\t"<<b; Swap (a,b);
cout<<a<<"\t"<<b; system (pause); return 0; }

#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 utilireturn 0; }
zador:
Ou seja nestes dois cdigos temos uma passagem por reComo 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 adteremos 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
exemplo anterior tinha

No prototype da funo (conrmar o ponto e virgula)

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 Na function header
pletamente ignorada e camos sempre com a primeira.
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 providenx) // by address
ciam uma maneira de retornar valores das funes.
Vejamos o exemplo
#include <iostream> using namespace std; int main() {
int val1 = 10; int val2 = 20; int &ref = val1; cout <<
val1 is " << val1 << endl; cout << val2 is " << val2 <<
endl; cout << ref is " << ref << endl; ref = val2; //What
does this do? cout << endl << ref = val2 << endl; cout
<< val1 is " << val1 << endl; cout << val2 is " << val2
<< endl; cout << ref is " << ref << endl; val2 = 30; cout
<< endl << Setting val2 = 30 << endl; cout << val1 is
" << val1 << endl; cout << val2 is " << val2 << endl;
cout << ref is " << ref << endl; system (pause); return
0; }

17.4 Exemplo: Swap


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

dentro do body function (dentro da prpria funo)


x *x
Podemos pensar que passando por referncia parece ser
muito mais simples do que passado por address.
Na verdade existem certas funes da biblioteca que s
permitem a passagem por address.

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
necessrio recordar um pouco sobre o funcionamento da
litaro inserir dados e fazer reporte da falta deles.
memria e suas operaes relacionadas a Buer.
No C++ a entrada e sada podem ser feitas atravs da biblioteca iostream. Para podermos us-la deveremos co- Buerizao um meio de sincronizao entre dispositivos de velocidades diferentes, tais quais memria e dispolocar a linha de cdigo: #include <iostream>
sitivos de armazenamento mecnicos, como discos magA 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 fatas, 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 recebrecursos 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
dados sero escritos imediatamente. o caso da es cin - Este objeto fornece entrada de dados buericrita no dispositivo cerr;
zada atravs do standard input device, o dispositivo de entrada padro;
cout - Este objeto fornece sada de dados buerizada atravs do standard output device, o dispositivo de sada padro;
cerr - Este objeto fornece sada de dados no bufferizada para o standard error device, o dispositivo de erro padro, que inicialmente denido para
a tela.

buered - signica que os dados sero mantidos


num buer de memria at que o dispositivo de
destino solicite, ou que um comando de descarregamento seja executado, ou quando o buer estiver
cheio. O problema que se o programa interrompido antes do buer ser escrito esses dados so perdidos.

clog - Este objeto fornece sada buerizada atra- 18.2 cout


vs do standard error device, o dispositivo de erro
cout << hello"; // mostra a palavra hello no
padro que inicialmente denido para a tela.
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
frase. Segunda frase. Terceira frase. */
tuitivas para o programador.
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
que por denio o ecr (monitor).
podem ser acessadas diretamente nos programas.
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 operador 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
operao de apresentao dos dados na sada; Note que os
tipos de dados que so passados para o cout so diversos,
ou seja, no importa qual o tipo de dado que ser entregue
ao cout, de alguma maneira ele sempre formatar de uma
maneira legvel no monitor. Nos captulos mais adiante
veremos como fazer com que tipos de dados diferentes
sejam tratados pelo mesmo objeto.

18.2.1

Escape Sequences

Aqui temos o operador de extrao ">>" que diz que tudo


o que o teclado escrever, coloque esses dados na varivel
que me segue. Este operador consegue at traduzir o conceito de dados de fora para dentro.
#include <iostream> using namespace std; int main(void)
{ int testScore; cin >> testScore; cout << Your test
score is " << testScore << "\n"; #ifdef WIN32 system
(pause); /* Necessrio apenas para sistemas Microsoft, em modo grco. Em UNIX, variantes e
similares use um terminal de texto e esta funo no ser
necessria. */ #endif return 0; }

H um conjunto de caracteres, ns chamamos de string.


Mas no exemplo anterior quando usamos o "\n, ns antes
dissemos que o cout com o operador << iria colocar no
monitor todos os caracteres que estivessem entre aspas.
Acontece que existem estas strings especiais chamadas
de escape sequences - que de alguma forma alteram o
sentido das strings. Existem muitas destas sequncias. As
mais conhecidas so estas:

H mais um pormenor. O computador est espera de


um Return (ENTER, ou New Line, ou Espao em
Branco ) para nalizar a entrada de dados na varivel, at
l o cursor aparece a piscar.

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 programa ainda no tinha compilado, e agora temos entrada
de dados quando o programa j est compilado e a correr/rodar.

\n nova linha muda o cursor para uma linha abaixo


\r retorno

Bem, na verdade, este ponto muito importante, por


que Vejamos mais a baixo a questo de termos 2 entradas.

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
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 compilador 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
permitido, aqui temos o caso em que vai ser colocado um
\? sinal de interrogao (?)
nmero estranho. Isto no est perfeitamente explicado.

\b deleo reversa

\\ 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


a piscar sem o utilizador saber o que fazer. Alm de que
temos o problema de overow em execuo, portanto
bom que o utilizador cumpra os requerimentos.

No caso de no conter argumentos apenas ir ler um caractere, em vez de uma cadeia de caracteres.

No caso de ter um argumento, ela aceita qualquer tecla


incluindo o enter. (o que no se passa com o cin e o opeDe 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, \nqualmos 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.

18.3.1

Lendo um caractere

Porm se pressionarmos uma tecla de caractere imprimvel, 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
>>, ou por funes como get() ou getline() do objeto cin.
digitar o caractere. Isto leva a vrias questes.
Quando o loop comea, o input buer est vazio.
O problema pressione uma tecla para continuar...
#include <iostream> using namespace std; int main(void)
{ char ch; do { cout << Pressione S ou s para sair,
qualquer outra tecla para continuar: "; cin >> ch; if (ch
!= 'S' && ch != 's) cout << Deseja continuar?"<<endl;
else cout << Saindo..."<<endl; } while (ch != 'S' && ch
!= 's); #ifdef WIN32 system (pause); #endif return 0; }

O programa funciona bem se pressionarmos S ou s


para sairmos;

Se digitarmos apenas o enter, sendo este o primeiro e


nico caractere no imput buer, ele removido do
input buer e atribudo varivel ch, ento o input
buer est vazio na prxima iterao do loop;
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 caractere nova linha permanece no input buer. Isto
faz com que na prxima iterao do loop, no haja
a oportunidade para entrar com dados.

O programa funciona bem se pressionarmos qualOu 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 acontece, 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 Com um argumento, o argumento o nmero mteres, mas tambm o pode ser sem argumentos ou ainda
ximo de caracteres a ser removido do input buer.
apenas um argumento.

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 depois 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)
{ char name[80]; int courseNum; cout << Informe o
no encontrar o nova linha.
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
1. Colocar sempre a funo ignore() depois do cin e do
(pause); #endif return 0; }
>>;
Ora este programa funciona muito bem, MAS
Se pressionarmos a tecla Enter para continuar, teremos
de fazer isso duas vezes, pois a primeira vez ignorada.
A razo: que no existe nada no input buer quando
a funo ignore chamada, por isso que a tecla enter
necessita de ser pressionada 2 vezes, colocando um caractere nova linha a mais no buer para a funo ignore()
remover.
Se tentarmos modicar isto atravs do if?
#include <iostream> using namespace std; int main(void)
{ char ch; do { cout << Pressionar S ou s para sair,\n
qualquer outra tecla para continuar: "; cin.get(ch);
if (ch != '\n') cin.ignore(); if (ch != 'S' && ch !=
's) cout << Deseja continuar?"<<endl; else cout <<
Saindo..."<<endl; } while (ch != 'S' && ch != 's);
#ifdef WIN32 system (pause); #endif return 0; }
Agora sim temos todos os problemas resolvidos e isto
agora funciona!!

18.3.4

cin, cin.get(), cin.getline()

Razo: O cin>>" deixa sempre o nova linha


no input buer. Assim devemos elimin-lo
com a funo ignore().
2. No colocar a funo ignore(), no caso de ser sem
parmetros, depois do getline();
Razo:O getline() remove o caractere nova linha que termina a entrada do input buer,
portanto no necessrio o ignore().
3. Vericar se temos o caractere nova linha no input
buer depois de utilizar o get(), se tivermos deveremos utilizar o ignore().
Razo: A funo get() com um argumento
deixa o caractere nova linha no input buer
se pressionarmos um caractere e o enter. mas
no deixar, se apenas pressionarmos o enter.
portanto necessrio conrmar.

18.4 Entrada de valores para variveis 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
ao mesmo tempo
entrada.
#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 enInforme 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


#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 diferentes. Temos de ter ateno na ordem de entrada.
Pergunta: se escrevssemos duas palavras para o nome,
apenas a primeira que apareceria a 2 palavra que estava
separada da primeira para um espao seria colocada na
varivel peso.

43

Captulo 19

Entrada e sada de dados 2


19.1 Entrada/Sada em cheiros
(arquivos)

joao, e que tem a extenso .doc que refere usualmente a


documentos do WORD no primeiro caso e com extenso
".odt do OpenOce no segundo. Outros tipos de extenses 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 introduzindo 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
e tipo texto
observar o tema neste momento.
Existem na verdade dois tipos de cheiros(arquivos): os
do tipo texto e os do tipo binrio.

19.2 Gravar (Salvar) os dados para


um cheiro(arquivo)

Os arquivos tipo texto apenas armazenam texto obedecendo uma codicao de caracteres, a mais comum a ASCII, isto implica no uso do cdigo para
armazenamento, ou seja, pode ser que a codicao
seja interpretada antes de ser efetivada no meio de
armazenamento.

Os dados que mantemos nos programas esto guardados


na memria RAM, que limpa quando o programa ou
computador para de funcionar. Isso implicaria que perderamos toda a informao! Porm existe uma maneira
para tornar os dados persistentes que gravar os dados
num cheiro (arquivo) no hard drive (disco rgido) ou
no outro meio persistente. Nas formas mais diretas de escrita podemos passar os dados em formato binrio para
o cheiro(arquivo). Outros meios avanados para guardar dados podem envolver bases de dados relacionais ou
XML.

Os arquivos binrios podem guardar mais informao, como imagens, base de dados, programasPor
exemplo, editores de texto com formatao, como
o OpenOce e o Word, guardam os seus arquivos
em formatos binrios, porque eles possuem alm do
texto, informao acerca da formatao do texto,
para as tabelas, as listas numeradas, tipo de fonte,
etc... da aparecerem os caracteres de formatao
tipo 6, L, h5

19.3 O que um cheiro(arquivo)?


Um arquivo uma coleo de dados que esto localizados numa memria persistente tipo hard drive, cd-rom,
etc. Para identicarmos o arquivo podemos atribuir-lhe
um nome (lename). Os lenames tm usualmente
uma extenso, que determina o tipo de arquivo em sistemas operacionais semelhantes aos da Microsoft , mas
que podem ser dispensados em sistemas operacionais que
guardam as caractersticas dos arquivos no meio de armazenamento, tais quais sistemas UNIX e seus similares
GNU/Linux, FreeBSD, etc... A extenso representada
por 3 ou 4 letras que seguem aps o nome do arquivo
e um ponto ".. Por exemplo: joao.doc ou joao.odt.
Isto diz-me que temos um cheiro(arquivo) que se chama

Os arquivos binrios podero ser mais bem explorados


em um tpico avanado, vamos trabalhar inicialmente
com arquivos tipo texto, que poderemos operar de maneira mais simplicada.

19.5 biblioteca padro fstream


At agora temos usado a biblioteca iostream (i de input
+ o de output + stream), que suporta, entre vrias funcionalidades, o objeto cin para ler da standard input (que
usualmente o teclado) e o objeto cout para standard
output (que usualmente o monitor)

44

19.8. USANDO A FUNO MEMBRO OPEN


Ora, agora queremos ler e escrever para cheiros(arquivos) e isso requer a biblioteca fstream (f de le
+ stream). Esta biblioteca dene 3 novos tipos de classe:

45

19.8 Usando a funo membro


open

ofstream (apenas para sada out to a le. serve Esta funo tem como primeiro argumento o nome e lopara criar, manipular cheiros (arquivos) e escrever, calizao do cheiro/(arquivo) a ser aberto, o segundo argumento especica o modo de abertura.
no serve para ler).
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 indiserve para ler cheiros (arquivos), receber dados dos camos o caminho todo: c:\\....\\joao.doc em sistemesmos, 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 directoand 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:
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 outque 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 parmetro que o nome do arquivo e o 2 o modo de abertura. */
stream.

19.6 Abrir um cheiro(arquivo)

Podemos recorrer a dois mtodos para abrir um cheiro


Observe que estamos abrindo o arquivo students.dat em
(arquivo):
modo binrio e ao mesmo tempo com o modo append,
isto signica que abriremos o arquivo e poderemos pre1. 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


O construtor uma funo que automaticamente chamada quando tentamos criar uma instncia de um objeto.
fstream ale; // criado uma instncia do fstream chamada de ale
Os construtores de objetos podem ser sobrecarregados,
ou seja, para a mesma classe podemos ter um construtor
sem argumentos, com um argumento, dois argumentos,
etc. No exemplo anterior criamos um sem argumentos.
Os construtores no retornam valores, geralmente o compilador reporta erro quando se declara funes que retornam valor e estas tm o mesmo nome da classe, pois este
nome reservado para os construtores. Vamos dar um
exemplo com dois argumento:

19.9 Comparando os dois mtodos


(pela funo membro e pelo
construtor)
O primeiro mtodo similar a ter
int age; age=39;
O segundo mtodo similar a
int age=39;

A escolha do melhor mtodo em cada situao depende


do contexto em que estamos criando o cdigo, geralmente
quando j temos o objeto criado e ele est fechado poofstream 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 funcionalidades, dependendo de como o projeto foi idealizado.
joao.doc para operaes de sada.

46

19.10 Abrir um arquivo para leitura

CAPTULO 19. ENTRADA E SADA DE DADOS 2


Agora, vajamos um exemplo mais completo:

#include <fstream> #include <iostream> using namespace std; int main () { ifstream arq; //crio objeto arq da
classe ifstream - leitura string str; arq.open(joao.doc);
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
o arquivo foi aberto satisfatoriamente atravs da funo
ifstream arq (joo.doc);
membro good(), que tambm retorna verdadeiro se o arquivo 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)
H mais uma nota a fazer, se quisermos ler e escrever, no
podemos usar o ofstream e o ifstream ao mesmo tempo,
teremos de usar o fstream. Teremos de fazer:
fstream a (joo.doc, ios::in | ios::out);
Neste caso, o comportamento padro preservar o contedo do cheiro (arquivo) ou cri-lo caso ele no exista.

19.11 Vericar se o cheiro (arquivo) foi aberto.

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
com um cheiro (arquivo) aberto, porque alguns sistemas operativos (operacionais) limitam o n de cheiros
(arquivos) abertos, e estando este aberto impede que outros se possam abrir e por m porque se no fecharmos,
outros programas no podero abri-lo at que o fechemos. Este comportamento faz parte de um esquema de
controle de acesso usado pelo sistema para assegurar que
os arquivos no sero usados por processos diferentes ao
mesmo tempo.
ofstream outle; outle.open(students.dat); // ....
outle.close();

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
#include <fstream> #include <iostream> using namesexemplo observa o comportamento bsico do fstream:
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
foi escrito pelo usurio outle << data << endl; //coloca
No caso do cheiro (arquivo) joao.doc no existir:
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:
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.
Agora vamos tentar ler o que escrevemos no documento
objeto a de ifstream. d um ponteiro!!
(a) = 0012FE40 (a.fail()) = 0

19.13. LOOPING PELO FICHEIRO (ARQUIVO).


criado.

47
(e-end+o-of+f-le). Esta funo no tem parmetros e
retorna true se o m do arquivo for alcanado e false
caso contrrio. No entanto, esta funo eof() no de
conana com os cheiros (arquivos) texto como o para
os binrios ( que nos cheiros (arquivos) binrios no
existem espaos em branco).

#include <fstream> #include <iostream> using namespace std; int main () { char data[80]; ifstream
inle; inle.open(joao.doc); if (inle.is_open() &&
inle.good()) //vericamos se est tudo bem { inle >>
data; //colocamos os dados abertos no array cout << data
<< 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 (inle.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 namespace std; int main () { char data[80]; ifstream
inle; inle.open(joao.doc); if (inle.is_open() &&
inle.good()) //vericamos se est tudo bem { inle >>
data; //colocamos os dados abertos no array cout << data
<< endl; inle >> data; //colocamos os dados abertos
no array cout << data << endl; inle.close(); } #ifdef
WIN32 system (pause); #endif return 0; }

Refazendo tudo

#include <fstream> #include <iostream> #include


<string> using namespace std; int main () { string
data;
ofstream outle;
outle.open(joao.doc);
if (outle.is_open() && outle.good()) { cout
<< Escrevendo no arquivo << endl; cout <<
"===================" << endl; cout << Informe 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() && inle.good()) { cout << Lendo do arquivo << endl;
inle.getline(data, 80);
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 <<
2. . readFile - ler do cheiro (arquivo) usando o ifsdata << endl; cout << Enter number of students: ";
tream
cin >> data; cin.ignore(); //esta funo membro para
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) {
cout << Arquivo no pode ser aberto para escrita.\n";
(pause); #endif return 0; }
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,


data); while(!inle.fail()) { cout << data << endl;
getline(inle, data); } inle.close(); } #ifdef WIN32
system (pause); #endif return 0; } bool writeFile
(ofstream& le, char* strFile) { le.open(strFile); return
!(le.fail()||!le.is_open()||!le.good()); } bool readFile
(ifstream& ile, char* strFile) { ile.open(strFile);
return !(ile.fail()||!ile.is_open()||!ile.good()); }

19.14 Manipuladores
Os objetos das classes stream podem ser congurados para fornecer e reportar os dados de maneira prformatada. Da mesma maneira que temos a formatao
quando usamos funes de formatao, como printf() e
scanf(), na linguagem C, podemos usar os manipuladores na linguagem C++ para informar os objetos streams
em que formato desejamos receber os dados deles ou fornecer para eles.

<< showbase << endl; cout << Decimal: " << dec
<< intValue << endl; cout << Octal: " << oct <<
intValue << endl; cout << Hexadecimal: " << hex <<
intValue << endl; cout << Desativando showbase " <<
noshowbase << endl; cout << endl; double doubleVal
= 12.345678; cout << Nmeros com ponto utuante
<< endl; cout << Padro: " << doubleVal << endl;
cout << setprecision(10); cout << Preciso de 10: "
<< doubleVal << endl; cout << scientic << Notao
cientca: " << doubleVal << endl; cout << uppercase;
cout << Caixa alta: " << doubleVal << endl; cout
<< endl; bool theBool = true; cout << Booleano <<
endl; cout << Padro: " << theBool << endl; cout
<< boolalpha << BoolAlpha ativo: " << theBool <<
endl; cout << endl; string myName = John"; cout <<
Strings << endl; cout << Padro: " << myName <<
endl; cout << setw(35) << right << Com setw(35) e
\"right\": " << myName << endl; cout.width(20); cout
<< Com width(20): " << myName << endl; cout <<
endl; #ifdef WIN32 system (pause); #endif return 0; }

Abaixo temos uma srie de manipuladores teis:

19.15 Exerccios
19.14.1

Ajustando a largura da entrada/sada

setw(w) - Ajusta a largura da sada e entrada para w;


precisa ser includo.
width(w) - Uma funo membro das classes iostream.

19.14.2

Preenchimento de espaos em
branco

1. Quero colocar num documento, uma lista das combinaes possveis entre a,b,c e d. com a respectiva
ordenao e quantidade;
2. . Quero que seja a pessoa a escolher o nome do cheiro (arquivo) e escrever tambm a localizao;
3. . Quero que seja depois tansformado num sistema
modular;
4. . Encontrar uma maneira para contar o n de espaos
em branco, o n de caracteres ". que quisermos de
um dado documento.

setll(ch) - Preenche os espaos em branco em campos de sada com ch; precisa ser includo.
#include <iostream> #include <fstream> using namespace 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
arquivo. << endl; return 1; } while (object.get(ch))
19.14.3 Ajustando a preciso
{ 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;
cout << Existem " << sentence_count << " sentenas.
programa.
<< 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 caractersticas prprias possibilitadas pela orientao a objetos.

Os caracteres so entendidos como sendo nmeros que


geralmente tm oito bits, esses nmeros so traduzidos
na tabela ASCII de 128 caracteres, como existem inmeras regies no mundo com caractersticas lingusticas
prprias, a tabela ASCII estendida por um bloco de caracteres acima dos 128 mais baixos que varia de acordo
com as necessidades de cada lngua. A parte superior
da tabela ASCII conhecida como parte estendida e
referenciada por pginas de cdigos para cada propsito
lingustico, isso quer dizer que podemos ter os mesmos
nmeros signicando caracteres diferentes para cada regio do mundo.

// listandoCodigoASCII.cpp #include<iostream> using


std::cout; using std::cin; using std::endl; #include<string>
using std::string; using std::getline; int main(){ string
anyWord; cout << Digite uma palavra: "; getline(cin,
anyWord); for ( int i = 0; i < anyWord.length(); i++) cout
<< anyWord[i] << " - " << (int)anyWord[i] << endl;
cout << endl; return 0; } //end main

20.2 Funes de caracteres teis.

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
argumento no ser uma letra, a funo retorna o mesmo
contenha 20 caracteres fazemos:
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 operacionais mais sosticados como o GNU/Linux, que possuem Funes que vericam o caractere. Estas funes recegerenciamento 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 detalhes consulte o livro Programar em C.

20.3 Strings em C++

No estilo C++, como era de se esperar, as strings so objetos, eles podem ser criados facilmente atravs da biblioteca padro referenciada pelo arquivo de cabealho
<string>. As strings so objetos com recursos que permitem manipular os seus caracteres com as funcionalidades

As cadeias de caracteres da linguagem C podem formatar


um novo tipo de dados, porm criar tipos de dados mais
sosticados no possvel nesta linguagem, as strings em
C++ so objetos da classe string, o que isso traz de novo
para o tratamento de textos em programas? A primeira

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


strings em C++
Isto torna possvel, basicamente, criar string de seis ma-

manipular

neiras diferentes:

erase A funo membro erase elimina parte de uma


string. Os parmetros passados para a funo so a posi1. Podemos denir um objeto string vazio, para futuo 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
um texto qualquer << endl; getline( cin, myText );
uma poro de outra string;
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 operar strings em C e C++

6. Podemos criar um objeto string preenchida com


uma quantidade denida de um determinado caracEm C, temos diversas funes que so usadas para matere;
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 operadores, como por exemplo "+", "+=", "<<", etc... Isto rar strings em C e C++, algumas particularidades da lintorna o cdigo um pouco mais intuitivo, vejamos os ope- guagem C++ permitem uma operao mais intuitiva das
strings e algumas novas formas de trat-las. Vejamos
radores:
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:
1. Atribuir o valor de uma string para outra;
2. Acessar caracteres individualmente;
3. Adicionar uma string no nal de outra;
4. Concatenar strings;
5. Enviar uma string a um output stream;
6. Receber uma string do input stream.

20.4.1 Funes uteis para o uso de strings


strlen() (str=string + len=length)- aceita um argumento
que pode ser um array (uma cadeia) de caracteres, um
ponteiro (que aponta para um array de caracteres) ou uma
string literal. retorna um nmero inteiro que representa o
nmero de caracteres, no incluindo o caractere null":
int len; len = strlen(Je) // a extenso 4 char* stinkydog = Dante"; len = strlen(stinkydog); // a extenso
5 char name[80] = Devvie"; len = strlen(name); // a
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 argumenmuito 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++

20.4.2

51

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
pequeno programa como:
target = src;
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
previamente alocadas para a string. Em c++, este prodois argumentos,
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 vestrcpy(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
char str1[80] = Devvie Kent"; char str2[80] = Devvie
endereo.
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
Agora, reitamos no que signica estas operaes: Em
primeiro lugar string no um tipo primitivo de dado,
uma classe, portanto um tipo de dado mais inteligente, uma das caractersticas dos objetos string que
eles so redimensionveis, ou seja, quando atribumos a
uma string um dado maior que seu espao interno de
armazenamento ela aumenta o seu espao interno para
comportar o novo dado. Outra caracterstica que a operao "=" para a string uma operao de atribuio de
contedo, de forma que a string copia a outra quando usamos este operador e no apenas o ponteiro que referncia
o endereo da string.

20.4.3

Unir strings

temos a funo strcmp (string+compare) (tem 2 arguentos. retornar 0 se forem iguais)


char str1[80] = Devvie Kent"; char str2[80] = Devvie
Kent"; if (!strcmp(str1, str2)) cout << The two C-strings
are equal"; else cout << The two C-strings are not equal";
esta comparao pode ser resultar em negativo e positivo
e isso tem a ver com o jogo de caracteres na tabela ascII.
aqui vai um resumo
Resultados de comparaes entre strings
Em C++ podemos comparar duas strings atravs da funo membro da classe string: compare(), existem os seguintes formatos (assinaturas) para a funo:

1 int compare ( const string& str2 ) const; 2 int compare


( const char* szc ) const; 3 int compare ( size_t pos1,
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 contedo 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);
4. Comparar uma C-string apontada por um ponteiro
(szc), com uma seo comeando em (pos1), a qual
contm (n1) caracteres do contedo do objeto a qual
ela pertence;
5. Comparar uma seo do objeto, iniciada em (pos1)
com (n1) caracteres, com uma seo de (str2), iniciada em (pos2) com (n2) caracteres;

Em C++ usamos objetos da classe stringstream (biblioteca sstream.h) para armazenar temporariamente os caracteres, depois usamos o operador ">>" para converter
os caracteres em nmero, bastando para isto criar a varivel no formato que desejamos receber o nmero. Mais
uma vez temos o uso do poliformismo para resoluo
de um problema comum de programao, a operao do
">>" diferente para cada tipo de dado, selecionada automaticamente pelo compilador de acordo com o tipo de
dado da varivel destino.

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 contedo 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, retornando uma referncia de valor de acordo com o cdigo
ASCII.
Se estiver comparando duas strings uma outra opo,
ainda mais natural, utilizar os operadores de comparao < e ==.
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 nmeros em tipo numrico.
atoi (acrnimo para ASCII to integer) recebe um argumento c-string) e retorna o inteiro que a c-string representa. No 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.
Assim como na linguagem C, podemos denir dados
compostos por associaes dos tipos bsicos, estes tipos
so chamados de estruturas (structs). C++ traz uma nova
representao de dados, muito semelhante na forma s estruturas, porm diferentes na forma conceitual: a palavra
chave class, que usada para criar uma classe de objetos
mais rica que as structs. Ao declararmos um identicador, tal qual fazemos ao declarar uma varivel e no lugar
do tipo especiquemos uma classe criaremos um objeto.
Antes de prosseguirmos, vejamos um pouco sobre o conceito por trs do uso de objetos. Um objeto entendido
como uma entidade de dados dentro da memria que,
basicamente, deve ser responsvel por seu contedo, ou
seja, um objeto deve ser capaz de gerenciar seu contedo
autonomamente, ou prover meios de outras entidades de
cdigo faz-lo de forma segura.

21.1.2 Funes membro (Mtodos)

Agora suponha que tenhamos como denir um modo para


entrar e outro para ler dados da matriz:
struct MyData { int n; char data[10]; oat nReal; bool
write_data(int pos, char c) { if (pos >= 0 && pos <
10) { data[pos]=c; return true; } return false; } char
read_data(int pos) { if (pos >= 0 && pos < 10) { return
data[pos]; } return '\0'; } };
Agora temos assegurados mtodos de incluso e acesso a
dados da matriz de caracteres, porm ainda existe um pequeno problema: Quem quiser o antigo mtodo de acesso
direto conseguir facilmente, pois os elementos da estrutura esto acessveis publicamente por padro.

21.1.3 Conceituao
21.1.1

Origem (atributos)

Observemos, por exemplo, o cdigo abaixo:


struct MyData { int n; char data[10]; oat nReal; };
Esta declarao, bem conhecida de quem j est familiarizado com a linguagem C, cria um tipo de dado composto heterogneo, que neste exemplo chamamos de MyData, o que acontece aqui que os dados esto agrupados
dentro desta estrutura, isto promove a possibilidade de
manipul-los em conjunto. Um dos problemas com esta
estrutura a presena de uma matriz de caracteres chamada data, observe que a mesma tem um tamanho denido de 10 caracteres, imagine que em algum momento
da execuo do programa tentamos colocar um caractere
na posio 11, ou qualquer posio fora da matriz, neste
caso estamos colocando o referido dado em endereos
invlidos para a operao que pretendemos realizar, ou
seja, no h controle nenhum que assegure que o cdigo
no far um acesso fora da rea que pertena a matriz.

O problema da visibilidade pblica dos dados em uma estrutura pode ser resolvido com um dos conceitos de objetos, o encapsulamento. Encapsular os dados, signica
reservar o acesso a funes que estejam dentro de um
grupo restrito, especializado para tais operaes de manipulao destes dados. Uma das vantagens deste procedimento que o cdigo adquire um formato mais organizado, onde os processos tornam-se claramente distintos,
caso tenhamos que analisar o cdigo, cada procedimento
estar restrito a partes denidas para cada operao.

21.2 Declarando classes


As estruturas so bem parecidas com as classes, com uma
pequena diferena, peguemos o caso da passagem de estruturas como argumentos de funes:
#include <iostream> #include <string> using namespace std; class Person { string name; int height; };

53

54
void setValues(Person&); void getValues(const Person&); int main () { Person p1; setValues(p1); cout
<< Informando dados sobre a pessoa:\n"; cout <<
"================================\n"; getValues(p1); return 0; } void setValues(Person& pers)
{ cout << Informe o nome da pessoa: "; getline(cin,
pers.name); cout << Informe a altura em milmetros: ";
cin >> pers.height; cin.ignore(); } void getValues(const
Person& pers) { cout << Nome da pessoa: " <<
pers.name << endl; cout << A altura da pessoa em
milmetros : " << pers.height << endl; }

CAPTULO 21. CLASSES


name: " << pers.getName() << endl; cout << Persons
height in milimeters is: " << pers.getHeight() << endl; }
Mas perguntam: Por que que nos demos ao trabalho
de recorrer a membros privados em vez de fazer todos
pblicos? Quando tnhamos uma estrutura no lugar de
uma classe, no havia nada que impedisse a colocao de
valores invlidos, por isso poderamos ter valores vazios
para a string e valores negativos para a varivel height.

Agora que Person uma classe, as funes membro


podem realizar a validao dos dados antes da atribuio de valores nas variveis. Poderamos fazer com que
a funo setName vericasse se a entrada na string se Mudamos o identicador de struct para class
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 neveis membro que so privadas por padro, estas no gativos e caso fossem, colocaria zero, ou no tomaria nenhuma ao.
so vistas por funes fora da classe.

Todas estas caractersticas demonstram o conceito de enDentro 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
bem delimitadas dos programas. Devido a este conceito
As modalidades podem ser:
podemos contar com cdigos mais fceis de analisar e fazer manuteno.
private (s podem ser acessados por membros da
mesma classe)
public (pode ser acessadas fora do objeto, onde este
estiver denido)

21.3 Instanciando objetos

protected (deixemos esta para quando falarmos em Instanciao de objetos o processo de criar a estrutura
lgica dos mesmos na memria. Isto ocorre quando declasses derivadas, pois depende deste conceito).
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
seja, estamos criando uma instncia da classe.
no conseguem acessar as variveis name e height.
Visualizamos melhor em forma de tabela:
A soluo criar funes publicas, para ler de e escrever
para as variveis privadas:
#include <iostream> #include <string> using namespace std; class Person { private: string name;
int height; public: string getName() const; void setName(string); int getHeight() const; void setHeight(int);
}; string Person::getName() const { return name; }
void Person::setName(string s) { if (s.length() ==
0) name = No name assigned"; else name = s; }
int Person::getHeight() const { return height; } void
Person::setHeight(int h) { if (h < 0) height = 0; else
height = h; } void setValues(Person&); void getValues(const Person&); int main () { Person p1;
setValues(p1); cout << Outputting person data\n"; cout
<< "======================\n"; getValues(p1);
return 0; } void setValues(Person& pers) { string str;
int h; cout << Enter persons name: "; getline(cin,str);
pers.setName(str); cout << Enter height in milimeters:
"; cin >> h; cin.ignore(); pers.setHeight(h); } void
getValues(const Person& pers) { cout << Persons

Podemos declarar os objetos logo aps denir a classe


conforme podemos ver no 1 caso logo abaixo. Neste
caso teremos a varivel rect criada como um objeto conforme estabelecido pelo modelo denido pela palavra
chave class. Este tipo de declarao mais usual para
objetos criados globalmente, pois a incluso desta declarao no cabealho pode fazer com que vrios objetos
sejam criados com o mesmo nome quando o cabealho
invocado de vrios arquivos. Portanto, mais prudente
usar esta opo quando a declarao est no arquivo fonte
e no no cabealho.
1 caso:
class CRectangle { int x, y; public: void set_values
(int,int); int area (void); } rect;
No 2 caso, apresentado logo abaixo, podemos declarar
objetos apenas quando precisarmos. Esta opo de declarar o objeto depois a mais usada, pois na maioria das
vezes temos o modelo dos objetos, a classe, declarada
em um arquivo de cabealho enquanto que os objetos sero criados no resto do cdigo fonte. Desta forma mais

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
o escrita do resto do programa.
2 caso:
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
age) { this->age = age; } int Dog::getAge() { return
Em ambos os casos temos
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, fazendo os testes necessrios para assegurar sua consistn- Acima podemos ver um modo de declarar as funes apenas como prottipos, que cam dentro da declarao da
cia e estabilidade. Sempre que precisemos utilizar os objetos 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,
classe. Neste caso teremos as funes denidas e consuma vez que os desenhamos adequadamente.
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 potncia 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 saber 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, seguindose 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 os mtodos (as funes membro)
ticador existe, no formato: ESCOPO::funo ou ESCOPO::dado. De maneira geral, quando declaramos
Vamos acompanhar com um exemplo: Vamos fazer o deidenticadores dentro da classe podemos deni-los no essenho 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 CRectantamos.
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 setGreen(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]; boolean isWithinSize(int s); double clipIntensity(double
E funes grandes podem ser denidas fora da
brightness); };
classe.

21.5 Especicadores de acesso


Temos as palavras reservadas private e public so
os chamados especicadores de acesso.

Neste caso tero de ser identicadas como pertencentes


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

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 (mtodos) especiais de uma classe. Permitem a inicializao
acess-las;
public Especica uma faixa de variveis ou das variveis membro de um objeto. Ou melhor, permifunes 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 espepartes do programa necessrio especicar o ciais chamadas de construtores. At aqui no os declaraobjeto 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 lmembros de uma classe chama-se Encapsulamento. A gica inicial do objeto. Desta forma estas funes so caboa prtica no desenho de classes deve sempre forar o ractersticas da orientao a objetos e servem para criaencapsulamento. raramente necessrio ou desejvel ter o dos mesmos.
acesso livre e pblico aos dados internos de uma classe. Construtores no podem ser chamados explicitamente
como fazemos no caso de funes membro regulares.
O encapsulamento visa, primariamente duas metas:
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 neobjeto foram criados;
cessitemos de alterar cdigo que utilizem objetos da
Inicializam os dados com os valores que o objeto
classe.
precisa para comear a funcionar corretamente.
Ou seja, o encapsulamento simplica a programao escondendo as particulariadades da classe e elimina o retra21.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 caraces da classe.
tersticas que os distinguem das funes membro convenSe nenhum especicador de acesso for usado, todos os cionais. Ou seja, denimos uma funo membro que posmembros e metodos so declarados como privados por sua o mesmo nome da classe, no tenha tipo de retorno e
a declaramos como pblica para que possa ser acessada
padro.

21.8. COPY CONSTRUCTORS


por quem queira instanciar objetos. Vejamos como denir um construtor:
class Caneta { string cor; int volume; /////////////// public:
Caneta( string c, int v ); }; Caneta::Caneta( string c, int v
) { cor = c; volume = v; }
Construtores podem iniciar os membros da classe de uma
forma simplicada. Este formato usado sempre que o
construtor tem dados bsicos que podem ser iniciados antes do resto da construo da estrutura do objeto. Podemos iniciar os dados do objeto declarando-o desta forma:
class Caneta { string cor; int volume; /////////////// public:
Caneta( string c, int v ) : cor(c), volume(v) { } };
Para faz-lo, como vemos no cdigo, basta listar as variveis membro em uma sequncia depois da declarao
do nome do construtor e de um sinal de dois pontos ":".
Iniciamos uma lista de membros, com o valor a ser atribudo entre parnteses depois de cada um, separando-os
por vrgulas.

21.7 Destrutores
21.7.1

Conceito

Alm do construtor a linguagem C++, assim como outras linguagens orientadas a objeto, possuem outro tipo
de funo especialmente criada e gerenciada pela linguagem, os destrutores. Estas so destinadas a desmontar a
estrutura do objeto quando o mesmo est sendo encerrado. O destrutor ter o mesmo nome da classe, mas precedido pelo sinal til ~ e tambm no retorna valor.
O destrutor tem as seguintes caractersticas:

57
O construtor tem o mesmo nome que a classe;
O destrutor tem o mesmo nome que a classe com o
prexo de tilde ~;
O construtor foi usado para inicializar as variveis
membro, mas noutros exemplos poderia alocar memria, tomar controle de recursos como dispositivos
de sistema e executar inicializaes de cdigo;
O destrutor no exemplo no faz nenhuma ao real,
para alm de fazer o eco informando que foi chamado.

21.8 copy constructors


Um copy constructor um construtor especial que toma
como argumento a referncia de um objeto da mesma
classe e cria um novo objeto que a copia do objeto
em referncia. Por padro, o compilador providencia um
copy constructor que faz a cpia membro por membro
do objeto original, construindo um objeto idntico. Isto
chamado de shallow copy ou member wise.
Em algumas situaes a cpia de um objeto no satisfatria, para ver isso vamos ver a classe employee, abaixo:
#include <iostream> #include <string.h> using namespace std; class Employee { public: Employee(char
*name, int id); ~Employee(); char *getName(){return
_name;} private://Other Accessor methods int _id;
char *_name; }; Employee::Employee(char *name, int
id) { _id = id; _name = new char[strlen(name) + 1];
//Allocates an character array object strcpy(_name,
name); } Employee::~Employee() { delete _name; } int
main() { Employee programmer(John,22); cout <<
programmer.getName() << endl; return 0; }

O destrutor chamado quando o objeto est sendo A funo strlen retorna o tamanho da string passada pelo
constructor. Repare que o nome do employee agora
nalizado;
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 terminator 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();


//Destructor void setAge(int age); int getAge(); void
setWeight(int weight); int getWeight(); void speak();
private: int age; int weight; }; Dog::Dog() { age = 0;
weight = 0; cout << Dog Constructor Called << endl;
} Dog::~Dog() { cout << Dog Destructor Called <<
endl; }

int main() { Employee programmer(John,22); cout


<< programmer.getName() << endl; //Lots of code ....
Employee manager(&programmer); //Creates a new
Employee manager, //which is an exact copy of the
//Employee programmer. return 0; }

Repare que:

Este programa contm um bug srio e morre com uma


exceo quando executado. O problema que o construtor que est sendo usado para criar um objeto ma-

58
nager, mas ele copia o endereo no ponteiro _name em
manager.
Nos temos 2 pointers ambos contendo o mesmo endereo. Imagine que agora um novo empregado contratado. quando o nome for atualizado, no apenas iremos
alterar o nome do empregado mas tambm do gerente.
Finalmente, quando os objetos deixarem de ser usados e
o destrutor da classe zer a liberao de espao na memria 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 construtor de cpia (copy constructor) na classe, substituindo
a implementao padro do compilador. Este recurso
automaticamente identicado e faz com que o compilador no crie a sua verso do construtor. Assim, denir
um construtor de cpia prprio a maneira mais eciente 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 cadeia de caracteres para copiar o contedo da original no
objeto a ser copiado e copiamos o contedo para o novo
objeto. Assim, teremos objetos distintos, cada um com
seu prprio contedo.

21.9 Ver tambm


Programao orientada a objetos/Classes e Objetos
- conceitos tericos

CAPTULO 21. CLASSES

Captulo 22

Encapsulamento
22.1 Conceito

para no dependermos de conceitos de herana que tambm 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 encapsupor 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 derncias 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 denirlimitadas e criar meios de criar mdulos onde cada classe mos para a nova.
faa bem aquilo de que est encarregada, tendo total conVejamos 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

Classes podem proteger sua estrutura de acessos de outras entidades de dados que no pertencem a seu corpo.
Para isto, em C++ temos atributos de acesso para blocos
de dados ou funes membros de classes. Em algumas
linguagens os atributos so denidos para cada membro
individualmente.

A segunda classe declarada possui a extenso ": public


veiculo" a mais, esta parte refere-se a uma declarao de
parentesco. De fato, ao declarar a classe desta forma estamos informando ao compilador que a classe veiculo
me da classe carro. Semanticamente, isto signica que
a classe carro possui toda a estrutura da classe veiculo
alm de seus prprios membros.

Os atributos de restrio de acesso em C++ so trs: private, public e protected. Cada atributo oferece um nvel
de ocultao para membros de classes. Eles so usados 22.2.2 Denindo acessos
para assegurar que apenas grupos identicados de cdigo
Considerando o exemplo anterior, podemos observar que
tenham acesso a partes presselecionadas da classe.
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
seja, os membros que no tenham denidos os seus atriclasse poder acessar membros privados (private).
butos de acesso explicitamente, sero denidos como privados. Este comportamento revela a necessidade de res22.2.1 Classes derivadas (pequena intro- guardar os membros de uma classe atravs de atributos de
restries. Em C++, ao denir membros em uma classe
duo)
antes da denio de qualquer atributo de restrio estaPrecisamos 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, poarmos dependncias circulares entre os tpicos, ou seja, demos denir atributos de restries para grupos de
59

60
membros e modicar o comportamento padro da classe.
Se denirmos public, os dados estaro acessveis a qualquer parte do programa, o que equivalente a coloca-los
em uma estrutura com a palavra struct ao invs de dentro de uma classe. Se 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 restringimos as cores a um conjunto que desejamos. Observe
que ao tentar atribuir qualquer cor diferente de vermelho, azul e prata, receberemos um retorno "false".
Assim, temos a possibilidade de controlar o comportamento do objeto criado atravs da restrio imposta.
O atributo combustvel ser manipulado livremente
pela classe veculo e pela classe carro, visto que o
atributo protected d visibilidade s classes derivadas de
veiculo. O mesmo mecanismo de controle visto no pargrafo anterior poder ser implementado para acessos
fora do escopo das duas classes, ou seja, para funes no
escopo global ou em outras classes.

22.3 Escopos globais


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

CAPTULO 22. ENCAPSULAMENTO

Captulo 23

Herana
23.1 Conceito

23.2 Sintaxe
Para declarar uma classe derivada de outra j existente,
procedemos de forma a declarar o parentesco e o grau de
visibilidade (acesso) que a classe derivada ter dos membros de sua classe base. Para isso seguimos o seguinte
cdigo sinttico:

Herana um dos pontos chave de programao orientada a objetos (POO). Ela fornece meios de promover a
extensibilidade do cdigo, a reutilizao e uma maior coerncia lgica no modelo de implementao. Estas caractersticas nos possibilitam diversas vantagens, 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 frequncia.
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 parendas 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 pudssemos 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
caminhao : public veiculo_rodoviario // Dene um
ticular, declarando-se o parentesco neste instante.
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 automopor 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);


t1.mostrar(); cout << "\n"; t2.mostrar(); cout <<
"\n"; c.set_rodas(4); c.set_pass(6); c.set_tipo(van);
c.mostrar(); #ifdef WIN32 system (pause); #endif
return 0; }

forma as informaes esto presentes,


mas s podem ser acessadas atravs de
funes publicas ou protegidas da classe
base.

Na implementao acima temos a classe base veiculo_rodoviario e duas classes derivadas : caminhao e
automovel. Podemos notar que as caractersticas comuns
a todos os tipos de veculos, rodas e passageiros, esto na
classe base, enquanto as caractersticas exclusivas de cada
tipo de veculo esto nas classes derivadas. Desta forma
podemos denir procedimentos especializados para cada
classe, fazendo com que todas as eventuais modicaes
feitas ao longo da implementao na classe base sejam
estendidas a todos os objetos criados a partir das classes
derivadas no programa.
Repare ainda um pormenor: tanto a classe caminhao
quanto a automovel tm como funo membro o mtodo
mostrar(), mas uma no interfere com a outra. Isto ilustra um outro aspecto da orientao a objeto, o polimorsmo. Este ser exposto em mais detalhe nos captulos
subsequentes.

Se tivermos membros protegidos (protected) na classe derivada, eles se comportam como se tivessem sido copiados para
a classe derivada como protegidos (protected).
Classe base herdada como private:

O acesso dos membros da classe base classe derivada


determinado pelo especicador de acesso: public, private e protected. Por defaut (padro) temos o private,
ou seja, como temos a opo de no explicitar o especicador de acesso, se este no estiver presente o compilador
usar private durante a interpretao do cdigo.
Assim camos com as possveis combinaes

Membros privados (private) da classe base:


Os membros esto presentes na classe,
porm ocultos como privados. Desta

Membros protegidos (protected) da classe


base:
Os membros se comportam como se tivessem sido copiados como privados (private) na classe derivada.

Classe base herdada como Protected:

Membros pblicos (public) da clase base:


Se comportam como se tivssemos
copiado-os como protegidos (protected)
na classe derivada

Membros privados (private) da classe base:


Os membros esto presentes na classe,
porm ocultos como privados. Desta
forma as informaes esto presentes,
mas no podero ser acessadas, a no ser
por funes da classe base que se utilizem
delas.

Membros pblicos (public) da classe base:


como se copissemos os membros da
classe base e os colocssemos como public na classe derivada. No nal, eles
permanecem como pblicos.

Membros privados (private) da classe base:


Os membros esto presentes na classe,
porm ocultos como privados. Desta
forma as informaes esto presentes,
mas no podero ser acessadas, a no ser
por funes da classe base que se utilizem
delas.

Classe base herdada como public:

Membros pblicos (public) da classe base:


Os membros se comportam como se tivessem sido copiados como privados (private) na classe derivada.

23.3 Controle de acesso classe


base
Quando uma classe herda outra, os membros da classe
base so incorporados como membros da classe derivada.
Devido separao das classes e do controle de acesso s
variveis em cada classe, devemos pensar como as restries de acesso so gerenciadas em classes diferentes,
principalmente o acesso a membros da classe base a partir das classes derivadas.

Membros protegidos (protected) da classe


base:

Membros protegidos (protected) da classe


base:
Se comportam como se estivssemos
copiado-os como protegidos (protected)
na classe derivada.

23.5. CONSTRUTORES E DESTRUTORES


Em suma, estas regras podem ser sintetizadas em uma
regra muito simples: Prevalece o atributo mais restritivo.
Para isto basta-nos listar os atributos por ordem de restries decrescente:
1. private
2. protected

63
x; public: void showx() { cout << x << "\n"; } }; class
base2 { protected: int y; public: void showy() { cout <<
y << "\n"; } }; class derived: public base1, public base2
// Inherit multiple base classes. { public: void set(int i,
int j) { x = i; y = j; } }; int main() { derived ob; ob.set(10,
20); // Disponvel pela classe derived ob.showx(); //
Pela classe base1 ob.showy(); // Pela classe base2 #ifndef
WIN32 system (pause); #endif return 0; }

3. public
Assim, temos todas as combinaes denidas quando colocamos um atributo combinado com o outro, bastando
para isto escolher sempre o mais restritivo na combinao. Por exemplo: Quando temos uma varivel pblica
na base e a herana privada, a combinao resulta em
uma varivel privada na classe derivada.

Repare que utilizamos o operador vrgula para dizer ao


compilador que a classe derivada herda mais de uma
classe. Com efeito, temos uma lista de classes separadas
por vrgulas depois do operador ":" (dois pontos).

Quando queremos que a classe derivada herde uma classe


como pblica e outra como privada ou protegida basta
preceder a classe com o seu 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 pauso de membro da classe derivada #ifdef WIN32 system rentesco conforme mostramos nas sees anteriores. Em
termos genricos, classes que herdam caractersticas de
(pause); #endif return 0; }
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 instancivoid show() { cout << i << " " << j << "\n"; } }; class
ado, o construtor da classe base chamado priderived : 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.

23.4 Heranas mltiplas


Podemos ter a situao em que uma classe derivada possa
herdar membros de vrias classes base. Esta caracterstica uma distino entre C++ e outras linguagens orientadas a objeto. Este recurso d mais poder de modelagem
ao programador, mas vale a pena lembrar que mais poder
exige mais cautela no uso.
// Um exemplo de mltiplas classes base. #include <iostream> using namespace std; class base1 { protected: int

No caso em que termos herana sequencial A-B-C, teremos:


#include <iostream> using namespace std; class base {
public: base() { cout << Construindo base << endl; }
~base() { cout << Destruindo base << endl; } }; class
derivada1 : public base { public: derivada1() { cout
<< Construindo derivada1 << endl; } ~derivada1()
{ cout << Destruindo derivada1 << endl; } }; class
derivada2: public derivada1 { public: derivada2() { cout
<< Construindo derivada2\n"; } ~derivada2() { cout <<
Destruindo derivada2\n"; } }; int main() { derivada2
ob; // constri e destri o objeto ob #ifdef WIN32

64

CAPTULO 23. HERANA

system (pause); #endif return 0; }

derivada(int x, int y): base(y) { j = x; cout << Construindo derivada\n"; }// derivada usa x; y passada em
lista para a base. ~derivada() { cout << Destruindo deriCaso de mltipla herana A - B e C
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 decladerivada: 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:
Neste caso a sequncia de inicializao segue ordem estabelecida na lista de herana. Mais explicitamente, temos
a construo das bases: base2 e base1, nesta ordem
respectivamente e depois a derivada. O que, automaticamente, nos revela a sequncia de destruio na ordem
inversa, ou seja: destroi-se a derivada, depois base1
e, nalmente, a estrutura da base2.

23.6 Passando parmetros para


construtores da classe base

#include <iostream> using namespace std; class base1


{ protected: int i; public: base1(int x) { i = x; cout
<< Construindo base1\n"; } ~base1() { cout << Destruindo base1\n"; } }; class base2 { protected: int k;
public: base2(int x) { k = x; cout << Construindo
base2\n"; } ~base2() { cout << Destruindo base2\n";
} }; class derivada: public base1, public base2 { int j;
public: derivada(int x, int y, int z): base1(y), base2(z) {
j = x; cout << Construindo derivada\n"; } ~derivada() {
cout << Destruindo derivada\n"; } void mostrar() { cout
<< i << " " << j << " " << k << "\n"; } }; int main() {
derivada ob(3, 4, 5); ob.mostrar(); // mostra 4 3 5 #ifdef
WIN32 system (pause); #endif return 0; }

Agora imaginemos que temos um conjunto de bases para


uma classe que queiramos derivar, ento podemos ter um
23.7 Superposio de funes
construtor em cada base que precise de parmetros para
que possa ser invocado pela nossa classe. Como poderemos passar os parmetros, uma vez que os mesmos s Muitas vezes temos classes derivadas que executam uma
determinada ao de forma distinta da mesma ao depodem ser passados durante a inicializao da classe?
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 dilores 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 objecorpo 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 exemClasse_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 condiBase2(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 manuConstruindo base\n"; } ~base() { cout << Destruindo ais de compiladores). Com este recurso podemos declabase\n"; } }; class derivada: public base { int j; public: rar em uma classe derivada uma funo com nome e pa-

23.9. VER TAMBM


rmetros idnticos a uma existente em uma classe base,
porm com contedo diferente.
Vejamos o exemplo de cdigo e teremos uma noo mais
concreta do que foi explanado:
#include <iostream> using namespace std; class animal {
public: void comer(); void mover(); void dormir() { cout
<< Dormindo... << endl; } }; ... ... class ave : public
animal { public: void comer(){ cout << Bicando... <<
endl; } void mover(){ cout << Voando... << endl; } };
... ... class peixe : public animal { public: void comer(){
cout << Mordendo... << endl; } void mover(){ cout <<
Nadando... << endl; } }; int main() { ave passarinho;
peixe sardinha; passarinho.mover(); sardinha.mover();
#ifdef WIN32 system(pause); #endif return 0; }
Ao executar o programa gerado por este cdigo percebemos que a mesma funo: mover(), ter comportamento
diferente quando invocada por objetos de classes diferentes. O programa mostrar a mensagem Nadando... para
a funo invocada pelo objeto sardinha e Voando...
para a invocada pelo objeto passarinho. Aqui, o mecanismo bem simples de se entender, quando cada objeto
tem uma verso diferente para a mesma funo fcil
para o compilador relacionar o objeto classe que ele
pertence e invocar a funo apropriada.

23.8 Acessando funes superpostas da classe base


O mecanismo para obter acesso s classes base a partir da
classe derivada intuitivo. Para isto usamos o operador
de resoluo de escopo, composto por um par de dois
pontos "::", usando a seguinte sintaxe:
<CLASSE>::<FUNO>(lista_de_parmetros);
Ou seja, basta invocar a funo informando qual a verso 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; }

65

23.9 Ver tambm


Programao orientada a objetos/Herana - conceito

Captulo 24

Polimorsmo
24.1 Conceito

24.5 Construtor de cpia virtual

Polimorsmo em linguagens orientadas a objeto, a capacidade 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 deriso 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 precout << 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 manualno-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


<< ob.derived1::i << " "; // tambm resolvido aqui. cout
<< ob.j << " " << ob.k << " "; cout << ob.sum; #ifdef
WIN32 system (pause); #endif return 0; }
2. A segunda maneira atravs de classes bases virtuais:
Quando temos 2 ou mais objetos que so derivados da
mesma base class, podemos prevenir mltiplas cpias da
base class declarando a base class como virtual quando
ela herdada. 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.

67

Captulo 25

Friend
25.1 Friend functions
O uso de funes amigas deve ser evitado sempre que
possvel, pois diminui a identidade da orientao a obje25.2 O que
tos. Isto ocorre porque o uso desse mecanismo representa
uma quebra no encapsulamento. Quando passamos a perFriend 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 tornConsiderando que o acesso a membros pode ser restrito
para determinadas partes do cdigo, podemos adotar uma
postura mais exvel para funes que conhecemos como
conveis e evitar os inconvenientes da restrio a membros por cdigos que no provoquem problemas maiores
a nossa estrutura da aplicao.

las muito bem restritas as funes que devem executar.


muito importante observar se estas funes alteram dados
dentro dos objetos que no podem ser modicados. Se as
devidas precaues forem tomadas no haver problemas
no uso de funes friend.

25.4 Friend classes

25.3 Declarar funes friend


O processo para fazer com que funes fora do escopo
da classe tenham acesso a membros sem nenhuma restrio muito simples. Para isto apenas temos de colocar
o prottipo da funo externa dentro da classe precedido
da palavra friend. Desta forma o compilador passa a ignorar os atributos de restrio de acesso da classe quando
a funo acessa membros da mesma.
Vamos ao exemplo:
// friend functions #include <iostream> using namespace
std; class CRectangle { int width, height; public: void
set_values (int, int); int area () {return (width * height);}
friend CRectangle duplicate (CRectangle); }; void
CRectangle::set_values (int a, int b) { width = a; height
= b; } CRectangle duplicate (CRectangle rectparam) {
CRectangle rectres; rectres.width = rectparam.width*2;
rectres.height = rectparam.height*2; return (rectres);
} int main () { CRectangle rect, rectb; rect.set_values
(2,3); rectb = duplicate (rect); cout << rectb.area();
system (pause); return 0; }

Da mesma forma que podemos declarar funes como


amigas de uma determinada classe, podemos declarar outra classe como sua amiga. Este artifcio faz com que
os membros da classe onde foi feita a declarao sejam
acessveis declarada. Assim, a segunda classe passa a
ter possibilidade de manipulao livre dos membros da
outra.
Apesar da funcionalidade ser um pouco semelhante
que temos no uso das funes, quando declaramos uma
classe como friend dentro de outra, teremos todas as
funes da primeira com poderes de acesso aos membros
da segunda. Esta caracterstica requer cuidado redobrado
quando operaes da classe friend interferem no contedo da outra.
// friend class #include <iostream> using namespace
std; class CSquare; class CRectangle { int width, height;
public: int area () {return (width * height);} void convert
(CSquare a); //consigo acessar porque friend }; class
CSquare { private: int side; public: void set_side (int
a) {side=a;} friend class CRectangle; //declaro friend

68

25.4. FRIEND CLASSES


class }; void CRectangle::convert (CSquare a) { width
= a.side; height = a.side; } int main () { CSquare sqr;
CRectangle rect; sqr.set_side(4); rect.convert(sqr); cout
<< rect.area(); system (pause); return 0; }
Nota:
No h a propriedade de reciprocidade (ou reverso). O facto de uma funo ou classe ser friend
de uma classe no implica o contrrio, ou seja, A ter
B como friend no implica que B a tenha em mesma
conta.
Outra propriedade que no h transitividade. Se
numa class A for declarado que a class B friend. E
depois que na classe B estiver declarado que a classe
C friend de B,Isto no implica que A seja friend
de C.

69

Captulo 26

Classes internas
26.1 Conceituao
As classes podem ser construdas uma dentro da outra
para uma melhor organizao do cdigo. Esta possibilidade nos leva a implicaes a serem consideradas durante
a fase de implementao do cdigo. Devemos vericar as
particularidades de acesso a dados, o que nos leva a diversas particularidades devido ao escopo das mesmas.
No exemplo a seguir, temos a implementao bsica de
uma classe interna a outra:
class data { int n; char str[256]; public: class idata { int
x; int y; int z; }; int getn(); char *getstr(); void setstr(
const char *instr); void setn(int inn); };
Uma vez que criamos o prottipo de objeto dentro de outra classe podemos us-lo atravs do operador de resoluo de escopo. Deveremos nos referir ao operador para
acessar o corpo da primeira classe e depois o invocamos
novamente para alcanar a outra. Desta forma, poderamos us-la como exemplicado abaixo:
data::idata ni;
importante notar que objetos diferentes tero dados diferentes na regio da classe interna, isso impede que usemos dados da classe mais externa dentro das classes internas. Devido a esta caracterstica as funes dentro da
classe interna no podem acessar dados da classe mais
externa, a menos que sejam estticos, o que no exige
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 presentes na linguagem C. Estes tm funes padronizadas e
comportamentos semelhantes a seus parentes diretos em
C. Esta caracterstica a traz compatibilidade que um requisito fundamental e adiciona uma nova funcionalidade
chamada sobrecarga de operadores.

ponto p1(1,5), p2(3,4), Soma; Soma = p1 + p2;

Ao tentar compilar este trecho de cdigo o compilador


retornar um erro por no conhecer a maneira de como
operar este tipo de dado. Como criamos o tipo de dado,
precisamos denir como fazer a soma do mesmo. PodeQuando 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 simbologia.
A sintaxe desta denio, muitas vezes causa confuso,
Ao denir novas funes para os operadores padro, na
mas poder ser facilmente entendida depois que tenhaverdade no substituimos a sua funo, apenas adicionamos 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? Obserum pouco fora do comum, mas apenas reete o comporvando 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 imediatamente antes do operador. Esta a primeira coisa a ter
mesmo operador.
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 ope27.2 Denindo novas operaes
rar.
Podemos visualizar isto melhor, da seguinte forma:
Digamos que temos uma classe chamada ponto, que dene dois inteiros para um plano hipoteticamente denido.
Este par de inteiros poder representar uma coordenada
neste plano formado por pontos espaados um do outro.
Sob estas condies, cada objeto desta classe ser uma
coordenada neste plano:

P3 = P1 + P2;
Que pode ser entendido como a invocao da funo:
P3 = P1.operator+( P2);

Agora podemos entender como acontece a invocao da


funo que 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 esconde 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 memria

que vamos alocar memria para o array na altura da compilao, e o compilador necessita de saber exatamente a
quantidade de memria que deve reservar porm se a
varivel o size declarator, o compilador no sabe quanta
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 exeReformulando o exemplo anterior agora com dados dincuo 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 utilizacin >> 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 responder 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 situapara 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 coloclimite 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 anteriores, onde queramos fazer com que o utilizador dissesse
quantos elementos do array que se deveria utilizar. J
dissemos antes que o declarador do n de elementos do
array tem de ser ou uma constante ou um literal, mas no
pode ser uma varivel. Isso d erro. Aqui vai o exemplo
desse erro:
#include <iostream> using namespace std; int main
() { int numTests; cout << digite o numero de testes
: "; cin >> numTests; int testScore[numTests]; return 0; }

Temos termo NEW. Que um operador cuja funo


alocar dinamicamente memria
Temos o tipo da varivel alocada dinamicamente
Repare que NO temos o nome do array
Uma vez que o array ca sem nome para nos referirmos a cada elemento do array teremos de usar o
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


int *IDpt = new int; *IDpt = 5;
ou

73

E agora no conseguimos apagar esse objeto por que ele


no tem nome e a nica maneira que tnhamos para saber onde ele estava era atravs do ponteiro que terminou
quando termina a funo pois ele local.

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


28.4 Retornando um ponteiro para
Leak
uma varivel local
O tempo de vida de uma varivel criada dinamicamente
o tempo de execuo do programa. Se um ponteiro
aponta para uma varivel dinmica e ca out of scope, j
no conseguiremos acessar essa memria criada dinamicamente. Fica indisponvel. A isso se chama Memory
Leak

#include <iostream> using namespace std; char *


setName(); int main (void) { char* str = setName();
//ponteiros para a funo cout << str; //imprimo o valor
do ponteiros? return 0; } char* setName (void) { char
name[80]; cout << Enter your name: "; cin.getline
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 estarem 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 reuma Varivel Local Esttica
servada dinamicamente.
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, terPergunta: 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);
.... .... //No delete } int main() { while (some condition
exists) // Pseudo-code { myfunction(); } exit 0; }
quando a funo myfunction chamada a varivel av
criada no stack e quando a funo acaba a varivel
retirada do stack. O mesmo acontece com o ponteiro pt,
ele uma varivel local. ou seja quando a funo acaba o
ponteiro tambm termina e retirado do stack. Porm o
objeto alocado dinamicamente ainda existe.

28.6 Retornando um Ponteiro a


uma Varivel Criada Dinamicamente
Outra alternativa, talvez melhor
#include <iostream> using namespace std; char *
setName(); int main (void) { char* str= setName(); cout
<< str; delete [] str; //fao o delete para evitar o memory
leak return 0; } char* setName (void) { char* name =

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 diyour 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 continame 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 exception 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)
Ora o que zemos antes com variveis, vamos ter de fazer
com arrays.

28.9 Vericar a existncia de memria 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 doualocao 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 Uma so as excees (este o mtodo defaut)
mos mensalmente. */
Notar a diferena:

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


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)
a melhor maneira para alocar um array dinamicamente
usar o loop

nothrow, aqui no caso de no se conseguir a memria retorna um ponteiro nulo, e o programa continua.

int *bu = new int[1024]; for (i = 0; i < 1024; i++) bobby = new (nothrow) int [5];
{ *bu = 52; //Assimila o valor 52 para cada elemento 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
delete[] pt; delete[] myBills;

28.8 Dangling Pointers


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;

// rememb-o-matic #include <iostream> using namespace std; int main () { int i,n,* p; cout << How many
numbers would you like to type? "; cin >> i; p= new
(nothrow) int[i]; //crimos I variaveis na execuo if (p
== 0) cout << Error: memory could not be allocated";
else { for (n=0; n<i; n++) { cout << Enter number: ";
cin >> p[n]; } cout << You have entered: "; for (n=0;
n<i; n++) cout << p[n] << ", "; delete[] p; } return 0; }

Captulo 29

Excees
Uma exception um erro que ocorre em tempo de execuo. Podemos lidar com estes erros e criar rotinas para
muitos deles, o que nos permite automatizar muitos erros
que antes teriam de ser emendados mo.

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 evitar colises. Por exemplo eu poderia criar uma funo
com um determinado nome e depois vir a saber que esse
mesmo nome existia na biblioteca. E isto pode ocorrer
bem freqentemente quando temos vrios programadores
contribuindo para o mesmo projeto e ainda mais quando
se recorre a bibliotecas para usar cdigo criado por outros.
O que o namespace permite continuar a termos o
mesmo nome mas ir fazer a diferenciao pela deteco
do contexto de aplicao para cada nome.

76

Captulo 31

Templates
Os templates permitem a criao de cdigo reusado,
usando templates possvel criar funes e classes genricas. Assim o tipo de dados usados pelas funes so
parmetros. Podemos criar um template para soma, e depois enviamos que tipo de dados queremos somar, podemos at utilizar a sobrecarga de operadores para tal m.

tiating.

31.1 Funes genricas

O que se torna bem parecido com o modelo utilizado anteriormente.

h quem prera ter a declarao do template da seguinte


forma
template <class X> void swapargs(X &a, X &b)// This
is a function template. { X temp; temp = a; a = b; b =
temp; }

Uma funo com dois tipos genricos:


template <class Ttype> ret-type func-name(parameter
#include <iostream> using namespace std; template
list) { // body of function }
<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 swaRepare 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
explicitax, y: " << x << ' ' << y << '\n'; cout << Original a, b: " 31.2 Sobrecarregando
<< 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 aucout << 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 funo swapargs(). portanto os templates no so bem funes que funcionam para as vrios tipos, mas antes os
templates permitem poupar escrita ao programador para
no ter de 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 instan77

Captulo 32

Containers
list
set
unordered_set
map
unordered_map

78

Captulo 33

Compilao
Compilao o processo de traduo do programa escrito em uma linguagem de programao para um formato no qual o computador entenda. A compilao gera
um cheiro - arquivo em portugus brasileiro - binrio
(executvel) a partir do cdigo fonte.

33.1 A traduo do cdigo para o


computador

guardadas num arquivo a parte, chamado de object le


e tem a extenso .o ou .obj dependendo do compilador.
Existem diferentes compiladores para diferentes linguagens de programao. Essa traduo feita se o cdigo
estiver na linguagem que o compilador compilar. Existem regras de escrita e de gramtica. No caso de existir
um erro de sintaxe, ento dar um erro de compilao.

33.4 Linker

Em C e C++ so 3 os programas usados para fazer a traduo do cdigo fonte (que so as linhas de cdigo que Apesar do nosso object le ter as instrues em lino programador escreve) num cheiro executvel, que o guagem mquina, o computador ainda no poder correr
como um programa. A razo que necessrio outro
computador pode executar:
cdigo da biblioteca, que o cdigo do run-time library,
que para as operaes comuns tipo a traduo o input
1. Preprocessor - pr-processador
do teclado ou a capacidade para interagir com hardware
2. Compiler - compilador
externo tipo o monitor para apresentar uma mensagem.
Estas bibliotecas run-time costumam j estar instaladas
3. Linker
com o sistema operacional, caso isso no acontea teremos 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 nalEste 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 prprocessador sabe que aquela instruo dirigida para ele.
33.5 Processo de compilao
No exemplo tnhamos:
#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 decheiro, que uma quantidade de memria no computapois 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 escreveEssencialmente, o pr-processador um processador de mos de, cdigo fonte ou source code (pode ter a termimacros para uma linguagem de alto nvel.[1]
nao .c, .cpp, e .cc - estas extenses dependem do
compilador que se utiliza). Esse source code de alguma forma crptica e para algum que no saiba de c++
no entanto aquilo que neste momento chamamos de hu33.3 Compilador
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
no temos um programa executvel. Para isso vamos utilizar o linker. Uma das vantagens do c++ que usufrui de
uma estrutura multi-le. A linguagem permite compilao 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 compramos).
Depois de se fazer este linking que obtemos o arquivo
executvel. No Windows, ele tem terminao .exe. Assim, o sistema operacional reconhece o programa como
independente.
Os compiladores atuais incluem tambm prcompiladores, (ou pr-processadores) (antes eram
software independente, extra), estes pr-compiladores
vo fazer alteraes ao cdigo fonte, que basicamente
consistem em eliminar pedaos de cdigo que escrevemos, e/ou substituir pedaos de cdigo que escrevemos
por outro (copy-paste), 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 33. COMPILAO

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 precedidos 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 escrito em c++). Nenhum dos 2 programas mostra a tabela inteira. O programa mostra alguns caracteres que o
programa 2 no mostra. De modo geral, faltam alguns
caracteres.

36.1 Programa 1
#include <stdio.h> #include <iostream> using namespace std; int main() { //CARACTER " " (ENTER)
= DECIMAL 10 HEXADECIMAL A; int s = 127;
cout<<" CARAC DEC HEX\n\n"; for ( char i =
127; i<127; i++ ) { 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.
C++11, anteriormente conhecido por C++0x o novo padro para a linguagem de programao C++. Ele substitui o antigo padro do C++, o ISO/IEC 14882, que foi publicado em 1998 e atualizado em 2003. Estes predecessores foram informalmente chamados C++98 e C++03. O
novo padro incluir muitas adies ao ncleo da linguagem (sua implementao principal), e estender a biblioteca padro do C++, incluindo a maior parte da biblioteca
do chamado C++ Technical Report 1 um documento
que prope mudanas ao C++ com exceo das funes matemticas 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 comit decidiu focar seus esforos nas solues introduzidas 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 denies. Tal processo inevitavelmente culmina em problemas de compatibilidade com cdigo pr-existente, o que
ocasionalmente aconteceu durante o processo de desenvolvimento do C++. Entretanto, de acordo com o anncio feito por Bjarne Stroustrup inventor da linguagem
C++ e membro do comit o novo padro ser quase
completamente compatvel com o padro atual.3
Novas classes:
std::array
std::tuple
std::foward_list
std::unordered_set
std::unordered_multiset
std::unordered_map
std::unordered_multimap
84

Regular expressions library: http://en.cppreference.


com/w/cpp/regex
Atomic operations library: http://en.cppreference.
com/w/cpp/atomic
Thread support library:
com/w/cpp/thread

http://en.cppreference.

37.1. FONTES, CONTRIBUIDORES E LICENAS DE TEXTO E IMAGEM

85

37.1 Fontes, contribuidores e licenas de texto e imagem


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=292027 Contribuidores: Marcos Antnio Nunes de Moura, Jorge Morais, Albmont, He7d3r.bot, Jonathan Queiroz, Codeks, Abacaxi, Kleberlyra e Annimo:
3
Programar em C++/Vetores Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Vetores?oldid=437250 Contribuidores:
Marcos Antnio Nunes de Moura, Daveiro, Jorge Morais, Edudobay, Marcelo-Silva, Wbrito, Master, Raylton P. Sousa, He7d3r.bot, Abacaxi e Annimo: 8
Programar em C++/Estruturas Fonte: https://pt.wikibooks.org/wiki/Programar_em_C%2B%2B/Estruturas?oldid=276333 Contribuidores: 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 Contribuidores: 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, Abacaxi, 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 Contribuidores: 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 Contribuidores: 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 Contribuidores: 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 Contribuidores: 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 Contribuidores: 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 Contribuidores: 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 Contribuidores: 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 Contribuidores: 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