Você está na página 1de 211

Universidade Catlica de Pelotas Centro Politcnico Cincia da Computao

C++ for Linux


por
Prof. Dr. Paulo Roberto Gomes Luzzardi luzzardi@atlas.ucpel.tche.br pluzzardi@gmail.com Home Page: http://infovis.ucpel.tche.br/luzzardi http://graphs.ucpel.tche.br/luzzardi

Verso: 2.08

Referncias Bibliogrficas
Stroustrup, Bjarne. The C++ Programming Language. Third Edition and Special Edition. Addison-Wesley, 2000. Reissig, Noriel Chang. Programao Orientada a Objetos em C++. Material de estudo, UCPel, 1994.

Pelotas, 29 de maio de 2008

Sumrio
1. Introduo 1.1 Origens 1.2 Conceitos bsicos 1.2.1 Objetos, mensagens, classes, instncias e mtodos 1.2.2 Abstrao 1.2.3 Encapsulamento 1.2.4 Polimorfismo 1.2.5 Herana 1.2.6 C++ versus C 1.2.7 Tipos de dados em C++ 1.3 Estilo de programao em C++ 1.4 Classes em C++ 1.5 Sobrecarga de funes 1.6 Herana simples 1.7 Construtores e destrutores 1.8 Palavras reservadas em C++ 1.9 Forma geral de um programa em C++ 1.10 Classe string 1.11 Exemplos de programas em C++ 2. Classes e Objetos 2.1 Classes 2.2 Funes friend 2.3 Funes inline 2.4 Definindo funes inline dentro de uma classe 2.5 Construtores parametrizados 2.6 Quando construtores e destrutores so executados 2.7 Operador resoluo de escopo 2.8 Passando objetos para funes 2.9 Retornando objetos 2.10 Atribuio de objetos 3. Array, Ponteiros e Referncias 3.1 Array de objetos 3.2 Ponteiros de objetos 3.3 O ponteiro this 3.4 Referncias 3.4.1 Parmetros referenciados 3.4.2 Passando referncias a objetos 3.4.3 Retornando referncias 3.5 Operadores C++ para alocao dinmica 3.5.1 Alocando objetos 3.5.2 Alocao de memria

4. Sobrecarga de Operadores e Funes 4.1 Sobrecarga de operadores 4.2 Criando uma funo-operador membro 4.3 Sobrecarga de operadores utilizando uma funo friend 5. Herana 5.1 Controle de acesso em classes base 5.2 Herana e membros protegidos 5.3 Herana mltipla de classes base 5.4 Passando parmetros para os construtores das classes base 5.5 Garantindo acesso 5.6 Classes base virtuais 6. Funes Virtuais e Polimorfismo 6.1 Funes virtuais 6.2 Funes virtuais puras 6.3 Classes abstratas 6.4 Usando funes virtuais 7. Utilizao Bsica do Sistema de I/O do C++ 7.1 Fluxos do C++ 7.2 Classes bsicas dos streams 7.3 Streams pr-definidos do C++ 7.4 Entrada e sada formatada 7.5 Formatando utilizando os membros de entrada e sada 7.6 Setando flags de formato 7.7 Formatando usando manipuladores 8. Tratamento de Excees 9. Jogo escrito em C++ 10. Classes pr-definidas do C++ 10.1 Classe <string> 10.2 Classe <vector> 11. Tabela ASCII 12. Glossrio 13. Arquivos em C++ 14. Programas em C++ 15. Outros conceitos em C++ 15.1 Mtodos const 15.2 Mtodos static 15.3 Referncias para Ponteiros 15.4 Arquivos conio.c e conio.h em C++ 15.5 Templates em C++ 16. Composio 17. Programas utilizando Herana Simples

Prof. Dr. Paulo Roberto Gomes Luzzardi

C++ for Linux

1. Introduo
O t e r m o Programao Orientao Objetos (O O P - Object Oriented Programming ) significa organizar um programa de forma que o mundo real seja representado virtualmente (ou internamente) como se fosse uma coleo de objetos que incorpora uma estrutura de dados (variveis ou atributos) e um conjunto de operaes (funes ou mtodos) que manipulam esta estrutura.

1.1 Origens
A linguagem de programao C++ uma extenso da linguagem C padro. Foi criada por Bjarne Stroustrup em 1980 na Bell, que a chamou de C com Classes e em 1983 passouse a se chamar C++. 1967: Simula (Noruega). 1980: Small Talk (Xerox) com objetivos comerciais e acadmicos (Adele Goldberg). 1980's Objective C (Cox), C++ (Stroustrup), Eifell (Meyer).

1.2 Conceitos bsicos


O paradigma orientado objetos possui cinco componentes bsicos: objetos, mensagens, classes, instncias e mtodos.

1.2.1 Objetos, mensagens, classes, instncias e mtodos


Objetos so entidades lgicas que contm atributos (dados armazenados em variveis) e mtodos (funes) que manipulam estes dados. Um objeto pode ser definido atravs de um tipo de dado chamado classe (class) ou atravs de uma estrutura (struct). Atributos: So as variveis definidas e declaradas para cada objeto. Existe trs tipos: atributos dos objetos ( individual para cada objeto, ou seja, cada objeto pode possuir um valor diferente) e atributos da classe (so estticos, ou seja, coletivos, iguais para todos os objetos) e atributos constantes (idnticos aos atributos da classe, somente no podem ser alterados por serem constantes). Mtodos: So as funes definidas pelo programador que serviro para manipular os atributos. Mensagens: So as chamadas dos mtodos (chamada das funes). Classe: um tipo de dado definido por class ou struct. Uma classe no um objeto, sim uma descrio do objeto.

Instncia: Os objetos so instncias de uma classe. Resumidamente, objetos so instncias de classes que respondem as mensagens atravs dos mtodos escritos pelo programador. Existem algumas diferenas na nomenclatura da programao orientao objetos e a definida em C++, veja no quadro abaixo:
POO classe objeto Mtodo atributo mensagem sub-classe super-classe herana #define max 10 typedef int TDados; // ----------------------------------- Definio da Classe Pilha (... // comentrio em C++ ) class Pilha { int topo; // ... atributo do objeto, cada um possui o seu TDados pilha[max]; // ... atributo do objeto, cada um possui o seu static int n; // ... atributo da classe, coletivo para todos os objetos static const float pi; // ... atributo constante da classe, coletivo para todos os objetos public: void Cria_Pilha(void); // ... mtodos (ou mensagens) void Push(TDados dado); // ... mtodos (ou mensagens) TDados Pop(void); // ... mtodos (ou mensagens) TDados Consulta_Pilha(void); // ... mtodos (ou mensagens) void Exibe_Pilha(void); // ... mtodos (ou mensagens) }; C++ classe objeto funo atributo chamada de uma funo classe derivada classe base derivao

Os atributos podem ser: atributos do objeto, atributos da classe (estticos) e atributos constantes (veja o prximo programa exemplo). Atributos do objeto: So individuais para cada objeto, ou seja, cada objeto pode ter um valor diferente. Atributos da classe: So estticos, ou seja, coletivos, iguais para todos os objetos. Podem ser alterados (a inicializao deve ser feita fora da classe). Atributos constantes: So constantes e estticos, ou seja, coletivos, iguais para todos os objetos. No podem ser alterados, pois so constantes (a inicializao deve ser feita fora da classe).

class Math { int x, y; // ... atributo do objeto, cada um possui o seu static int n; // ... atributo da classe, coletivo para todos os objetos static const float pi; // ... atributo constante da classe, coletivo para todos os objetos public: Math(void) : x(1), y(2) { } // inicializao dos atributos atravs do construtor void Exibe(void) { cout << x << - << y << endl; } }; int Math :: n = 7; // inicializao do atributo da classe (tem que ser fora da classe) const float Math :: pi = 3.141516; // inicializao do atributo constante da classe

Observao: Um objeto (instncia de uma classe ) pode ser comparado a uma estrutura (struct) do C padro, mas alm de possuir campos ( dados, variveis ou atributos), possui tambm as funes ( mtodos) que manipulam estes dados (atributos), ou seja, encapsulamento d e dados e cdigo. Uma classe uma extenso do tipo de dados struct. Uma estrutura ( struct) em C++ tem as mesmas caractersticas de uma classe (class). Uma linguagem de programao orientada objetos precisa suportar quatro propriedades: abstrao, encapsulamento, herana e polimorfismo.

1.2.2 Abstrao
Objetos devem representar dados do mundo real.

1.2.3 Encapsulamento (encapsulao)


Os objetos possuem internamente atributos e mtodos agrupados no mesmo local, onde os mtodos manipulam os atributos.

1.2.4 Polimorfismo (grego: muitas formas )


a capacidade de objetos diferentes reagirem segundo a sua funo a uma ordem padro. Significa que o nome de um objeto pode ser utilizado para vrios propsitos ligeiramente diferentes, ou seja, ... um a interface, v rio s m to do s ... . A caracterstica de polimorfismo utilizada na sobrecarga de funes e sobrecarga de operadores.

1.2.5 Herana
o processo pelo qual uma classe de objetos pode adquirir as propriedades de outra classe de objetos, em outras palavras, um objeto herda as caractersticas de outro (herana simples) ou vrios objetos ( herana mltipla).

1.2.6 C++ versus C


A Linguagem de Programao C++ possui as seguintes caractersticas que a linguagem C no possui, dentre elas pode-se citar: a) Utilizao de classes e objetos; b) Utilizao de funes inline; c) Converso de tipos (vrios tipos de casts); d) Verificao de argumentos (parmetros) das funes; e) Operadores de gerenciamento de memria ( new e delete ) especficos; f) Utilizao de referncias no lugar de ponteiros; g) Uso de constantes tipadas ( const int n = 7; ) h) Sobrecarga de operadores; i) Sobrecarga de funes; j) Polimorfismo (sobrecarga de operadores e funes); k)Templates (utilizao de gabaritos): so funes genricas em que o tipo dos dados (parmetros e retorno da funo) so definidos em tempo de compilao; l) Tratamento de excees (tratamento de erros); m) Espaos de nomes ( namespace ).

1.2.7 Tipos de dados em C++


Tipos bsicos: char, int, float, double, void. Tipos derivados: estruturas.

vetor, funes, ponteiros, referncias, constantes, classes e

Tipo lgico : bool (true e false so pr-definidos em C++)

Como declarar e utilizar uma varivel lgica :


int main(void) { bool ok = true; bool flag = false; }

Modificadores de tipos em C++ : signed, unsigned, short e long .


Tipo de Dado bool char unsigned char short int unsigned short int int unsigned int long int unsigned long int float double long double enum long long int Tipo lgico caracter caracter c/sinal inteiro curto inteiro curto sem sinal inteiro inteiro sem sinal inteiro longo inteiro longo sem sinal real (preciso de 7 dgitos) real (preciso de 15 dgitos) real (preciso de 18 dgitos) enumerao inteiro super longo Bits 8 8 8 16 16 32 32 32 32 32 64 80 16 64 Bytes 1 1 1 2 2 4 4 4 4 4 8 10 2 8 Faixa true ou false (0 ou 1) -128 127 0 255 -32768 32767 0 65535 -2.147.483.648 2.147.483.648 0 4.294.295.000 -2.147.483.648 2.147.483.648 0 4.294.967.296 -3.4e-38 3.4e+38 -1.7e-308 1.7e+308 -3.4e-4932 3.4e+ 4932 -2.147.483.648 2.147.483.648 -9.223.372.036.854.775.808 9.223.372.036.854.775.807

long int x = 2147483648 l; long long int y = 9223372036854775807 ll;

Programa exemplo:
#include <iostream> using namespace std;

// necessrio um l // necessrio dois ll

int main(void) { long long int x = 9223372036854775807ll; cout << x << endl; x++; cout << x << endl; } // 9223372036854775807 // -9223372036854775808 Porque?

Observao: Sempre que uma operao matemtica for realizada e o valor for maior ou menor que os valores mximo e mnimo, referente a faixa de valores vlidos, o programa rotaciona e coloca o resultado da operao dentro da faixa de valores vlidos. No programa acima, quando o maior valor possvel de um inteiro super longo acrescido em um, o valor resultante o menor valor da faixa de valores.

1.2.8 Alguns conceitos bsicos em C++


Classes de armazenamento : responsvel pelo tempo de vida de um objeto: Se o objeto for esttico ele dura (permanece alocado na memria RAM) todo o tempo de vida do programa. Se ele for dinmico (new) ele tem um tempo finito de vida, ou seja, ele depende do comando ( delete ), ou seja, ele alocado e desalocado da memria RAM.

1.3 Estilo de programao em C++


Aqui so mostradas mais algumas diferenas entre o C e C++. Programa exemplo (1): Primeiro programa em C++: Hello World .
// hello.cpp #include <iostream.h> (cin e cout) int main(void) { cout << "Hello, World ...\n"; cout << Tecle <enter> para continuar "; cin.get(); return(0); } // ... comentrio em C++ // ... header responsvel pelas funes de entrada e sada

// ... imprime na tela // ... para e espera que uma tecla seja pressionada

Programa exemplo (2) : Programa permite a entrada de uma palavra via teclado (cin) e exibe ( cout) o nmero de caracteres ( strlen) desta palavra na tela.
// palavra.cpp #include <iostream.h> #include <string.h> int main(void) { char palavra[256]; cout << "Digite uma palavra: "; cin >> palavra; // ... entrada de dados via teclado ( no aceita espaos) cout << "Palavra tem " << strlen(palavra) << " caracter(es)" << endl; // pula prxima linha return(0); // strlen pertence ao C padro }

Observaes:
cout << Palavra: ; cin >> palavra; // ... << chamado operador de sada // ... >> chamado operador de entrada

Programa exemplo (3): O programa permite a entrada de uma palavra via teclado (cin.getline ) e exibe ( cout) o nmero de caracteres ( strlen) desta palavra na tela.
// nome.cpp #include <iostream.h> #include <string.h> int main(void) { char nome[81];

cout << "Digite um Nome: "; cin.getline(nome, 80); // ... entrada de dados via teclado (aceita espaos) cout << nome << " tem " << strlen(nome) << " caracter(es)" << endl; return(0); }

Programa exemplo (4): O programa permite a entrada de uma palavra via teclado (cin) e exibe ( cout) o nmero de caracteres ( strlen) desta palavra na tela demonstrando como limpar o buffer de teclado ( cin.ignore).
// pausa.cpp #include <iostream.h> #include <string> using namespace std; void pausa(void) { cin.ignore(5,'\n'); cin.get(); } int main(void) { string palavra;

// header do C++, existe tambm string.h do C padro // necessrio para o header string

// limpar o buffer de teclado // espera uma tecla qualquer

// classe string, no precisa inicializar

cout << "Digite uma palavra: "; cin >> palavra; // ... entrada de dados via teclado cout << "Palavra tem " << palavra. length() << " caracter(es)" << endl; pausa(); // pausa }

Programa exemplo (5): O programa demonstra a definio e utilizao de uma classe Ponto.
// ponto.cpp #include <iostream> using namespace std; class Ponto { int x, y; // necessrio por causa do include sem (.h) // definio de uma classe // no necessrio declarar implicitamente como private // mtodo privado, no pode ser chamado pelo main // somente por mtodos da classe Ponto

void seta_atributos(int tx, int ty) { x = tx; y = ty; } public: void Inicializa(int tx, int ty) main { seta_atributos(tx,ty);

// mtodos pblicos, podem ser chamados pelo

10

} void Exibe(void) { cout << "( x = " << x << " ) ( y = " << y << " )" << endl; } void Move(int tam) { x = x + tam; y = y + tam; } }; // no esquecer ponto-e-vrgula int main(void) { Ponto pt;// declarao de um objeto pt da classe Ponto pt.Inicializa(1, 2); pt.Exibe(); pt.Move(10); pt.Exibe(); } Resultado do Programa : (x=1)(y=2) ( x = 11 ) ( y = 12 )

Programa exemplo (6): Programa demonstra a definio e utilizao de uma Calculadora, simulando quatro operaes [+, -, * e /].
// calc.cpp #include <iostream> using namespace std; class Calculadora { private: double x, y, resp; char op; bool erro; private: void Add(void) { resp = x + y; erro = false; } void Sub(void) { resp = x - y; erro = false; } void Mult(void) { resp = x * y; erro = false; } void Div(void)

classe

// bool ... tipo lgico ( true ou false)

11

{ if (y not_eq 0) // not_eq igual a != { resp = x / y; erro = false; } else erro = true; } public: void Entrada(void) { cout << "Digite um valor: "; cin >> x; cout << "Operador [+-*/]: "; do { op = cin.get(); } while (not strchr("+-*/",op)); cout << "Digite outro valor: "; cin >> y; } void Calcula(void) { switch (op) { break; case '-': Sub(); break; case '*': Mult(); break; case '/': Div(); break; } } void Exibe(void) { if (erro) cout << "ERRO: Diviso por Zero" << endl; else cout << "Resposta: " << resp << endl; }

// not igual a !

case '+': Add();

};

int main(void) { Calculadora calc; calc.Entrada(); calc.Calcula(); calc.Exibe(); }

// Calculadora (classe) calc (objeto)

Programa exemplo (7): O programa demonstra a declarao de variveis em qualquer lugar ou no escopo de um bloco ou comando.
// ascii.cpp #include <iostream>

12

using namespace std; int main(void) { for (char i = 'A';i <= 'Z';i++) // a varivel i foi declarada no escopo do comando for cout << i; cout << endl; for (char j = 'a';j <= 'z';j++) // a varivel j foi declarada no escopo do comando for cout << j; cout << endl; }

Programa exemplo (8): O programa exibe na tela a tabela ASCII.


// asctable.cpp #include <iostream> using namespace std; int main(void) { for (int cod = 32;cod <= 127;cod++) { cout << "Cdigo: " << cod << "-> Caracter: " << ( char) cod; cin.get(); } }

// cast char

Comentrio: Em C++ permitido declarar variveis locais dentro de um bloco. Observao: Uma varivel declarada no escopo de um comando ou dentro de um bloco somente pode ser acessada no bloco ou no escopo do comando.

namespace
Quando o programador escreve um programa pode ocorrer a repetio de um nome de um mtodo e/ou classe que j existe em alguma biblioteca padro. Para evitar esse erro, utiliza-se namespace. Um namespace permite dividir um programa em regies que mantm suas prprias tabelas de smbolos (regies chamadas declarativas). Um namespace evita que nomes declarados em um programa entrem em conflito com outros nomes definidos no mesmo programa, uma vez que os nomes de um namespace so independentes dos outros. Se um namespace no utilizado preciso referenciar as funes da seguinte maneira: namespace :: nome (exemplo: std::cout).

Programa SEM o uso o namespace :


Programa exemplo (9) : O programa exibe na tela a tabela ASCII mostrando a

13

no utilizao do namespace.
// ascii.cpp #include <iostream> int main(void) { for (char i = 'A';i <= 'Z';i++) std::cout << i; std::cout << std::endl; for (char j = 'a';j <= 'z';j++) std::cout << j; std::cout << std::endl; } // note que o arquivo de header est sem .h

Programa COM o uso o namespace :


Programa exemplo (10): O programa exibe na tela a tabela ASCII mostrando a utilizao do namespace.
// ascii.cpp #include <iostream> using namespace std; int main(void) { for (char i = 'A';i <= 'Z';i++) cout << i; cout << endl; for (char j = 'a';j <= 'z';j++) cout << j; cout << endl; } // necessrio para o header iostream

1.4 Classes em C++


Em C++, para criar um objeto, necessrio definir uma classe (class). Como foi visto anteriormente, uma classe sintaticamente similar a uma estrutura (struct), apenas com a diferena que a estrutura manipulada por funes externas, ao invs da classe, que possui as funes internas para manipular seus atributos. Uma classe pode ter atributos e mtodos privados (private) e / o u pblicos (public). Por default , os atributos e mtodos de uma classe so privados, ou seja, se nenhum especificador de acesso for declarado, o compilador considera por default private. Se os atributos e mtodos so privados, eles s podem ser acessados por funes (mtodos) membros da classe.

Sintaxe de uma classe: 14

class nome_da_classe { atributos e mtodos privados; public: }; atributos e mtodos pblicos;

// ... s podem ser acessados por objetos desta classe

// ... podem ser acessados por outros objetos

Exemplo da declarao de uma classe :


const int TAM = 9; typedef int TDados; // -------------------------------------- Definio da Classe Fila class Fila { TDados fila[TAM]; int inic, fim; public: void Cria_Fila(void); // ... mtodo pblico void Inclui_Fila(TDados dado); // ... mtodo pblico TDados Exclui_Fila(void); // ... mtodo pblico TDados Consulta_Fila(void); // ... mtodo pblico void Exibe_Fila(void); // ... mtodo pblico // constante tipada

// ... atributo privado // ... atributos privados

};

Como escrever um mtodo (funo) fora da classe :


// -------------------------------------- Inclui_Fila void Fila :: Inclui_Fila(TDados dado) { if (fim == TAM-1) { cout << "Erro: Fila Cheia" << endl; return; } fila[fim] = dado; fim++; } // ... :: operador de resoluo de escopo

Outra forma de declarar uma classe ( struct):


Programa exemplo (11) : O programa demonstra a declarao de uma classe atravs de uma struct.
// struct.cpp #include <iostream> using namespace std;

15

struct Contador { private: int num; public: void init(void) { num = 0; } void incrementa(void) { num = num + 1; } int exibe(void) { return(num); } }; int main(void) { Contador c; c.init(); cout << c.exibe() << endl; c.incrementa(); cout << c.exibe() << endl; cin.get(); }

Como definir um objeto:


nome_da_classe nome_do_objeto, nome_do_objeto, ...;

Exemplo:
Fila fila1, fila2; // ... definio dos objetos fila1 e fila2

Como acessar um mtodo (como enviar mensagem para um objeto):


fila1.Cria_Fila(); fila2.Cria_Fila();

Programa exemplo (12): Implementao do objeto Lista (Lista Linear).


// linear.cpp (Lista_Linear) #include <iostream> #include <string> #include <cctype> // ctype para o C++ using namespace std; const int tam = 5;

16

typedef int TDados;

// -------------------------------------- Definio da Classe Lista class Lista { TDados lista[tam]; // atributos privados (private) int n; public: void Inicializa_Lista(void); void Inclui_Lista(TDados dado); TDados Exclui_Lista(void); TDados Consulta_Lista(void); void Exibe_Lista(void); }; // ... obrigatrio ponto-e-vrgula // -------------------------------------- Inicializa_Lista void Lista :: Inicializa_Lista(void) { n = 0; } // -------------------------------------- Inclui_Lista void Lista :: Inclui_Lista(TDados dado) { if (n == tam) { cout << "Erro: Lista Cheia" << endl; return; } lista[n] = dado; n++; } // -------------------------------------- Exclui_Lista TDados Lista :: Exclui_Lista(void) { if (n == 0) { cout << "Erro: Lista Vazia << endl; return(0); } n--; return(lista[n+1]); } // -------------------------------------- Consulta_Lista TDados Lista :: Consulta_Lista(void) { if (n == 0) { cout << "Erro: Lista Vazia" << endl; return(0); } return(lista[n-1]);

17

} // -------------------------------------- Exibe_Lista void Lista :: Exibe_Lista(void) { cout << "Lista: "; if (n == 0) { cout << "VAZIA << end; return; } for (int i = 0;i < n;i++) cout << lista[i] << " "; cout << endl; return; } // -------------------------------------- Programa Principal int main(void) { Lista lista; char tecla; TDados valor; lista.Inicializa_Lista(); do { lista.Exibe_Lista(); cout << "[I]nclui, [E]xclui, [C]onsulta ou [F]im: "; do { tecla = toupper(cin.get()); } while (not strchr("IECF", tecla)); switch (tecla) { case 'I': cout << "Valor: "; cin >> valor; lista.Inclui_Lista(valor); break; case 'E': valor = lista.Exclui_Lista(); if (valor not_eq 0) cout << "Valor Excludo da Lista: " << valor << endl; break; case 'C': valor = lista.Consulta_Lista(); if (valor not_eq 0) cout << "Valor Consultado: " << valor << endl; break; } } while (tecla not_eq 'F'); }

Programa exemplo (13): Implementao de um objeto Pilha.


// Pilha.cpp #include <iostream> #include <string> #include <cctype>

18

using namespace std; const int tam = 50; typedef int TDados; // -------------------------------------- Definio da Classe Pilha class Pilha { TDados pilha[tam]; int topo; public: void Cria_Pilha(void); void Push(TDados dado); TDados Pop(void); TDados Consulta_Pilha(void); void Exibe_Pilha(void); }; // -------------------------------------- Cria_Pilha void Pilha :: Cria_Pilha(void) { topo = 0; } // -------------------------------------- Push void Pilha :: Push(TDados dado) { if (topo == tam) { cout << Erro: Pilha Cheia << endl; return; } pilha[topo] = dado; topo++; } // -------------------------------------- Pop TDados Pilha :: Pop(void) { if (topo == 0) { cout << "Erro: Pilha Vazia << endl; return(0); } topo--; return(pilha[topo]); } // -------------------------------------- Consulta_Pilha TDados Pilha :: Consulta_Pilha(void) { if (topo == 0) { cout << "Erro: Pilha Vazia" << endl;

19

return(0); } return(pilha[topo-1]); } // -------------------------------------- Exibe_Pilha void Pilha :: Exibe_Pilha(void) { cout << "Pilha: "; if (topo == 0) { cout << "VAZIA << endl; return; } for (int i = topo-1;i >= 0;i--) cout << pilha[i] << " "; cout << endl; return; }

// pode ser usada a funo endl;

// -------------------------------------- Programa Principal int main(void) { Pilha pilha; char tecla; TDados valor; pilha.Cria_Pilha(); do { pilha.Exibe_Pilha(); cout << "[P]ush, P[o]p, [C]onsulta ou [F]im: "; do { tecla = toupper(cin.get()); } while (not strchr("POCF", tecla)); switch (tecla) { case 'P': cout << "Valor: "; cin >> valor; pilha.Push(valor); break; case 'O': valor = pilha.Pop(); if (valor not_eq 0) cout << "Valor Excludo da Pilha: " << valor << endl; break; case 'C': valor = pilha.Consulta_Pilha(); if (valor not_eq 0) cout << "Valor Consultado: " << valor << endl; break; } } while (tecla not_eq 'F'); }

Programa exemplo (14): Implementao de um objeto Fila.


// Fila.cpp #include <iostream>

20

#include <string> #include <cctype> using namespace std; const int tam = 5; typedef int TDados; // -------------------------------------- Definio da Classe Fila class Fila { TDados fila[tam]; int inic,fim; public: void Cria_Fila(void); void Inclui_Fila(TDados dado); TDados Exclui_Fila(void); TDados Consulta_Fila(void); void Exibe_Fila(void); }; // -------------------------------------- Cria_Fila void Fila :: Cria_Fila(void) { inic = 0; fim = 0; } // -------------------------------------- Inclui_Fila void Fila :: Inclui_Fila(TDados dado) { if (fim == tam-1) { cout << "Erro: Fila Cheia" << endl; return; } fila[fim] = dado; fim++; } // -------------------------------------- Exclui_Fila TDados Fila :: Exclui_Fila(void) { if (fim == 0) { cout << "Erro: Fila Vazia" << endl; return(0); } inic++; if (inic >= fim) fim = 0; return(fila[inic-1]); } // -------------------------------------- Consulta_Fila

21

TDados Fila :: Consulta_Fila(void) { if (fim == 0) { cout << "Erro: Fila Vazia" << endl; return(0); } return(fila[inic]); } // -------------------------------------- Exibe_Fila void Fila :: Exibe_Fila(void) { cout << "Fila: "; if (fim == 0) { cout << "VAZIA\n"; return; } for (int i = inic;i < fim;i++) cout << fila[i] << " "; cout << endl; return; } // -------------------------------------- Programa Principal int main(void) { Fila fila; char tecla; TDados valor; fila.Cria_Fila(); do { fila.Exibe_Fila(); cout << "[I]nclui, [E]xclui, [C]onsulta ou [F]im: "; do { tecla = toupper(cin.get()); } while (not strchr("IECF", tecla)); switch (tecla) { case 'I': cout << "Valor: "; cin >> valor; fila.Inclui_Fila(valor); break; case 'E': valor = fila.Exclui_Fila(); if (valor not_eq 0) cout << "Valor Excludo da Fila: " << valor << endl; break; case 'C': valor = fila.Consulta_Fila(); if (valor not_eq 0) cout << "Valor Consultado: " << valor << endl; break; } } while (tecla not_eq 'F'); }

22

1.5 Sobrecarga de funes


Uma das formas de polimorfismo em C++ feito atravs da sobrecarga de funes , ou seja, duas ou mais funes, com mesmo nome, recebem parmetros de tipos diferente podendo ainda ter retorno diferentes.
// abs.cpp #include <iostream> using namespace std; // ----------------------------- prototypes int abs(int x); double abs(double x); // declarao da funo abs // sobrecarga da funo abs

// ----------------------------- Programa Principal int main(void) { cout << abs(-10) << endl; cout << abs(-12.34) << endl; } // ----------------------------- abs int abs(int x) { return(x < 0 ? -x : x); } // ----------------------------- abs double abs(double x) { return(x < 0 ? -x : x); }

Operador Ternrio:
Sintaxe: condio ? comando1 : comando2; Exemplo:
int maior(int x, int y) { return(x > y ? x : y); }

Programa exemplo (16): O programa demonstra a sobrecarga de funes atravs da funo stradd.
// stradd.cpp

23

#include <iostream> #include <string> using namespace std; // --------------------------------- Prototypes void stradd(char *s, char *r); void stradd(char *s, int i); void stradd(char *s, double d); // --------------------------------- Programa Principal int main(void) { char str[80] = ""; stradd(str,"UCPel, "); stradd(str,2006); stradd(str," -> "); stradd(str,123.45); cout << str << endl; } // --------------------------------- stradd void stradd(char *s, char *r) { strcat(s,r); } // --------------------------------- stradd void stradd(char *s, int i) { char tmp[80]; sprintf(tmp,"%d",i); strcat(s,tmp); } // --------------------------------- stradd void stradd(char *s, double d) { char tmp[80]; sprintf(tmp,"%.2f",d); strcat(s,tmp); }

Programa exemplo (17): O programa demonstra a sobrecarga de funes atravs da funo Imprime.
// imprime.cpp #include <iostream>

24

using namespace std; // --------------------------------- Prototypes void Imprime(char *s); void Imprime(char s); void Imprime(int s); void Imprime(double s); // --------------------------------- Programa Principal int main(void) { Imprime("Sistema Operacional Linux") ; Imprime('A'); Imprime(123); Imprime(123.45); } // --------------------------------- Imprime void Imprime(char *s) { cout << s << endl; } // --------------------------------- Imprime void Imprime(char s) { cout << s << endl; } // --------------------------------- Imprime void Imprime(int s) { cout << s << endl; } // --------------------------------- Imprime void Imprime(double s) { cout << s << endl; }

Sobrecarga de operadores (polimorfismo)


Outra forma de polimorfismo em C++ a sobrecarga de operadores. Alguns operadores podem ser sobrecarregados. Por exemplo, em iostream os operadores << e >> so sobrecarregados nos mtodos cout e cin.
cout << Digite uma palavra: ; cin >> palavra;

25

Valores default de parmetros formais


Os parmetros formais (tambm conhecidos por argumentos) nas funes ou mtodos em C++ podem assumir valores default (por falta), ou seja, no caso da chamada de uma funo suprimir um parmetro.

Funo com valor default depois da funo main :


Programa exemplo (18): O programa demonstra o uso de valores default na funo Imprime_String .
// default.cpp #include <iostream> using namespace std; // --------------------------------- Prototypes void Imprime_String(char *s, int linha = 1); // --------------------------------- Programa Principal int main(void) { Imprime_String("Ubuntu 6.06", 3); Imprime_String("Ubuntu 6.06"); } // valor default

// ... parmetro linha foi inserido // parmetro linha foi suprimido

// --------------------------------- Imprime_String void Imprime_String(char *s, int linha) { for (int i = 1;i <= linha;i++) cout << endl; cout << s << endl; } // sem valor default

Funo com valor default antes da funo main :


Programa exemplo (19): O programa demonstra o uso de valores default na funo Imprime_String .
// default.cpp #include <iostream> using namespace std; // --------------------------------- Imprime_String void Imprime_String(char *s, int linha = 1) { for (int i = 1;i <= linha;i++) // valor default

26

cout << endl; cout << s << endl; } // --------------------------------- Programa Principal int main(void) { Imprime_String("Ubuntu 6.06", 3); Imprime_String("Ubuntu 6.06"); }

// parmetro linha foi inserido // parmetro linha foi suprimido

Referncias e parmetros de referncia


As referncias so diferentes de ponteiros, pois elas ficam vinculadas diretamente localizao de memria de uma expresso ou varivel. No reservado espao de memria para uma referncia, ou seja, uma referncia no ocupa espao de memria. As referncias servem como uma forma alternativa de passagem de parmetro por referncia, ou seja, sem o uso de ponteiros. Sintaxe: tipo &varivel = expresso_inicializao;
// ... expresso ou varivel

Significado: O operador & significa referncia ao tipo , ou seja, a varivel de referncia fica vinculada posio de memria da expresso de inicializao. Programa exemplo (20): O programa demonstra a utilizao de ponteiros em C++.
// pointer.cpp #include <iostream> using namespace std; int main(void) { int n = 7; int *p = &n; cout << "n igual " << n << endl; cout << "n igual " << *p << endl; cout << "o endereo de n igual " << &n << endl; cout << "o endereo de n igual " << p << endl; cout << "o endereo de p igual " << &p << endl; }

Programa exemplo (21): O programa demonstra a utilizao de referncias e parmetros de referncia em C++.
// reference.cpp

27

#include <iostream> using namespace std; int main(void) { int n = 7; int &ref = n;

// ref uma referncia para uma posio de memria // ... n igual a 7 // .. ref igual a 7 // ... n igual a 8 // ... ref igual a 8

cout << "n igual " << n << endl; cout << "n igual " << ref << endl; ref++; cout << "n igual " << n << endl; cout << "n igual " << ref << endl; }

Programa exemplo (22): O programa demonstra o uso de referncias e parmetros de referncia como parmetro de funes atravs da funo troca.
// troca.cpp #include <iostream> using namespace std; // ------------------ Prototypes void troca(int &x, int &y); void troca(int *x, int *y); // passagem de parmetros com referncias // passagem de parmetros com ponteiros

// ----------------------------------------------------- Programa Principal int main(void) { int x = 3, y = 4; cout << x << " - " << y << endl; cout << x << " - " << y << endl; troca(x,y); troca(&x,&y); cout << x << " - " << y << endl; } // ------------------------------ troca void troca(int &x, int &y) { int t; t = x; x = y; y = t; } // ------------------------------ troca void troca(int *x, int *y) { // chamada com ponteiros // chamada com referncias

// chamada com referncias // chamada com ponteiros

28

int t; t = *x; *x = *y; *y = t; }

Especificador inline
O especificador inline utilizado na definio do prottipo de uma funo (ou na definio de uma funo) para especificar ao compilador que a funo deve ser expandida na linha da chamada da funo e no seja feita a chamada da funo propriamente dita, ou seja, torna o programa mais rpido, pois a chamada da funo no utiliza a pilha de retorno. Programa exemplo (23) : O programa demonstra a utilizao do especificador inline.
// inline.cpp #include <iostream> using namespace std; // ------------------------------------------- Random inline void Random(int n) { cout << rand() % n << endl; } // ----------------------------------------------------- Programa Principal int main(void) { srand(time(NULL)); Random(10); Random(100); Random(1000); }

// inicializa o gerador de nmeros aleatrios // gera um nmero aleatrio entre 0 e 9 // gera um nmero aleatrio entre 0 e 99 // gera um nmero aleatrio entre 0 e 999

Especificador const
O especificador const serve para definir uma constante tipada, ou seja, o valor da entidade declarada como const no pode ser alterada. Programa exemplo (24) : O programa demonstra a utilizao do especificador const.
// circulo.cpp #include <iostream> #include <math.h> using namespace std;

29

int main(void) { const float pi = 3.1416; float raio,area; cout << "Raio: "; cin >> raio; area = pi * pow(raio,2); cout << "Area do Crculo: " << area << endl; }

// power funo potncia

Programa exemplo (25) : O programa demonstra a utilizao do especificador const.


// const.cpp #include <iostream> #include <math.h> using namespace std; const int tam = 5; const double pi = 4 * atan(1); const char *nome = "\nBy Paulo Roberto Gomes Luzzardi, 2006\n"; int main(void) { int x[tam] = {1, 2, 3, 4, 5}; cout << pi; cout << nome; for (int i = 0;i < 5;i++) cout << x[i] << ", "; cout << endl; }

Operador de resoluo de escopo (qualificao de escopo)


O operador de resoluo de escopo ( : : ) permite escrever funes fora do escopo de uma classe ( class) ou estrutura ( struct), ou ainda, referenciar uma varivel global dentro de um bloco que possui uma varivel local com o mesmo nome da varivel global. Programa exemplo (26) : O programa demonstra a utilizao do operador de qualificao de escopo ( ::).
// escopo.cpp #include <iostream> using namespace std; int valor = 1; int main(void) {

30

int valor = 2; cout << valor << endl; cout << ::valor << endl; } // aqui valor local (2) // ::valor global (1)

Especificador enum
O especificador enum permite ao programador criar tipos de dados do tipo enumerao. Sintaxe: enum nome_enumerao {lista_das_enumeraes} lista_de_variveis; Programa exemplo (27): O programa demonstra a utilizao do especificador enum.
// enum.cpp #include <iostream> using namespace std; int main(void) { enum Dias {Seg, Ter, Qua, Qui, Sex, Sab, Dom}; Dias d; int i; do {

cout << "Dia da Semana [0..6] ou [9] Sair: "; cin >> i; d = Dias(i); switch (d) { case Seg: cout << "Segunda-feira" << endl; break; case Ter: cout << "Tera-feira" << endl; break; case Qua: cout << "Quarta-feira" << endl; break; case Qui: cout << "Quinta-feira" << endl; break; case Sex: cout << "Sexta-feira" << endl; break; case Sab: cout << "Sbado" << endl; break; case Dom: cout << "Domingo" << endl; break; } } while (i not_eq 9);

Programa exemplo (28): O programa demonstra a utilizao do especificador enum.


// enum2.cpp #include <iostream>

31

using namespace std; int main(void) { enum Dias {Seg, Ter, Qua, Qui, Sex, Sab, Dom}; const char *nome[] = {"Segunda", "Tera", "Quarta", "Quinta", "Sexta", "Sbado", "Domingo"}; for (int i = 0;i <= 6;i++) cout << Dias(i) << " -> " << nome[Dias(i)] << endl; }

Sada do programa:
0 -> Segunda 1 -> Tera 2 -> Quarta 3 -> Quinta 4 -> Sexta 5 -> Sbado 6 -> Domingo

Operadores new e delete (alocar e liberar memria)


Os operadores new e delete permitem ao programador alocar ( new) e liberar (delete ) memria dinamicamente (alocao dinmica, ou seja, alocao em tempo de execuo do programa) na rea de h e a p (local da memria RAM utilizada para o armazenamento de estruturas de dados de tamanho e existncia no determinada). Eles substituem as funes malloc, calloc e free da linguagem C padro. Sintaxe (new): tipo_base *nome_ponteiro = new tipo_base; tipo_base *nome_ponteiro = new (tipo_base); tipo_base *nome_ponteiro = new tipo_base[nmero_de_elementos]; Exemplos:

float *p = new float; float *q = new (float); float *r = new float[7];

Sintaxe (delete ): delete nome_ponteiro; Exemplo: delete p; ou delete [] r; // quando um vetor Programa exemplo (29): O programa demonstra a utilizao dos operadores new e delete.
// new.cpp #include <iostream> using namespace std;

32

int main(void) { int *x = new int; *x = 100; cout << *x << endl; cout << x << endl; delete x; }

// 100 (contedo do ponteiro) // 0x8fbe0dec (endereo do ponteiro)

Programa exemplo (30) : Programa demonstra a utilizao dos operadores new e delete .
// new2.cpp #include <iostream> using namespace std; const int tam = 10; int main(void) { int *x = new int[tam]; for (int i = 0;i < tam;i++) x[i] = i; // x recebe 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 for (int j = 0;j < tam;j++) cout << &x[j] << " -> " << x[j] << endl; delete [] x; }

Resultado do programa :
0x8fc10db2 -> 0 0x8fc10db4 -> 1 0x8fc10db6 -> 2 0x8fc10db8 -> 3 0x8fc10dba -> 4 0x8fc10dbc -> 5 0x8fc10dbe -> 6 0x8fc10dc0 -> 7 0x8fc10dc2 -> 8 0x8fc10dc4 -> 9

Programa exemplo (31): O programa demonstra a utilizao dos operadores new e delete.
// new3.cpp #include <iostream> using namespace std; const int tam = 10;

33

int main(void) { float *x = new float[tam]; for (int i = 0;i < tam;i++) x[i] = (float) i / 2; for (int j = 0;j < tam;j++) cout << &x[j] << " -> " << x[j] << endl; delete [] x; }

Resultado do programa :
0x8f78124e -> 0 0x8f781252 -> 0.5 0x8f781256 -> 1 0x8f78125a -> 1.5 0x8f78125e -> 2 0x8f781262 -> 2.5 0x8f781266 -> 3 0x8f78126a -> 3.5 0x8f78126e -> 4 0x8f781272 -> 4.5

1.6 Herana simples


A herana simples permite que uma classe incorpore os atributos e mtodos de outra classe, ou seja, permite a construo de hierarquias de classes . O primeiro passo envolve a definio de uma classe base que define as caractersticas comuns a todos os objetos derivados desta classe. As classes oriundas da classe base so chamadas classes derivadas. Uma classe derivada herda todas as caractersticas da classe base e pode ter novas caractersticas adicionadas a ela. Uma classe derivada segue a seguinte diretriz em relao a classe base: classe_derivada um(a) classe_base Exemplo: um cardial um pssaro

// classe base: pssaro // classe derivada: cardial

Especificadores de acesso public (pblico) Quem tem acesso classe tem acesso tambm a qualquer membro pblico. raro ter atributos pblicos, mas comum ter mtodos pblicos. Qualquer mtodo tem acesso. 34

private (privado) Um membro privado no acessvel fora da classe, somente pelos membros da
classe.

A inteno permitir que apenas quem escreve a classe possa usar esse membro. protected (protegido) O membro protegido acessvel classe e a suas sub-classes (classes derivadas). A inteno dar acesso aos programadores que estendero sua classe.

Controle de acesso na definio de uma classe derivada


Q u a n d o u m a classe derivada d e f in id a , o u s e j a , n a d e f in i o d e herana simples , seus membros (atributos e mtodos) so declarados internamente e o acesso a estes pode ser pblico ( public), privativo ( private) ou protegido ( protected). O acesso a membros protegidos igual ao acesso a membros privativos, exceto para o acesso das classes derivadas da classe. A forma geral de especificar herana simples :
class classe_derivada : especificador_de_acesso classe_base { // atributos // mtodos };

Quando uma classe herda as caractersticas de outra classe, todos os membros da classe base tornam-se membros da classe derivada. O tipo de acesso da classe base dentro da classe derivada determinado pelo especificador de acesso . Qualquer que seja o especificador de acesso, membros privativos da classe base continuam sendo propriedade privada da classe base, e no podem ser acessados por classes derivadas. Quando o especificador de acesso public, todos os membros pblicos da classe base tornam-se membros pblicos da classe derivada, e os membros protegidos da classe base tornam-se membros protegidos da classe derivada. Esta a diferena que existe entre membros privativos e membros protegidos. Quando o especificador de acesso private, todos os membros pblicos e protegidos da classe base tornam-se membros privativos da classe derivada, ou seja, a classe derivada no pode transferir seus privilgios de acesso a outras classes. Quando o especificador de acesso protected, todos os membros pblicos e protegidos da classe base tornam-se membros protegidos da classe derivada.

35

Programa exemplo (32) : O objetivo do programa demonstrar a utilizao de herana simples (atributos da classe base so privados).
// heranca1.cpp #include <iostream> using namespace std; class Base { int x, y;

// atributos privados, somente a classe base pode ter acesso a eles

public: void Seta(int a, int b) { x = a; y = b; cout << "x = " << x << endl; cout << "y = " << y << endl; } int Soma(void) { cout << "Soma (x+y): " << x+y << endl; return(x+y); } }; class Derivada : public Base { int z; public: Derivada(int x) { z = x; cout << "z = " << z << endl; } int Somador(int soma) { return(soma+z); // no possvel acessar x e y pois so privados a classe base } }; int main(void) { Derivada objeto(3); int resp;

// construtor parametrizado

objeto.Seta(1, 2); resp = objeto.Soma(); cout << "Somador (x+y+z): " << objeto.Somador(resp) << endl; } Resultado do Programa : z=3

36

x=1 y=2 Soma (x+y): 3 Somador (x+y+z): 6

Responda: Porque o atributo z mostrado primeiro?

Tipos de acessos (resumo) public (pblico): Todos os atributos da classe base so pblicos na classe derivada. private (privado): Os atributos s podem ser acessados pelos mtodos que fazem
parte da classe. derivadas.

protected (protegido): Os atributos podem ser acessados pelos mtodos de classes

Programa exemplo (33) : O objetivo do programa demonstrar a utilizao de herana simples (atributos da classe base so protegidos).
// heranca2.cpp #include <iostream> using namespace std; class Base { protected: int x, y; public: void Seta(int a, int b) { x = a; y = b; cout << "x = " << x << endl; cout << "y = " << y << endl; } void Soma(void) { cout << "Soma (x+y): " << x+y << endl; }

// atributos protegidos, ou seja, podem ser acessados na classe derivada

};

class Derivada : public Base { int z; public: Derivada(int x) { z = x; cout << "z = " << z << endl;

37

} int Somador(void) { return(x+y+z); }

};

int main(void) { Derivada objeto(3);

// construtor parametrizado

objeto.Seta(1, 2); objeto.Soma(); cout << "Somador (x+y+z): " << objeto.Somador() << endl; }

Resultado do Programa:
z=3 x=1 y=2 Soma (x+y): 3 Somador (x+y+z): 6

1.7 Construtores e destrutores


Construtor um mtodo especial que tem o mesmo nome da classe. Quando o objeto criado, ou seja, declarado, o construtor executado. Os objetos podem ser globais ou locais. Destrutor outro mtodo especial que possui o nome da classe precedido por um ~ (til). Quando o programa termina (objeto global) ou quando um mtodo termina (objeto local) o objeto destrudo. O destrutor muito til quando o objeto alocado dinamicamente. Programa exemplo (34): O programa demonstra a criao e manipulao de uma lista linear.
// linear.cpp (Lista_Linear) #include <iostream> #include <string> #include <cctype> using namespace std; const int tam = 5; typedef int TDados; // -------------------------------------- Definio da Classe Lista

38

class Lista { TDados lista[tam]; int n; public:

// dados privados (private)

Lista(void); // construtor (no tem tipo de retorno) ~Lista(void); // destrutor (no tem tipo de retorno) void Inclui_Lista(TDados dado); TDados Exclui_Lista(void); TDados Consulta_Lista(void); void Exibe_Lista(void); }; // obrigatrio ponto-e-vrgula // -------------------------------------- Construtor Lista :: Lista(void) { n = 0; } // -------------------------------------- Destrutor Lista :: ~Lista(void) { n = 0; } // -------------------------------------- Inclui_Lista void Lista :: Inclui_Lista(TDados dado) { if (n == tam) { cout << "Erro: Lista Cheia" << endl; return; } lista[n] = dado; n++; } // -------------------------------------- Exclui_Lista TDados Lista :: Exclui_Lista(void) { if (n == 0) { cout << "Erro: Lista Vazia" << endl; return(0); } n--; return(lista[n+1]); } // -------------------------------------- Consulta_Lista TDados Lista :: Consulta_Lista(void) { if (n == 0) {

39

cout << "Erro: Lista Vazia" << endl; return(0); } return(lista[n-1]); } // -------------------------------------- Exibe_Lista void Lista :: Exibe_Lista(void) { cout << "Lista: "; if (n == 0) { cout << "VAZIA" << endl; return; } for (int i = 0;i < n;i++) cout << lista[i] << " "; cout << endl; return; } // -------------------------------------- Programa Principal int main(void) { Lista lista; char tecla; TDados valor; do { lista.Exibe_Lista(); cout << "[I]nclui, [E]xclui, [C]onsulta ou [F]im: "; do { tecla = toupper(cin.get()); } while (not strchr("IECF", tecla)); switch (tecla) { case 'I': cout << "Valor: "; cin >> valor; lista.Inclui_Lista(valor); break; case 'E': valor = lista.Exclui_Lista(); if (valor not_eq 0) cout << "Valor Excluido da Lista: " << valor << endl; break; case 'C': valor = lista.Consulta_Lista(); if (valor not_eq 0) cout << "Valor Consultado: " << valor << endl; break; } } while (tecla not_eq 'F');

Programa exemplo (35): O programa demonstra a criao e manipulao de uma Lista Simplesmente Encadeada .
// Lista Encadeada

40

#include <iostream> #include <string> #include <cctype> using namespace std; // ----------------------------------------- Definies #define SUCESSO #define FALTA_DE_MEMORIA #define LISTA_VAZIA typedef int TDados; typedef struct nodo { 0 1 2

TDados dado; struct nodo *elo; } TNodo;

typedef struct { TNodo *primeiro; } TLista; class Lista { TLista l; public: Lista(void); // construtor ~Lista(void); // destrutor int Inclui_Lista(TDados dado); int Exclui_Lista(void); int Consulta_Lista(TDados *dado); void Imprime_Erro(int erro); void Exibe_Primeiro(void); void Exibe_Lista(void); }; // ------------------------------- Construtor Lista :: Lista(void) { l.primeiro = NULL; } // ----------------------------------------- Destrutor Lista :: ~Lista(void) { TNodo *p,*q; if (l.primeiro not_eq NULL) { p = l.primeiro; while (p not_eq NULL) { q = p->elo; delete(p); p = q;

41

} } l.primeiro = NULL; } // ------------------------------- Inclui_Lista int Lista :: Inclui_Lista(TDados dado) { TNodo *p; p = new TNodo; // em C seria p = (TNodo *) malloc(sizeof(TNodo)); if (p == NULL) return(FALTA_DE_MEMORIA); else { p->dado = dado; if (l.primeiro == NULL) { l.primeiro = p; p->elo = NULL; } else { p->elo = l.primeiro; l.primeiro = p; } return(SUCESSO); } } // ------------------------------- Exclui_Lista int Lista :: Exclui_Lista(void) { TNodo *p; if (l.primeiro == NULL) return(LISTA_VAZIA); else { p = l.primeiro; l.primeiro = p->elo; delete(p); // seria free(p); return(SUCESSO); } } // ------------------------------- Consulta_Lista int Lista :: Consulta_Lista(TDados *dado) { TNodo *p; if (l.primeiro == NULL) return(LISTA_VAZIA); else { p = l.primeiro; *dado = p->dado;

42

return(SUCESSO); }

// ------------------------------- Imprime_Erro void Lista :: Imprime_Erro(int erro) { switch (erro) { case FALTA_DE_MEMORIA: cout << "ERRO: FALTA DE MEMORIA" << endl; break; case LISTA_VAZIA: cout << "ERRO: LISTA VAZIA << endl; break; } } // ----------------------------------------- Exibe_Primeiro void Lista :: Exibe_Primeiro(void) { if (l.primeiro not_eq NULL) cout << "Primeiro: | " << l.primeiro; else cout << "Primeiro: | NULL |"; } // ----------------------------------------- Exibe_Lista void Lista :: Exibe_Lista(void) { TNodo *p; cout << endl << "Lista Encadeada: "; if (l.primeiro == NULL) cout << "LISTA VAZIA"; else { p = l.primeiro; while (p not_eq NULL) { cout << " | " << p->dado; p = p->elo; } } } // ------------------------------- Programa Principal int main(void) { Lista lista; TDados valor; int erro; char tecla; do { lista.Exibe_Primeiro(); lista.Exibe_Lista(); cout << "\n[I]nclui, [E]xclui, [C]onsulta ou [F]im: ";

43

do { tecla = toupper(cin.get()); } while (not strchr("IECF",tecla)); switch (tecla) { case 'I': cout << "Valor: "; cin >> valor; erro = lista.Inclui_Lista(valor); break; case 'E': erro = lista.Exclui_Lista(); if (not erro) cout << "Ok, Elemento Excluido"; break; case 'C': erro = lista.Consulta_Lista(&valor); if (not erro) cout << "Valor Consultado: " << valor << endl; break; } if (erro and tecla not_eq 'F') lista.Imprime_Erro(erro); } while (tecla not_eq 'F'); } // and igual a &&

Programa exemplo (36) : O programa demonstra a criao e manipulao uma Lista Duplamente Encadeada .
// Dupla.cpp #include <iostream> #include <string> #include <cctype> using namespace std; #define SUCESSO #define FALTA_DE_MEMORIA #define LISTA_VAZIA typedef int TDados; typedef struct Nodo { 0 1 2

struct Nodo *anterior; TDados dado; struct Nodo *posterior; } Tnodo;

typedef struct {

TNodo *primeiro; int n; TNodo *ultimo; } TDupla;

class Dupla { TDupla d; public:

Dupla(void); ~Dupla(void);

44

};

int Insere_Direita(TDados dado); int Insere_Esquerda(TDados dado); void Imprime_Lista_Esquerda(void); void Imprime_Lista_Direita(void); void Imprime_Erro(int erro); void Exibe_Descritor(void);

// ------------------------------- Construtor Dupla :: Dupla(void) { d.primeiro = NULL; d.n = 0; d.ultimo = NULL; } // ------------------------------- Destrutor Dupla :: ~Dupla(void) { TNodo *p,*q; p = d.primeiro; while (p not_eq NULL) { q = p; delete(p); p = q->posterior; } } // ------------------------------- Insere_Direita int Dupla :: Insere_Direita (TDados dado) { TNodo *p,*q; p = new TNodo; if (p == NULL) return(FALTA_DE_MEMORIA); else { p->dado = dado; p->posterior = NULL; if (d.n == 0) { d.primeiro = p; d.n = 1; d.ultimo = p; p->anterior = NULL; } else { q = d.ultimo; d.ultimo = p; q->posterior = p; p->anterior = q; (d.n)++; } return(SUCESSO);

45

} } // ------------------------------- Insere_Esquerda int Dupla :: Insere_Esquerda(TDados dado) { TNodo *p,*q; p = new TNodo; if (p == NULL) return(FALTA_DE_MEMORIA); else { p->dado = dado; p->anterior = NULL; if (d.n == 0) { d.primeiro = p; d.n = 1; d.ultimo = p; p->posterior = NULL; } else { q = d.primeiro; d.primeiro = p; q->anterior = p; p->posterior = q; (d.n)++; } return(SUCESSO); } }

// ------------------------------- Imprime_Lista_Direita void Dupla :: Imprime_Lista_Direita(void) { TNodo *p; cout << "\nLista pela Direita: "; p = d.ultimo; while (p not_eq NULL) { cout << p->dado << " | "; p = p->anterior; } } // ------------------------------- Imprime_Lista_Esquerda void Dupla::Imprime_Lista_Esquerda(void) { TNodo *p; cout << "\nLista pela Esquerda: "; p = d.primeiro; while (p not_eq NULL)

46

{ cout << p->dado << " | "; p = p->posterior; }

// ------------------------------- Imprime_Erro void Dupla::Imprime_Erro(int erro) { switch (erro) { case FALTA_DE_MEMORIA: cout << "ERRO: Falta de Memria" << endl; break; case LISTA_VAZIA: cout << "ERRO: Lista Vazia" << endl; break; } } // ------------------------------- Exibe_Descritor void Dupla :: Exibe_Descritor(void) { printf("Descritor: | %p | %d | %p |", d.primeiro, d.n, d.ultimo); } // ------------------------------- Programa Principal int main(void) { Dupla dupla; TDados valor; int erro; char tecla; do { dupla.Exibe_Descritor(); dupla.Imprime_Lista_Esquerda(); dupla.Imprime_Lista_Direita(); cout << "\nValor: "; cin >> valor; if (valor not_eq 0) { cout << "[E]squerda ou [D]ireita: "; do { tecla = toupper(cin.get()); } while (not strchr("ED",tecla)); switch (tecla) { case 'E': erro = dupla.Insere_Esquerda(valor); break; case 'D': erro = dupla.Insere_Direita(valor); break; } if (erro) dupla.Imprime_Erro(erro); } } while (valor not_eq 0); }

47

1.8 Palavras reservadas em C++


A s palavras reservadas e m C + + so: asm, catch, class, delete , private, protected, public, template, friend, inline, new, operator , overload , this, throw, try e virtual.

1.9 Forma geral de um programa em C++


A forma geral de um programa em C++ :
#includes declaraes de classes base; declaraes de classes derivadas; prottipos das funes no-membro; int main(void) { }

1.10 Classe string


C++ possui uma classe chamada string que permite ao programador fazer algumas operaes no possveis na linguagem C padro, como por exemplo, atribuir uma constante string a uma varivel string (veja exemplo abaixo) dentre outras coisas . Os prximos exemplos demonstram alguns mtodos da classe string. Programa exemplo (37): O p r o g r a m a d e m o n s t r a a u t i l i z a o d a c l a s s e string.
// string1.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s = "Couve", r = "-flor"; string t; t = s + r; cout << t << endl; } // C padro no permite atribuio e soma de strings

Programa exemplo (38): O p r o g r a m a d e m o n s t r a a u t i l i z a o d a c l a s s e string.

48

// string2.cpp #include <iostream.h> #include <string> using std::string; // necessrio por causa do arquivo de include <string.h> do C padro

int main(void) { string s = "Couve", r = "-flor"; string t; t = s + r; cout << t << endl; }

Programa exemplo (39): O p r o g r a m a d e m o n s t r a a u t i l i z a o d a c l a s s e string.


// string3.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s = "C++ for Linux"; int n = s.length(); cout << "String: " << s << endl; cout << "Total de Caracteres: " << n << endl; }

Programa exemplo (40): O p r o g r a m a d e m o n s t r a a u t i l i z a o d a c l a s s e string.


// string4.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s; // pode-se declarar uma string sem inicializao cout << "Qual o seu nome? "; getline(cin, s); // mtodo para leitura de uma string if (not s.empty()) // mtodo verifica string vazia if (s != ) { int n = s.size(); // mtodo retorna o nmero de caracteres da string cout << "String: " << s << endl; cout << "Total de Caracteres: " << n << endl; } else

49

cout << "Erro: String Vazia" << endl; }

Programa exemplo (41): O p r o g r a m a d e m o n s t r a a u t i l i z a o d a c l a s s e string.


// string5.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s = "universidade", r; r = s.substr(7, 5); // 7 - posio inicial | 5 - nmero de caracteres que sero copiados cout << "String resultante: " << r << endl; // idade s.erase(0, 7); // 0 - posio inicial | 7 - nmero de caracteres que sero apagados cout << "String s: " << s << endl; // idade }

Programa exemplo (42): O p r o g r a m a d e m o n s t r a a u t i l i z a o d a c l a s s e string.


// string6.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s("universidade"); s.replace(7, 5, "os"); // 7 - posio inicial | 5 - nmero de caracteres que sero trocados cout << "String modificada: " << s << endl; // universos }

Programa exemplo (43): O p r o g r a m a d e m o n s t r a a u t i l i z a o d a c l a s s e string.


// string7.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s("Couve"), r("-flor"), t; t = s + r; cout << t << endl;

// t igual a t()

50

Programa exemplo (44) : O programa demonstra o clculo do dia juliano , ou seja, o usurio informa via teclado dia, ms e ano e o programa informa o dia da semana (segunda, tera, quarta, etc) correspondente a esta data. Observao: Sem a utilizao de objetos.
// dia.cpp #include <iostream> using namespace std; // ---------------------------- Programa Principal int main(void) { int dia, mes, ano; int a, b, c; long int d, e, dj; char tecla; double resp; do { do {

cout << "Dia [1..31]: "; cin >> dia; } while (dia < 1 or dia > 31); do { cout << "Mes [1..12]: "; cin >> mes; } while (mes < 1 or mes > 12); do { cout << "Ano [1900..2999]: "; cin >> ano; } while (ano < 1900 or ano > 2999); cout << "Data: " << dia << " de "; switch (mes) { case 1: cout << "Janeiro"; break; case 2: cout << "Fevereiro"; break; case 3: cout << "Maro"; break; case 4: cout << "Abril"; break; case 5: cout << "Maio"; break; case 6: cout << "Junho"; break; case 7: cout << "Julho"; break; case 8: cout << "Agosto"; break; case 9: cout << "Setembro"; break;

// or igual a ||

51

case 10: cout << "Outubro"; break; case 11: cout << "Novembro"; break; case 12: cout << "Dezembro"; break; } cout << " de " << ano; if (mes < 3) { ano--; mes += 12; } a = ano / 100; b = a / 4; c = 2 - a + b; resp = 365.25 * (ano + 4716); d = (long int) resp; resp = 30.6001 * (mes + 1); e = (long int) resp; dj = d + e + dia + c - 1524; int resto = dj % 7; cout << "\nDia da Semana: "; switch (resto) { case 0: cout << "SEGUNDA-FEIRA"; break; case 1: cout << "TERA-FEIRA"; break; case 2: cout << "QUARTA-FEIRA"; break; case 3: cout << "QUINTA-FEIRA"; break; case 4: cout << "SEXTA-FEIRA"; break; case 5: cout << "SBADO"; break; case 6: cout << "DOMINGO"; break; } do { cout << "\nNovo Clculo [S/n]?"; cin >> tecla; } while (not strchr("SsNn", tecla)); } while (strchr("Ss", tecla)); }

Programa exemplo (45): O programa demonstra o clculo do dia juliano, ou seja, o usurio informa via teclado dia, ms e ano e o programa informa o dia da semana (segunda, tera, quarta, etc) correspondente a data informada. Observao: Com a utilizao de um objeto Data.
// juliano.cpp // --------------------------- Prototypes #include <iostream>

52

using namespace std; // --------------------------- Classe: Data class Data { int dia, mes, ano; public: void Le_Atributos(void); void Exibe_Data_Extenso(void); int Calcula_Dia_Juliano(void); void Exibe_Dia_Semana(int resto); }; // --------------------------- Programa Principal int main(void) { Data data; char tecla; do { data.Le_Atributos(); data.Exibe_Data_Extenso(); int resto = data.Calcula_Dia_Juliano(); data.Exibe_Dia_Semana(resto); cout << "\nNovo Clculo [S/n]?"; do { cin >> tecla; } while (not strchr("SsNn", tecla)); } while (strchr("Ss", tecla));

// definio do objeto data

// -------------------------------- Mtodo: Le_Atributos void Data :: Le_Atributos(void) { do { cout << "Dia [1..31]: "; cin >> dia; } while (dia < 1 or dia > 31); do { cout << "Mes [1..12]: "; cin >> mes; } while (mes < 1 or mes > 12); do { cout << "Ano [1900..2999]: "; cin >> ano; } while (ano < 1900 or ano > 2999); } // -------------------------------- Mtodo: Calcula_Dia_Juliano int Data :: Calcula_Dia_Juliano(void) { int a, b, c; long int d, e, dj; int dd = dia, mm = mes, aa = ano; double resp;

53

if (mm < 3) { aa--; mm += 12; } a = aa / 100; b = a / 4; c = 2 - a + b; resp = 365.25 * (aa + 4716); d = (long int) resp; resp = 30.6001 * (mm + 1); e = (long int) resp; dj = d + e + dd + c - 1524; int resto = dj % 7; return(resto); } // -------------------------------- Mtodo: Exibe_Dia_Semana void Data :: Exibe_Dia_Semana(int resto) { cout << "\nDia da Semana: "; switch (resto) { case 0: cout << "SEGUNDA-FEIRA"; break; case 1: cout << "TERA-FEIRA"; break; case 2: cout << "QUARTA-FEIRA"; break; case 3: cout << "QUINTA-FEIRA"; break; case 4: cout << "SEXTA-FEIRA"; break; case 5: cout << "SBADO"; break; case 6: cout << "DOMINGO"; break; } } // -------------------------------- Mtodo: Exibe_Data_Extenso void Data :: Exibe_Data_Extenso(void) { cout << "Data: " << dia << " de "; switch (mes) { case 1: cout << "Janeiro"; break; case 2: cout << "Fevereiro"; break; case 3: cout << "Maro"; break; case 4: cout << "Abril"; break; case 5: cout << "Maio"; break; case 6: cout << "Junho";

54

break; case 7: cout << "Julho"; break; case 8: cout << "Agosto"; break; case 9: cout << "Setembro"; break; case 10: cout << "Outubro"; break; case 11: cout << "Novembro"; break; case 12: cout << "Dezembro"; break; } cout << " de " << ano; }

Mtodo cin.getline (leitura de uma string)


O mtodo cin.getline permite a entrada de uma string qualquer via teclado.

Prottipo: void cin.getline (char *s, int n);


Onde: s a string declarada como char *s ou char s[] n o nmero de caracteres Programa exemplo (46): O programa demonstra a entrada de uma string via teclado atravs do mtodo cin.getline .
// string.cpp #include <iostream> using namespace std; int main(void) { char s[81]; cout << "Digite seu nome: "; cin.getline(s,80); cout << s << "\nTotal de caracteres: " << strlen(s) << endl; cout << "Tecle <ENTER> para encerrar"; cin.get(); }

Programa exemplo (47): O programa permite a entrada de strings (nomes, mximo 50) at que o usurio digite apenas enter e aps ordena e imprime na tela os nomes em ordem alfabtica.
// sort1.cpp #include <iostream>

55

using namespace std; const int tam= 50; int main(void) { char nome[tam][41], temp[41]; bool trocou; int n = -1; do { n++; cout << "Nome: "; cin.getline(nome[n],40); } while (strcmp(nome[n],"") not_eq 0 and n < tam); if (strcmp(nome[n],"") == 0) n--; int j = n; cout << "Nomes digitados\n"; for (int i = 0;i <= n;i++) cout << nome[i] << endl; do { trocou = false; for (int i = 0;i < j;i++) if (strcmp(nome[i],nome[i+1]) > 0) { strcpy(temp,nome[i]); strcpy(nome[i],nome[i+1]); strcpy(nome[i+1],temp); trocou = true; } j--; } while (trocou); cout << "Nomes Ordenados\n"; for (int i = 0;i <= n;i++) cout << nome[i] << endl; }

// and igual a &&

Programa exemplo (48): O programa permite a entrada de strings (nomes, mximo 50) at que o usurio digite apenas enter e aps ordena e imprime os nomes em ordem alfabtica. Este programa possui uma funo que faz a troca de duas strings.
// sort2.cpp #include <iostream> using namespace std; void troca(char *s, char *r) { int n, ns, nr; ns = strlen(s); nr = strlen(r); ns > nr ? n = ns : n = nr; char *t = (char *) new char * [n+1]; strcpy(t,s); strcpy(s,r);

56

strcpy(r,t); delete t; } const int tam = 50; int main(void) { char nome[tam][41], temp[41]; bool trocou; int n = -1; do { n++; cout << "Nome: "; cin.getline(nome[n],40); } while (strcmp(nome[n],"") not_eq 0 and n < tam); if (strcmp(nome[n],"") == 0) n--; int j = n; cout << "Nomes digitados\n"; for (int i = 0;i <= n;i++) cout << nome[i] << endl; do { trocou = false; for (int i = 0;i < j;i++) if (strcmp(nome[i],nome[i+1]) > 0) { troca(nome[i],nome[i+1]); trocou = true; } j--; } while (trocou); cout << "Nomes Ordenados\n"; for (int i = 0;i <= n;i++) cout << nome[i] << endl; }

2. Classes e Objetos
2.1 Classes
A declarao de uma classe ( class) define um novo tipo de dado que mistura cdigo (funes ou mtodos ) e dados ( variveis ou atributos ) e utilizado para declarar objetos.

Como declarar uma classe:


class nome_da_classe { // atributos e mtodos privadas; // se for suprimido o especificador de acesso ele por default: private especificador_de_acesso:

57

//atributos e mtodos; . . . especificador_de_acesso: // atributos e mtodos; } lista_de_objetos;

Observaes:

a) A lista_de_objeto s opcional, ou seja, os objetos desta classe podem ser declarados a qualquer momento, conforme exemplo abaixo: nome_da_classe lista_de_objetos; b) O especificador de acesso padro private, ou seja, se no for definido nenhum especificador, por default atributos e mtodos so private.
Programa exemplo (49): O programa exibe um boneco na tela. O programa possui uma classe chamada Boneco.
// boneco.cpp #include <iostream> using namespace std; // ---------------------------------------------- Classe: Boneco class Boneco { private: int n; private: void Cabeca(void); void Corpo(void); void Braco_Esquerdo(void); void Braco_Direito(void); void Perna_Esquerda(void); void Perna_Direita(void); public: void Seta_Atributo(int x) { n = x; } void Incrementa_Atributo(void) { n++; } void Desenha_Boneco(void); };

58

// ---------------------------------------------- Programa Principal int main(void) { Boneco boneco; boneco.Seta_Atributo(1); for (int i = 1;i <= 6;i++) { boneco.Desenha_Boneco(); boneco.Incrementa_Atributo(); cin.get(); } }

Programa exemplo (50) : O programa faz o boneco andar na tela. O programa possui uma classe chamada Boneco.
// anda.cpp #include <iostream> using namespace std; // ---------------------------------------------- Classe: Boneco class Boneco { private: int c; public: void Seta_Atributo(int col) { c = col; } void Incrementa_Atributo(void); void Desenha_Boneco(void); void Anda_Boneco(void); }; // ---------------------------------------------- Programa Principal int main(void) { Boneco boneco; boneco.Seta_Atributo(10); boneco.Desenha_Boneco(); for (int i = 1;i <= 70;i++) { boneco.Anda_Boneco(); boneco.Incrementa_Atributo(); system("clear"); } } // ---------------------------------------------- Boneco: Desenha_Boneco void Boneco :: Desenha_Boneco(void) { cout << " O" << endl; cout << "/|\\" << endl;

59

cout << " |" << endl; cout << "/ \\" << endl; } // ---------------------------------------------- Boneco: Anda_Boneco void Boneco :: Anda_Boneco(void) { char s[256] = ""; int i = 0; for (int col = 1;col <= c;col++) { s[i++] = ' '; s[i] = (char) NULL; } cout << s << " O" << endl; cout << s << "/|\\" << endl; cout << s << " |" << endl; cout << s << "/ \\" << endl; } // ---------------------------------------------- Boneco: Incrementa_Atributo void Boneco :: Incrementa_Atributo(void) { c++; }

Especificadores de acesso:

public

(pblico): Todos os elementos da classe base (atributos ou mtodos) so pblicos na classe derivada, ou seja, podem ser acessados por qualquer outro mtodo ou funo (funo main, por exemplo). (privado): Os elementos (atributos e mtodos) s podem ser acessados pelos mtodos (funes) que fazem parte da classe. necessrio para que os mtodos de uma classe derivada possa acessar os atributos e mtodos de uma classe base.

private

protected (protegido): necessrio apenas quando utiliza-se herana, ou seja,

Observao: A classe base q u a l q u e r c l a s s e d e f i n i d a e m C + + . C l a s s e derivada herda todas as caractersticas (atributos e mtodos pblicos e protegidos) da classe base. Apenas atributos e mtodos privados no so herdados pela classe derivada. Os mtodos declarados dentro de uma classe so chamados de mtodos membros e podem acessar qualquer atributo ou mtodo da classe, mesmo os privados a classe. Os atributos declaradas dentro de uma classe so chamados atributos membros. Podem ser privados, pblicos ou protegidos (quando usados em herana).

Restries na declarao de uma classe : 60

1) Nenhum atributo pode ser inicializado dentro da declarao da classe; 2) No pode-se referenciar um objeto de uma classe ainda no declarada; 3) Nenhum membro pode ser declarado como extern (tipo externo) ou register (registrador). Como acessar atributos pblicos : os atributos pblicos de uma classe so acessados da mesma forma que os campos de uma estrutura, ou seja, com ponto (.) ou seta (->), se o objeto for um ponteiro. Programa exemplo (51): O programa possui atributos pblicos que so acessados pela funo main. O programa pergunta o seu nome e exibe na tela o nmero de caracteres do nome.
// public.cpp #include <iostream> using namespace std; class Pessoa { public: char nome[81]; int n; }; int main(void) { Pessoa pessoa; cout << "Qual o seu nome: "; cin.getline(pessoa.nome,80); pessoa.n = strlen(pessoa.nome); cout << "Nmero de caracteres: " << pessoa.n << endl; }

Programa exemplo (52): O programa possui atributos pblicos que so acessados pela funo main. O programa pergunta o seu nome e exibe na tela o nmero de caracteres deste nome utilizando alocao dinmica (ponteiros).
// public2.cpp #include <iostream> using namespace std; class Pessoa { public: char nome[81]; int n; };

61

int main(void) { Pessoa *pessoa; pessoa = new Pessoa; cout << "Qual o seu nome: "; cin.getline(pessoa->nome,80); pessoa->n = strlen(pessoa->nome); cout << "Nmero de caracteres: " << pessoa->n << endl; }

2.2 Funes friend (amigas)


possvel acessar atributos e mtodos privados ( private) de uma classe por funes no-membros da classe atravs da utilizao de funes amigas (friend). Uma funo amiga possui acesso a todos os atributos e mtodos privados (private) e protegidos ( protected ) de uma classe a qual ela amiga.

Como declarar uma funo amiga :


friend tipo_retorno nome_mtodo(lista_de_argumentos);
Programa exemplo (53) : O programa mostra a utilizao de uma funo amiga (friend).
// friend.cpp #include <iostream> using namespace std; class Calc { float a, b; public: void Inicializa_Atributos(float x, float y) { a = x; b = y; } friend float Div(Calc t); // observao: Div no membro da classe Calc }; int main(void) { Calc calc; calc.Inicializa_Atributos(3.0,4.0); cout << "Soma: " << Div(calc) << endl; } float Div(Calc t)

62

{ return(t.a / t.b); }

// pode acessar a e b pois uma funo amiga

Funes amigas ( friend) podem ser utilizadas em trs situaes: a) Podem ser teis quando se sobrecarrega certos tipos de operadores; b) Tornam a criao de certas funes de entrada e sada mais fceis; c) Podem ser utilizadas quando duas ou mais classes contm membros que esto interligados, ou necessitam testar os atributos de ambas.

2.3 Funes inline


Funes inline so pequenas funes (ou mtodos) que so expandidas na chamada da funo. Esta caracterstica aumenta o desempenho do programa (velocidade), pois no h chamada da funo, ou seja, no utilizada a pilha de retorno da funo e no so utilizados os registradores para armazenar o estado do programa, ocupando tempo e memria. Programa exemplo (54) : O p ro gram a m o s tra a utiliz ao d e um a f uno inline.
// inline.cpp #include <iostream> using namespace std; inline int maior(int x, int y) { return(x > y ? x : y); } inline int menor(int x, int y) { return(x < y ? x : y); } int main(void) { cout << "Maior: " << maior(5,6) << endl; cout << "Menor: " << menor(5,6) << endl; }

Programa exemplo (55): O programa mostra como o programa seria compilado pelo compilador.
// inline2.cpp #include <iostream> using namespace std;

63

int main(void) { cout << "Maior: " << (5 > 6 ? 5 : 6) << endl; cout << "Menor: " << (5 < 6 ? 5 : 6) << endl; }

Restries na utilizao do inline :


a) No pode conter nenhuma varivel esttica ( static int n = 0; ); b) No pode conter nenhum comando de repetio, switch ou goto; c) No pode ser recursiva; d) Declarao de vetores, matrizes e strings no so aceitas; e) Se a funo void no pode-se utilizar return.

2.4 Definindo funes inline dentro de uma classe


Pequenos mtodos quando escritos dentro de uma classe so considerados inline (no sendo necessrio colocar o inline, pois o mtodo automaticamente inline). Normalmente, o construtor pequeno e inserido dentro da classe.

2.5 Construtores parametrizados


Em C++ permitido passar argumentos (parmetros com valores iniciais) para construtores de classes (objetos). Isto evita que existam mtodos especficos para inicializar atributos. Isto necessrio, pois nenhum atributo de uma classe pode ser inicializado diretamente na declarao de uma classe. Programa exemplo (56): O programa possui uma classe: Boneco. A classe possui um construtor parametrizado.
// boneco.cpp #include <iostream> using namespace std; // ---------------------------------------------- Classe: Boneco class Boneco { private: int n; private: void Cabeca(void); void Bracos(void); void Corpo(void); void Pernas(void); public: Boneco(int x)

// construtor parametrizado

64

};

{ n = x; } void Desenha_Boneco(void);

// ---------------------------------------------- Programa Principal int main(void) { Boneco boneco(1); boneco.Desenha_Boneco(); } // ---------------------------------------------- Boneco: Cabeca void Boneco :: Cabeca(void) { cout << " O" << endl; } // ---------------------------------------------- Boneco: Bracos void Boneco :: Bracos(void) { cout << "/|\\" << endl; } // ---------------------------------------------- Boneco: Corpo void Boneco :: Corpo(void) { cout << " |" << endl; } // ---------------------------------------------- Boneco: Pernas void Boneco :: Pernas(void) { cout << "/ \\" << endl; } // ---------------------------------------------- Boneco: Desenha_Boneco void Boneco :: Desenha_Boneco(void) { Cabeca(); Bracos(); Corpo(); Pernas(); }

// construtor parametrizado

Programa exemplo (57): O programa demonstra a utilizao de uma classe de objetos chamada Arquivo . O programa permite criar, abrir, gravar, exibir , anexar e ordenar palavras em um arquivo binrio de palavras.
// Arquivo.cpp

65

#include <iostream> using namespace std; // ----------------------------------------------- Classe: Arquivo class Arquivo { FILE *fp; // lista de atributos char nome[81], palavra[31], tecla; bool aberto; // tipo lgico (boolean) void Erro(int erro); long int Tamanho_Arquivo(void); public: Arquivo(char *s); ~Arquivo(void); void Cria_Arquivo(void); void Abre_Arquivo(void); void Grava_Palavras(void); void Exibe_Palavras(void); void Insere_Palavras(void); void Consulta_Palavras(void); void Ordena_Palavras(void); }; // mtodos privados

// mtodos pblicos

// ----------------------------------------------- Programa Principal int main(void) { char nome[81], tecla; cout << "Nome do Arquivo de Palavras: "; cin.getline(nome,80); Arquivo arquivo(nome); // construtor parametrizado do { cout << "[1] - Cria o Arquivo" << endl; cout << "[2] - Abre o Arquivo" << endl; cout << "[3] - Grava primeiras Palavras" << endl; cout << "[4] - Exibe todas Palavras" << endl; cout << "[5] - Insere mais Palavras" << endl; cout << "[6] - Consulta Palavras" << endl; cout << "[7] - Ordena Palavras" << endl; cout << "[9] - Fim" << endl; do { cout << "Qual a alternativa: "; cin >> tecla; } while (not strchr("12345679",tecla)); switch (tecla) { case '1': arquivo.Cria_Arquivo(); break; case '2': arquivo.Abre_Arquivo(); break; case '3': arquivo.Grava_Palavras(); break; case '4': arquivo.Exibe_Palavras(); break; case '5': arquivo.Insere_Palavras();

66

break; case '6': arquivo.Consulta_Palavras(); break; case '7': arquivo.Ordena_Palavras(); break; } } while (tecla not_eq '9'); } // ----------------------------------------------- Construtor parametrizado Arquivo :: Arquivo(char *s) { strcpy(nome,s); aberto = false; } // ----------------------------------------------- Destrutor Arquivo :: ~Arquivo(void) { if (aberto) fclose(fp); } // ----------------------------------------------- Cria_Arquivo void Arquivo :: Cria_Arquivo(void) { cout << "Arquivo: " << nome << endl; fp = fopen(nome,"r+b"); if (fp not_eq NULL) { fclose(fp); Erro(1); } else { cout << "Ok, Arquivo Criado" << endl; fp = fopen(nome,"w+b"); if (fp == NULL) Erro(2); else aberto = true; } } // ----------------------------------------------- Abre_Arquivo void Arquivo :: Abre_Arquivo(void) { cout << "Arquivo: " << nome << endl; fp = fopen(nome,"r+b"); if (fp == NULL) Erro(3); cout << "Ok, Arquivo Aberto" << endl; aberto = true; } // ----------------------------------------------- Erro

67

void Arquivo :: Erro(int erro) { switch (erro) { case 1: cout << "ERRO FATAL: Arquivo Existe" << endl; break; case 2: cout << "ERRO FATAL: Problema no Disco" << endl; break; case 3: cout << "ERRO FATAL: Arquivo Inexistente" << endl; break; } exit(0); } // ----------------------------------------------- Tamanho_Arquivo long int Arquivo :: Tamanho_Arquivo(void) { long int n = 0; if (aberto) { rewind(fp); fread(palavra,sizeof(palavra),1,fp); while (not feof(fp)) { n++; fread(palavra,sizeof(palavra),1,fp); } } return(n); } // ----------------------------------------------- Grava_Palavra void Arquivo :: Grava_Palavras(void) { if (aberto) { rewind(fp); do { cout << "Palavra: "; cin >> palavra; fwrite(palavra,sizeof(palavra),1,fp); do { cout << "Continua [S/n]? "; cin >> tecla; } while (not strchr("SsNn",tecla)); } while (strchr("Ss",tecla)); } else cout << "ERRO: [1] Criar ou [2] Abrir um arquivo ... " << endl; } // ----------------------------------------------- Exibe_Palavras void Arquivo :: Exibe_Palavras(void) { if (aberto)

68

{ rewind(fp); fread(palavra,sizeof(palavra),1,fp); while (not feof(fp)) { cout << "Palavras: " << palavra << endl; fread(palavra,sizeof(palavra),1,fp); } } else cout << "ERRO: [1] Criar ou [2] Abrir um Arquivo ... " << endl; } // ----------------------------------------------- Insere_Palavras void Arquivo :: Insere_Palavras(void) { if (aberto) { fseek(fp,0,SEEK_END); do { cout << "Palavra: "; cin >> palavra; fwrite(palavra,sizeof(palavra),1,fp); do { cout << "Continua [S/n]? "; cin >> tecla; } while (not strchr("SsNn",tecla)); } while (strchr("Ss",tecla)); } else cout << "ERRO: [1] Criar ou [2] Abrir um arquivo ... " << endl; } // ----------------------------------------------- Consulta_Palavras void Arquivo :: Consulta_Palavras(void) { long int n, posicao; int pos; char tecla; if (aberto) { n = Tamanho_Arquivo(); do { do { cout << "Posicao [0.." << n << "]: "; cin >> pos; } while (pos < 0 or pos > n); posicao = pos * sizeof(palavra); fseek(fp,posicao,SEEK_SET); fread(palavra,sizeof(palavra),1,fp); cout << "PALAVRA: " << palavra << endl; do { cout << "Continua [S/n]? "; cin >> tecla; } while (not strchr("SsNn",tecla)); } while (strchr("Ss",tecla)); }

69

else cout << "ERRO: [1] Criar ou [2] Abrir um arquivo ... " << endl; } // ----------------------------------------------- Ordena_Palavras void Arquivo :: Ordena_Palavras(void) { long int n; int i = 0,j; char temp[31]; if (aberto) { n = Tamanho_Arquivo(); rewind(fp); char vetor[n][31]; fread(&vetor[i],sizeof(vetor[i]),1,fp); while (not feof(fp)) { i++; fread(&vetor[i],sizeof(vetor[i]),1,fp); } for (i = 0;i < n-1;i++) for (j = i + 1;j < n;j++) if (strcmp(vetor[i],vetor[j]) > 0) { strcpy(temp,vetor[i]); strcpy(vetor[i],vetor[j]); strcpy(vetor[j],temp); } rewind(fp); for (i = 0;i < n;i++) fwrite(&vetor[i],sizeof(vetor[i]),1,fp); cout << "Ok, Arquivo Ordenado ..." << endl; } else cout << "ERRO: [1] Criar ou [2] Abrir um Arquivo ... " << endl; }

Lembrete: A vantagem em utilizar construtores parametrizados evitar a criao de mtodos que inicializem atributos, tipo: Inicializa_Atributos . Observao: Como foi visto anteriormente, C++ possui um tipo de dado chamado bool (booleam ) . utiliz ad o com o flag, ou seja, aceita apenas dois valores: true (verdadeiro) ou false (falso). As palavras true e false so pr-definidas.

2.6 Quando construtores e destrutores so executados


A execuo do construtor de um objeto depende de sua declarao, ou seja, se global ou local. O construtor de um objeto local executado quando a sua declarao encontrada. Quando mais de um objeto declarado com a mesma classe, seus construtores so executados da esquerda para a direita. Os destrutores so executados na ordem inversa

70

dos construtores. Construtores de objetos globais so executados antes da funo main. Destrutores globais so executados depois do main em ordem inversa aos construtores. Programa exemplo (58): O programa demonstra a execuo destrutores.
// construtor.cpp #include <iostream> using namespace std; class Classe { public: int quem; Classe(int id); ~Classe(void); } global1(1), global2(2); Classe :: Classe(int id) { cout << "Construtor: " << id << endl; quem = id; } Classe :: ~Classe(void) { cout << "Destrutor: " << quem << endl; } int main(void) { Classe local1(3); cout << "main" << endl; Classe local2(4); } Resultado do programa : Construtor: 1 Construtor: 2 Construtor: 3 main Construtor: 4 Destrutor: 4 Destrutor: 3 Destrutor: 2 Destrutor: 1

dos construtores e

// objetos globais

// objeto local // objeto local

2.7 Operador resoluo de escopo


71

O operador de resoluo de escopo :: pode ser utilizado em duas situaes: (a) Declarar um mtodo fora de uma classe; (b) Acessar uma varivel fora do seu escopo, ou seja, acessar uma varivel global dentro de um mtodo ou funo que possui uma varivel local com o mesmo nome de uma varivel global. Programa exemplo (59): O programa demonstra a utilizao do operador de resoluo de escopo.
// escopo.cpp #include <iostream> using namespace std; int var = 5; int main(void) { int var = 4; // varivel global

// varivel local

cout << "Local: " << var << endl; cout << "Global: " << :: var << endl; }

// operador de resoluo de escopo

2.8 Passando objetos para funes


Em C++ possvel passar objetos (passagem de argumentos por valor ) como parmetros de funes externas as classes. Programa exemplo (60): O programa mostra a passagem de um objeto via parmetro para uma funo externa.
// objeto.cpp #include <iostream> using namespace std; // ----------------------------------------------- Classe class Classe { int i; public: Classe (int n); // construtor void Inicializa_Atributos(int n); int Retorna_Atributo(void); }; // ----------------------------------------------- funo externa

72

void Exibe(Classe objeto) // parmetro da funo um objeto { objeto.Inicializa_Atributos(2); cout << "Atributo: " << objeto.Retorna_Atributo() << endl; } // ----------------------------------------------- Programa Principal int main(void) { Classe objeto(1); Exibe(objeto); cout << "Atributo: " << objeto.Retorna_Atributo() << endl; } // ----------------------------------------------- construtor Classe :: Classe (int n) { i = n; } // ----------------------------------------------- Inicializa_Atributos void Classe :: Inicializa_Atributos(int n) { i = n; } // ----------------------------------------------- Retorna_Atributo int Classe :: Retorna_Atributo(void) { return(i); }

2.9 Retornando objetos


Em C++ possvel que uma funo qualquer retorne um objeto. Programa exemplo (61): O programa demonstra o retorno de um objeto atravs de uma funo externa.
// retorno.cpp #include <iostream> using namespace std; // ----------------------------------------------- Classe class Classe { int i;

73

public: void Inicializa_Atributos(int n); int Retorna_Atributo(void); }; // ----------------------------------------------- funo externa Classe Exibe(void) // funo retorna um objeto { Classe objeto; objeto.Inicializa_Atributos(2); return(objeto); }

// retorno do objeto

// ----------------------------------------------- Programa Principal int main(void) { Classe objeto; objeto = Exibe(); cout << "Atributo: " << objeto.Retorna_Atributo() << endl; } // ----------------------------------------------- Inicializa_Atributos void Classe :: Inicializa_Atributos(int n) { i = n; } // ----------------------------------------------- Retorna_Atributo int Classe :: Retorna_Atributo(void) { return(i); }

2.10 Atribuio de objetos


C++ permite atribuio de objetos, ou seja, um objeto ter os mesmos valores de outro objeto. Programa exemplo (62): O programa demonstra uma atribuio entre dois objetos.
// atrib.cpp #include <iostream> using namespace std; // ----------------------------------------------- Classe class Classe { int i;

74

public: void Inicializa_Atributos(int n); int Retorna_Atributo(void); }; // ----------------------------------------------- Programa Principal int main(void) { Classe objeto1, objeto2; objeto1.Inicializa_Atributos(5); cout << "Atributo Objeto 1: " << objeto1.Retorna_Atributo() << endl; objeto2 = objeto1; // atribuio de objetos cout << "Atributo Objeto 2: " << objeto2.Retorna_Atributo() << endl; } // ----------------------------------------------- Inicializa_Atributos void Classe :: Inicializa_Atributos(int n) { i = n; } // ----------------------------------------------- Retorna_Atributo int Classe :: Retorna_Atributo(void) { return(i); }

3. Array, Ponteiros e Referncias


3.1 Array de objetos
Em C++ possvel declarar vetores de objetos. Programa exemplo (63) : O programa demonstra um vetor de objetos.
// vetor.cpp
#include <iostream> using namespace std; const int MAX = 3; // ----------------------------------------------- Classe class Classe { int i; public: void Inicializa_Atributos(int n); int Retorna_Atributo(void);

75

}; // ----------------------------------------------- Programa Principal int main(void) { Classe objeto[MAX]; int i;

// vetor de trs objetos

for (i = 0;i < MAX;i++) { objeto[i].Inicializa_Atributos(i+1); cout << "Atributo Objeto [" << i << "]: " << objeto[i].Retorna_Atributo() << endl; } } // ----------------------------------------------- Inicializa_Atributos void Classe :: Inicializa_Atributos(int n) { i = n; } // ----------------------------------------------- Retorna_Atributo int Classe :: Retorna_Atributo(void) { return(i); }

Observao: Pode-se inicializar cada atributo do vetor na declarao do vetor de objetos. Programa exemplo (64): O programa demonstra um vetor de objetos sendo inicializado na declarao.
// vetor2.cpp #include <iostream> using namespace std; const int MAX = 3; // ----------------------------------------------- Classe class Classe { int i; public: Classe(int n) { i = n; } int Retorna_Atributo(void); };

// construtor inicializa atributos

// ----------------------------------------------- Programa Principal int main(void) {

76

Classe objeto[MAX] = {1,2,3}; int i;

// vetor de objetos inicializado

for (i = 0;i < MAX;i++) cout << "Atributo Objeto [" << i << "]: " << objeto[i].Retorna_Atributo() << endl; } // ----------------------------------------------- Retorna_Atributo int Classe :: Retorna_Atributo(void) { return(i); }

3.2 Ponteiros de Objetos


C++ permite tambm a utilizao de ponteiros para objetos. Programa exemplo (65): O programa demonstra a utilizao de um ponteiro para um objeto.
// pointer1.cpp #include <iostream> using namespace std; // ----------------------------------------------- Classe class Classe { int i; public: Classe (int n) { i = n; } int Retorna_Atributo(void); }; // ----------------------------------------------- Programa Principal int main(void) { Classe objeto(10), *pobj; pobj = &objeto; cout << "Atributo Objeto: " << pobj->Retorna_Atributo() << endl; cout << "Atributo: " << (*pobj).Retorna_Atributo() << endl; } // ----------------------------------------------- Retorna_Atributo int Classe :: Retorna_Atributo(void) { return(i); }

C++ permite ainda aritmtica de ponteiros. O programa 66 mostra um exemplo de

77

aritmtica de ponteiros para objetos. Programa exemplo (66): O programa demonstra aritmtica de ponteiros para objetos.
// pointer2.cpp #include <iostream> using namespace std; const int MAX = 3; // ----------------------------------------------- Classe class Classe { int i; public:

};

Classe (int n) { i = n; } int Retorna_Atributo(void);

// ----------------------------------------------- Programa Principal int main(void) { Classe *pobj, objeto[MAX] = {10, 20, 30}; int i; pobj = &objeto[0]; for (i = 0;i < MAX;i++) { cout << "Atributo Objeto: " << pobj->Retorna_Atributo() << endl; pobj++; } } // ----------------------------------------------- Retorna_Atributo int Classe :: Retorna_Atributo(void) { return(i); }

Programa exemplo (67): O programa demonstra acesso a um atributo de um objeto atravs de um ponteiro para objeto.
// pointer3.cpp #include <iostream> using namespace std; // ----------------------------------------------- Classe class Classe {

78

public: int i; // atributo pblico

Classe (int n) { i = n; } int Retorna_Atributo(void); }; // ----------------------------------------------- Programa Principal int main(void) { Classe objeto(100); int *pobj; pobj = &objeto.i; // ponteiro acessa atributo pblico do objeto cout << "Atributo Objeto: " << *pobj << endl; } // ----------------------------------------------- Retorna_Atributo int Classe :: Retorna_Atributo(void) { return(i); }

3.3 O Ponteiro this


Quando um mtodo qualquer chamado, passado automaticamente um argumento que um ponteiro para o objeto que gerou a chamada. Este ponteiro chamado this, ou seja, o ponteiro this aponta para o objeto que chamou o mtodo. Programa exemplo (68) : O programa demonstra a utilizao do ponteiro this.
// this.cpp #include <iostream> using namespace std; // ----------------------------------------------- Classe class Classe { int x; public: Classe Exibe(void) { this->x = 2; return(* this); } int Retorna_Atributo(void) { return(x); } };

79

// ----------------------------------------------- Programa Principal int main(void) { Classe objeto, objeto_temp; objeto_temp = objeto.Exibe(); cout << "Atributo: " << objeto_temp.Retorna_Atributo() << endl; }

Programa exemplo (69) : O programa demonstra a utilizao do ponteiro this.


// this.cpp #include <iostream> using namespace std; // ----------------------------------------------- Classe class Classe { int x,y; public: Classe Inicializa_Atributos(int tx, int ty) { this->x = tx; this->y = ty; return(* this); } void Retorna_Atributos(int &a, int &b) { a = x; b = y; } void Incrementa_Atributos(int n) { x = x + n; y = y + n; } }; int main(void) { Classe objeto, temp; int a, b; objeto = objeto.Inicializa_Atributos(2, 3); objeto.Retorna_Atributos(a, b); cout << "a = " << a << endl; cout << "b = " << b << endl; temp = objeto; temp.Incrementa_Atributos(7); temp.Retorna_Atributos(a, b); cout << "a = " << a << endl; cout << "b = " << b << endl; }

// referncias

80

Observao: O ponteiro this muito importante quando operadores so sobrecarregados e podem auxiliar no gerenciamento de alguns tipos de listas encadeadas. Restries: Funes amigas ( friend) no so membros de uma classe, portanto, no recebem ponteiro this. Mtodos estticos (sem retorno) tambm no possuem ponteiro this.

3.4 Referncias
C++ possui uma caracterstica relativa a ponteiros chamada referncia, onde o operador & significa referncia a . Uma referncia um ponteiro implcito que no alocado na memria, ou seja, no ocupa espao de memria.

int& x = y;
Na declarao acima, a varivel x possui uma expresso de inicializao int& x = y; desta forma a varivel de referncia x est vinculada localizao de memria de y, ou seja, qualquer modificao na varivel y afeta diretamente a varivel x.

Forma geral:
tipo& nome_da_varivel = expresso_de_inicializao;

Restries ao uso de referncias : No possvel:


1) 2) 3) 4) 5) 6) Referenciar outra referncia; Obter o endereo de uma referncia; Criar arrays (vetores) de referncias; Ter um ponteiro para uma referncia; Referenciar campos de bits; sempre necessrio inicializar uma referncia na declarao da referncia, a no ser que seja membro de uma classe, parmetro formal de uma funo ou retorno de uma funo.

3.4.1 Parmetros referenciados


Uma referncia permite criar uma nova forma de fazer passagem de parmetros por referncia sem o uso de ponteiros. Com o uso de referncias, no lugar de ponteiros, no necessrio acessar o contedo do ponteiro (*p), ou seja, pode-se usar apenas o nome da varivel de referncia. Programa exemplo (70) : O programa demonstra a utilizao da passagem de parmetros utilizando-se referncia e ponteiros .

81

// troca.cpp #include <iostream> using namespace std; void Troca(int& a, int& b) { int temp; temp = a; a = b; b = temp; } void Troca(int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp; } int main(void) { int x = 3, y = 4; cout << "x = " << x << " - y = " << y << endl; Troca(x, y); cout << "x = " << x << " - y = " << y << endl; Troca(&x, &y); cout << "x = " << x << " - y = " << y << endl; } // utilizando ponteiros // utilizando referncias

3.4.2 Passando referncias a objetos


Quando um objeto passado como argumento para uma funo, uma cpia deste objeto criada. Neste momento, o construtor deste novo objeto no executado, mas quando a funo termina, o destrutor chamado. Se o objeto no precisa ser destrudo, o objeto deve ser passado utilizando-se uma referncia a (&) , pois neste caso, no criada uma cpia do objeto passado para a funo. Programa exemplo (71) : O programa demonstra a utilizao da passagem de parmetros utilizando-se referncia a .
// ref.cpp #include <iostream> using namespace std; class Classe {

82

int id; public: int i; Classe(int num); ~Classe(void); void Negativo(Classe &obj) { obj.i = -obj.i; } }; int main(void) { Classe obj(1); obj.i = 10; obj.Negativo(obj); cout << obj.i << endl; } Classe :: Classe(int num) { cout << "Construindo: " << num << endl; id = num; } Classe :: ~Classe(void) { cout << "Destruindo: " << id << endl; }

// experimente sem o &

3.4.3 Retornando referncias


Uma funo pode retornar uma referncia, possibilitando a utilizao da chamada da funo esquerda de uma atribuio. Programa exemplo (72): O programa demonstra a utilizao do retorno de uma funo atravs de uma referncia .
// return.cpp #include <iostream> using namespace std; char &troca(int i); char str[20] = "Paulo"; int main(void) { cout << str << endl; troca(4) = 'a'; cout << str << endl; } char &troca(int i) { return(str[i]);

83

3.5 Operadores C++ para alocao dinmica


C++ possui dois operadores que permitem alocar memria dinamicamente: new e delete. O o p e r a d o r new permite a alocao de uma poro de memria RAM (Random Access Memory Memria de Acesso Aleatrio) e retorna o endereo de memria desta rea alocada. Se no houver memria suficiente livre para tal, o ponteiro recebe um NULL. O o p e r a d o r delete libera a rea de memria alocada pelo operador new, para que esta rea possa ser utilizada novamente. C++ permite ainda, por questo de compatibilidade, a utilizao das funes padres do C que permitam alocar memria dinamicamente: malloc, calloc e free.

Como declarar um ponteiro:


tipo_base *nome_ponteiro;

Exemplos :
char *s; int *x; Classe *obj; float *f;

Como alocar um ponteiro:


nome_ponteiro = new tipo_base; nome_ponteiro = new (tipo_base) nome_ponteiro = new tipo_base[nmero_de_elementos];

Exemplos :
p = new float; q = new (float); r = new float[7];

Como liberar um ponteiro:


delete nome_ponteiro ;
ou

delete [] nome_ponteiro ;

Observao: Pode-se declarar e alocar um ponteiro ao mesmo tempo.

84

int *i = new int; float *f = new (float); char *s = new char[7];

Programa exemplo (73): O programa demonstra a utilizao dos operadores new e delete para alocao dinmica em C++.
// ptr1.cpp #include <iostream> using namespace std; int main(void) { int *ptr;// declarao do ponteiro ptr = new int; if (ptr == NULL) { cout << "ERRO FATAL: Falta de Memria\n"; exit(EXIT_FAILURE); // pr-definido } *ptr = 1234; // incializa o ponteiro com o valor inteiro 1234 cout << "No endereo " << ptr << " existe o valor " << *ptr << endl; delete ptr; } Resultado do Programa : No endereo 0x804a008 existe o valor 1234

Forma geral de alocar arrays (vetores ou matrizes):


nome_ponteiro = new tipo_base [nmero_de_elementos][nmero_de_elementos][nmero_de_elementos];

Observao: Arrays no podem ser inicializadas. Programa exemplo (74) : O programa demonstra a indexao de um ponteiro de n elementos, ou seja, um array unidimensional (1D).
// ptr2.cpp #include <iostream> using namespace std; int main(void) { int *ptr; int n; cout << "n = "; cin >> n; ptr = new int[n];

// [n] aloca n elementos inteiros

85

if (ptr == NULL) { cout << "ERRO FATAL: Falta de Memria\n"; exit(EXIT_FAILURE); } for (int i = 0;i < n;i++) ptr[i] = i; // indexao do ponteiro for (int i = 0;i < n;i++) cout << "No endereo " << &ptr[i] << " existe o valor " << ptr[i] << endl; delete [] ptr; }

Programa exemplo (75): O programa demonstra uma forma alternativa de alocar e inicializar um ponteiro ao mesmo tempo.
// ptr3.cpp #include <iostream> using namespace std; int main(void) { int *ptr; ptr = new int (100); // 100 o valor inicial do ponteiro if (ptr == NULL) { cout << "ERRO FATAL: Falta de Memria\n"; exit(EXIT_FAILURE); } cout << "No endereo " << ptr << " existe o valor " << *ptr << endl; delete ptr; }

3.5.1 Alocando objetos


C++ permite a alocao de objetos, ou seja, ponteiros para objetos. O operador new aloca um ponteiro e retorna o endereo para o objeto. Quando o objeto alocado, seu construtor executado. Quando o objeto desalocado, o destrutor do objeto executado. Programa exemplo (76): O programa demonstra alocao de um objeto.
// pessoa1.cpp #include <iostream> using namespace std; class Pessoa { int idade; public: char nome[41]; void Inicializa_Atributos(char *s, int id);

86

int Calcula_Ano_Nascimento(int ano_atual); }; int main (void) { Pessoa *ptr; int ano_atual, ano_nascimento, idade; ptr = new Pessoa; if (not ptr) // !NULL verdadeiro { cout << "ERRO FATAL: Falta de Memria\n"; exit(EXIT_FAILURE); } cout << "Ano Atual: "; cin >> ano_atual; cout << "Idade: "; cin >> idade; ptr->Inicializa_Atributos("Paulo Roberto Gomes Luzzardi", idade); ano_nascimento = ptr->Calcula_Ano_Nascimento(ano_atual); cout << ptr->nome; cout << " nasceu em " << ano_nascimento << endl; delete ptr; } void Pessoa :: Inicializa_Atributos(char *s, int id) { strcpy(nome,s); idade = id; } int Pessoa :: Calcula_Ano_Nascimento(int ano_atual) { return(ano_atual - idade); } Resultado do programa : Ano Atual: 2006 <enter> Idade: 44 <enter> Paulo Roberto Gomes Luzzardi nasceu em 1962

Programa exemplo (77): O programa demonstra alocao de um objeto (Classe Pessoa possui construtor).
// pessoa2.cpp #include <iostream> using namespace std; class Pessoa { int idade; public: public:

char nome[41];

87

};

Pessoa(char *s, int id); int Calcula_Ano_Nascimento(int ano_atual);

int main (void) { Pessoa *ptr; int ano_atual, ano_nascimento; ptr = new Pessoa("Paulo Roberto Gomes Luzzardi", 44); if (not ptr) // !NULL verdadeiro { cout << "ERRO FATAL: Falta de Memria\n"; exit(EXIT_FAILURE); } cout << "Ano Atual: "; cin >> ano_atual; ano_nascimento = ptr->Calcula_Ano_Nascimento(ano_atual); cout << ptr->nome << " nasceu em " << ano_nascimento << endl; delete ptr; } Pessoa :: Pessoa (char *s, int id) { strcpy(nome,s); idade = id; } int Pessoa :: Calcula_Ano_Nascimento(int ano_atual) { return(ano_atual - idade); } Resultado do programa : Paulo Roberto Gomes Luzzardi nasceu em 1962 // inicializao dos atributos do objeto

Programa exemplo (78): O programa demonstra alocao de um objeto (Classe Pessoa possui construtor e destrutor).
// pessoa3.cpp #include <iostream> using namespace std; class Pessoa { int idade; public: char *nome; // ponteiro Pessoa(char *s, int id); ~Pessoa(void); int Calcula_Ano_Nascimento(int ano_atual); }; int main (void)

88

{ Pessoa *ptr; int ano_atual, ano_nascimento; ptr = new Pessoa("Paulo Roberto Gomes Luzzardi", 44); if (not ptr) // !NULL verdadeiro { cout << "ERRO FATAL: Falta de Memria\n"; exit(EXIT_FAILURE); } cout << "Ano Atual: "; cin >> ano_atual; ano_nascimento = ptr->Calcula_Ano_Nascimento(ano_atual); cout << ptr->nome << " nasceu em " << ano_nascimento << endl; delete ptr; } Pessoa :: Pessoa (char *s, int id) { int n = strlen(s); nome = new char [n+1]; if (not nome) { cout << "ERRO FATAL: Falta de Memria\n"; exit(EXIT_FAILURE); } strcpy(nome,s); idade = id; } Pessoa :: ~Pessoa(void) { delete nome; } // destrutor // desalocao do atributo nome // construtor // inicializao dos atributos do objeto

int Pessoa :: Calcula_Ano_Nascimento(int ano_atual) { return(ano_atual - idade); } Resultado do programa : Paulo Roberto Gomes Luzzardi nasceu em 1962

Programa exemplo (79): O programa demonstra alocao de um vetor de objetos (Classe Pessoa possui construtor e destrutor).
// pessoa4.cpp #include <iostream> using namespace std; const int N_ELementos = 3; class Pessoa {

89

int idade; public: char nome[81]; void Inicializa_Atributos(char *s, int id); int Calcula_Ano_Nascimento(int ano_atual);

};

int main (void) { Pessoa *ptr; int ano_atual, ano_nascimento[N_Elementos]; ptr = new Pessoa[N_Elementos]; // alocao do vetor de trs objetos if (not ptr) // !NULL verdadeiro { cout << "ERRO FATAL: Falta de Memria\n"; exit(EXIT_FAILURE); } ptr[0].Inicializa_Atributos("Paulo Roberto Gomes Luzzardi", 44); ptr[1].Inicializa_Atributos("Adriane Maria Machado de Freitas Luzzardi", 37); ptr[2].Inicializa_Atributos("Paola de Freitas Luzzardi", 7); cout << "Ano Atual: "; cin >> ano_atual; for (int i = 0;i < N_Elementos;i++) ano_nascimento[i] = ptr[i].Calcula_Ano_Nascimento(ano_atual); for (int i = 0;i < N_Elementos;i++) cout << ptr[i].nome << " nasceu em " << ano_nascimento[i] << endl; delete [] ptr; } void Pessoa :: Inicializa_Atributos (char *s, int id) { strcpy(nome,s); idade = id; } int Pessoa :: Calcula_Ano_Nascimento(int ano_atual) { return(ano_atual - idade); } Resultado do programa : Paulo Roberto Gomes Luzzardi nasceu em 1962 Adriane Maria Machado de Freitas Luzzardi nasceu em 1969 Paola de Freitas Luzzardi nasceu em 1999

3.5.2 Alocao de memria


Dependendo da verso do compilador, talvez seja necessrio, no momento da liberao da memria alocada ( delete ), especificar o nmero de elementos alocados pelo operador new. Algumas verses do compilador no verificam a quantidade de elementos alocados e desalocados, ou seja, tenha cuidado em alocar e liberar a mesma quantidade de elementos.

90

Exemplo:
Objeto *ptr; ptr = new Objeto[4]; ... delete [4]ptr;

4. Sobrecarga de Operadores e Funes


4.1 Sobrecarga de operadores
Em C++ alguns operadores (quase todos, com exceo destes: . :: ?: sizeof ) podem ser sobrecarregados da mesma forma que as funes podem ser. Quando um operador sobrecarregado, ele no perde suas caractersticas normais, por exemplo: se numa pilha os operadores '+' e '' forem sobrecarregados para '+' inserir na pilha ( push) e '' retirar da pilha ( pop), eles continuam somando e subtraindo, respectivamente, da mesma forma que antes, ou seja, a partir deste momento eles executam novas operaes ( push e pop). A sobrecarga de operadores realizada atravs de funes operadoras (operator ), as quais definem as operaes especficas relativas classe especificada. Estas funes podem ser membros ou no da classe que ter os operadores sobrecarregados. Funes no-membros da classe devem ser quase sempre funes amigas da classe.

4.2 Criando uma funo-operador membro


A forma geral para declarar uma funo operadora :

tipo_retorno nome_da_classe :: operator@(lista_de_parmetros) { corpo_da_funo; }


Onde: @ o operador que ser sobrecarregado. Quando um operador unrio sobrecarregado (-, ++, --), a lista de parmetros deve ser vazia ( void). Quando for binrio (+, -, *, /, %), deve possuir um parmetro. Programa exemplo (80): O programa demonstra a sobrecarga do operador '+' em um objeto Soma.
// soma.cpp #include <iostream> using namespace std;

91

class Soma { double valor; public: Soma

Soma(void) {};

// construtor necessrio para declarar um objeto temporrio

Soma (double val) { valor = val; } void Exibe(char *mensagem) { cout << mensagem << valor << endl; } Soma operator+(Soma t) { Soma temp; temp.valor = t.valor + valor; return(temp);

// operator+

} };

// -------------------------------------- Programa Principal int main(void) { Soma objeto1(1.23), objeto2(2.34), objeto3(0.0); objeto1.Exibe("Valor do Objeto 1: "); objeto2.Exibe("Valor do Objeto 2: "); objeto3.Exibe("Valor do Objeto 3: "); objeto3 = objeto1 + objeto2; // sobrecarga do operador '+' objeto3.Exibe("Soma dos Valores dos Objetos 1 e 2: "); }

Programa exemplo (81): O programa demonstra a sobrecarga dos operadores '+' e '-' em uma fila alocada em um vetor.
// fila.cpp // Sobrecarga dos operadores '+' e '-' em uma fila em vetor #include <iostream> #include <cctype> using namespace std; const int Tam = 5; typedef int TDados; // -------------------------------------- Definio da Classe Fila class Fila { TDados fila[Tam];

92

int inic,fim; public: void Cria_Fila(void); void operator+(TDados dado); void operator-(TDados *dado); TDados Consulta_Fila(void); void Exibe_Fila(void); // insere na fila // retira da fila

};

// -------------------------------------- Cria_Fila void Fila :: Cria_Fila(void) { inic = 0; fim = 0; } // -------------------------------------- operator+ void Fila :: operator+(TDados dado) { if (fim == Tam) { cout << "Erro: Fila Cheia" << endl; return; } fila[fim] = dado; fim++; } // -------------------------------------- operatorvoid Fila :: operator-(TDados *dado) { if (fim == 0) { cout << "Erro: Fila Vazia" << endl; return; } inic++; if (inic >= fim) fim = 0; *dado = fila[inic-1]; } // -------------------------------------- Consulta_Fila TDados Fila :: Consulta_Fila(void) { if (fim == 0) { cout << "Erro: Fila Vazia" << endl; return 0; } return(fila[inic]); } // -------------------------------------- Exibe_Fila

93

void Fila :: Exibe_Fila(void) { cout << "Fila: "; if (fim == 0) { cout << "VAZIA" << endl; return; } for (int i = inic;i < fim;i++) cout << fila[i] << " "; cout << endl; } // -------------------------------------- Programa Principal int main(void) { Fila fila; char tecla; TDados valor;

fila.Cria_Fila(); do { fila.Exibe_Fila(); cout << "[I]nclui, [E]xclui, [C]onsulta ou [F]im: "; do { tecla = toupper(getchar()); } while (not strchr("IECF", tecla)); switch (tecla) { case 'I': cout << "Valor: "; cin >> valor; fila+(valor); // Insere na Fila (operador +) break; case 'E': fila-(&valor); // Retira da Fila (operador -) if (valor not_eq 0) cout << "Valor Excludo da Fila: " << valor << endl; break; case 'C': valor = fila.Consulta_Fila(); if (valor not_eq 0) cout << "Valor Consultado: " << valor << endl; break; } } while (tecla not_eq 'F'); }

Observao: Note que nas chamadas dos operadores sobrecarregados, ambas possuem apenas um parmetro, pois os operadores '+' e '-' so operadores binrios.

Operadores Lgicos:
Alm dos operadores aritmticos e relacionais, o C++ possui os operadores lgicos e operadores bit bit. Observao: Todos os operadores do C padro podem ser utilizados em programas escritos em C++.

94

bit:

A seguir as prximas trs tabelas mostram os operadores lgicos, relacionais e bit

Operadores Lgicos: &&, || e !


C && || ! C++ and or not Ao true quando a condio_A e condio_B forem true true quando a condio_A ou condio_B forem true negao (no) inverte a condio

Operadores Relacionais : !=
C != C++ not_eq Ao diferente, ou seja, no igual

Operadores bit bit: &, &=, |, |=, ^, ^= e ~


C & &= | |= ^ ^= ~ C++ bitand and_eq bitor or_eq xor xor_eq compl Ao (e) true quando bit_A e bit_b forem true (1) and (1) (e igual) (ou) true quando bit_A ou bit_B forem true: (1) ou (0) / (0) ou (1) / (1) ou (1) |-> (0) ou (0) false (ou igual) (ou exclusivo) somente quando um dos bits for true: (1) ou (0) | (0) ou (1) (ou exclusivo igual) (complemento de um )

4.3 Sobrecarga friend

de

operadores

utilizando

uma

funo

Em C++ possvel sobrecarregar operadores em relao a uma classe amiga (friend). Lembre que uma funo amiga no possui o ponteiro this, pois ela no membro de uma classe base, ou seja, necessrio passar um ou dois parmetros para ela: (a) dois operandos se o operador for binrio (+, -, *, /) e (b) apenas um se o operador for unrio (++, --). Programa exemplo (82): O programa demonstra a sobrecarga do operador '+' atravs de uma funo amiga ( friend).
// local.cpp #include <iostream> using namespace std; class Local

95

{ int objeto; int latitude, longitude;

// identificao do objeto

public: Local(void) {}; Local(int obj, int la, int lo) { objeto = obj; latitude = la; longitude = lo; } void Exibe(void) { cout << "Objeto (" << objeto << "): Latitude: " << latitude << " -> Longitude: " << longitude << endl; } friend Local operator+(Local op1, Local op2); // funo amiga Local operator-(Local op2); Local operator=(Local op2); Local operator++(void); }; int main(void) { Local objeto1(1, 10, 20), objeto2(2, 30, 40), objeto3(3, 50, 60); ++objeto1; objeto1.Exibe(); objeto2.Exibe(); objeto2 = ++objeto1; objeto1.Exibe(); objeto2.Exibe(); objeto2 = objeto3; objeto2.Exibe(); } Local operator+(Local op1, Local op2) { Local tmp; tmp.latitude = op1.latitude + op2.latitude; tmp.longitude = op1.longitude + op2.longitude; return(tmp); } Local Local :: operator-(Local op2) { Local tmp; tmp.latitude = latitude - op2.latitude; tmp.longitude = longitude - op2.longitude; return(tmp); } Local Local :: operator=(Local op2) { latitude = op2.latitude; longitude = op2.longitude; return(*this); } // funo amiga (friend)

96

Local Local :: operator++(void) { (latitude)++; (longitude)++; return(*this); } Resultado do Programa : Objeto(1): Latitude: 11 -> Longitude: 21 Objeto(2): Latitude: 30 -> Longitude: 40 Objeto(1): Latitude: 12 -> Longitude: 22 Objeto(2): Latitude: 12 -> Longitude: 22 Objeto(2): Latitude: 50 -> Longitude: 60

Existem algumas restries quanto utilizao de funes amigas como operadores sobrecarregados: (a) Os operadores =, (), [] ou -> no podem ser sobrecarregados em funes amigas; (b) Com os operadores unrios ++ e --, os operandos devem ser referncias. Programa exemplo (83): O programa demonstra a sobrecarga dos operadores '++' e '--' atravs de funes amigas ( friend).
// local.cpp #include <iostream> using namespace std; class Local { int objeto; int latitude, longitude; public: Local(void) {}; Local(int obj) { objeto = obj; } Local(int obj, int la, int lo) { objeto = obj; latitude = la; longitude = lo; } void Exibe(void) { cout << "Objeto (" << objeto << "): Latitude: " << latitude << " -> Longitude: " << longitude << endl; } Local operator=(Local op2); friend Local operator++(Local &op2);

97

friend Local operator--(Local &op2); }; int main(void) { Local objeto1(1, 10, 20), objeto2(2); objeto1.Exibe(); ++objeto1; objeto1.Exibe(); objeto2.Exibe(); objeto2 = ++objeto1; objeto1.Exibe(); objeto2.Exibe(); --objeto2; objeto2.Exibe(); } Local Local :: operator=(Local op2) { latitude = op2.latitude; longitude = op2.longitude; return(*this); } Local operator++(Local &op2) { op2.latitude++; op2.longitude++; return(op2); } Local operator--(Local &op2) { op2.latitude--; op2.longitude--; return(op2); } Resultado do Programa : Objeto(1): Latitude: 10 -> Longitude: 20 Objeto(1): Latitude: 11 -> Longitude: 21 Objeto(2): Latitude: 134514985 -> Longitude: 134513662 Objeto(1): Latitude: 12 -> Longitude: 22 Objeto(2): Latitude: 12 -> Longitude: 22 Objeto(2): Latitude: 11 -> Longitude: 21

// lixo

5. Herana
5.1 Controle de acesso em classes base
Quando uma classe derivada herda as caractersticas de uma classe base, os membros da classe base (pblicos e protegidos) tornam-se membros da classe derivada.

98

O tipo de acesso aos membros da classe base dependem do especificador de acesso da classe derivada. Os especificadores de acesso de uma classe derivada podem ser pblicos o u privados. Se o especificador de acesso no for explicitado, por default a classe derivada privada. Quando utilizado um especificador de acesso pblico (public) em uma classe base todos os membros pblicos se tornam pblicos da classe derivada. Quando os membros so protegidos (protected ) da classe base eles podem ser acessados na classe derivada e tornam-se protegidos da classe derivada. Os membros privados (private) da classe base no podem ser acessados pela classe derivada.

Forma geral:
class nome_da_classe_derivada : especificador_acesso nome_classe_base { // atributos e mtodos; };

Programa exemplo (84): O programa demonstra a utilizao de uma classe derivada, ou seja, herana simples.
// heranca1.cpp #include <iostream> using namespace std; class Base { protected: int x, y; private: void seta_atributos(int tx, int ty) { x = tx; y = ty; } public: void Inicializa(int tx, int ty) { seta_atributos(tx,ty); } void Exibe(void) { cout << "x = " << x << " | y = " << y << endl; } }; class Derivada : public Base { public: void Move(int tam) {

99

} };

x = x + tam; y = y + tam;

int main(void) { Derivada d; // d.seta_atributos(1,2); d.Inicializa(1,2); d.Exibe(); d.Move(10); d.Exibe(); } Resultado do Programa : x=1|y=2 x = 11 | y = 12 .... erro, pois este mtodo privado da classe base

Nota: No programa exemplo 84, acima, troque o especificador de acesso da classe derivada de public para private e tente compilar o programa. Quando o especificador de acesso de uma classe derivada privada (private) todos os membros pblicos e protegidos da classe base tornam-se privados da classe derivada.

5.2 Herana e membros protegidos


Quando um membro (atributo ou mtodo) de uma classe base declarado como protegido (protected ) somente estes podem ser acessados por uma classe derivada. Quando um membro declarado como protegido em uma classe base ele torna-se acessvel a qualquer classe derivada, inclusive se a classe derivada torna-se derivada de outra classe derivada. Programa exemplo (85): O programa demonstra a utilizao de duas classes derivadas atravs de uma classe base.
// heranca2.cpp #include <iostream> using namespace std; class Base { protected: int x, y; private: void seta_atributos(int tx, int ty)

100

{ x = tx; y = ty; } public: void Inicializa(int tx, int ty) { seta_atributos(tx,ty); } void Exibe(void) { cout << "x = " << x << " | y = " << y << endl; } }; class Derivada1 : public Base { public: void Move(int tam) { x = x + tam; y = y + tam; } }; class Derivada2 : public Derivada1 { public: void Retorna(int tam) { x = x - tam; y = y - tam; } }; int main(void) { Derivada1 d1; Derivada2 d2; d1.Inicializa(1,2); d1.Exibe(); d1.Move(10); d1.Exibe(); d2.Inicializa(2,3); d2.Exibe(); d2.Move(10); d2.Exibe(); d2.Retorna(15); d2.Exibe(); } Resultado do Programa : x=1|y=2 x = 11 | y = 12 x=2|y=3 x = 12 | y = 13 x = -3 | y = -2

101

Se o especificador de acesso da segunda classe derivada for privado (private) alguns mtodos ( Inicializa , Move e Exibe) no podem ser acessados na funo main, somente na classe derivada2 (veja programa 86, abaixo). Programa exemplo (86): O programa demonstra a utilizao de duas classes derivadas atravs de uma classe base (segunda classe derivada tem acesso privado).
// heranca3.cpp #include <iostream> using namespace std; class Base { protected: int x, y; private: void seta_atributos(int tx, int ty) { x = tx; y = ty; } public: void Inicializa(int tx, int ty) { seta_atributos(tx,ty); } void Exibe(void) { cout << "x = " << x << " | y = " << y << endl; } }; class Derivada1 : public Base { public: void Move(int tam) { x = x + tam; y = y + tam; } }; class Derivada2 : private Derivada1 { public: void Retorna(int tam) { Inicializa(2,3); // pblica na base privada a classe derivada2 Move(10); // pblica na classe derivada privada a classe derivada2 x = x tam; // protegida na base acessvel a classe derivada2 y = y tam; // protegida na base acessvel a classe derivada2 Exibe(); // pblica na base privada a classe derivada2 } };

102

int main(void) { Derivada1 d1; Derivada2 d2; d1.Inicializa(1,2); d1.Exibe(); d1.Move(10); d1.Exibe(); d2.Retorna(15); } Resultado do Programa : x=1|y=2 x = 11 | y = 12 x = -3 | y = -2

5.3 Herana mltipla de classes base


Quando uma classe herda as caractersticas de mais de uma classe base este tipo de herana chamado de Herana Mltipla. Programa exemplo (87): O programa demonstra a utilizao de herana mltipla, ou seja, uma classe derivada de duas classes base.
// multipla.cpp #include <iostream> using namespace std; class Base1 { protected: int x; public: void Exibe_Atributo_X(void) { cout << "x = " << x << endl; } }; class Base2 { protected: int y; public: void Exibe_Atributo_Y(void) { cout << "y = " << y << endl; } }; class Derivada : public Base1 , public Base2 { // herana mltipla

103

public: void Seta(int tx, int ty) { x = tx; y = ty; } }; int main(void) { Derivada d; d.Seta(1,2); d.Exibe_Atributo_X(); d.Exibe_Atributo_Y(); } // derivada // base1 // Base2

5.4 Passando parmetros para os construtores das classes base


Para passar parmetros para uma classe base atravs de uma classe derivada, utiliza-se a sintaxe abaixo dentro da classe derivada (veja exemplo 88):

Sintaxe:
class nome_da_classe_derivada : especificador_acesso nome_da_classe_base { //atributos construtor_derivado (lista_de_argumentos) : base1 (lista_de_argumentos), base2 (lista_de_argumentos) { } };

Programa exemplo (88): O programa demonstra a utilizao de construtores para uma classe base atravs de uma classe derivada em herana simples.
// heranca.cpp #include <iostream> using namespace std; class Base { protected: int x; public: Base(int tx) // construtor { x = tx; cout << "Construtor Base, Ok " << endl; } ~Base(void) // destrutor { cout << "Destrutor Base, Ok" << endl; }

104

}; class Derivada : public Base // herana simples { private: int y; public: Derivada (int ty, int tx) : Base(tx) // passando argumentos para a classe base { y = ty; cout << "Construtor Derivada, Ok" << endl; } ~Derivada (void) //destrutor { cout << "Destrutor Derivada, Ok" << endl; } void Exibe(void) { cout << "| x = " << x << " | y = " << y << " |" << endl; } }; int main(void) { Derivada d(3,4); d.Exibe(); } Resultado do Programa : Construtor Base, Ok Construtor Derivada, Ok |x=4|y=3| Destrutor Derivada, Ok Destrutor Base, Ok

Programa exemplo (89): O programa demonstra a utilizao de construtores para classes bases atravs de uma classe derivada em herana mltipla.
// heranca.cpp #include <iostream> using namespace std; class Base1 { protected: int x; public: Base1(int tx) { x = tx; cout << "Construtor Base1, Ok " << endl; } ~Base1(void) {

105

cout << "Destrutor Base1, Ok" << endl; }; }

class Base2 { protected: int y; public: Base2(int ty) { y = ty; cout << "Construtor Base2, Ok " << endl; } ~Base2(void) { cout << "Destrutor Base2, Ok" << endl; } }; class Derivada : public Base1 , public Base2 { private: int z; public: Derivada (int tz, int ty, int tx) : Base2(ty) , Base1(tx) { z = tz; cout << "Construtor Derivada, Ok" << endl; } ~Derivada (void) { cout << "Destrutor Derivada, Ok" << endl; } void Exibe(void) { cout << "| x = " << x << " | y = " << y << " | z = " << z << " |" << endl; } }; int main(void) { Derivada d(3,4,5); d.Exibe(); } Resultado do Programa : Construtor Base1, Ok Construtor Base2, Ok Construtor Derivada, Ok |x=5|y=4|z=3| Destrutor Derivada, Ok Destrutor Base2, Ok Destrutor Base1, Ok

5.5 Garantindo acesso 106

Quando uma classe derivada herda uma classe base com especificador de acesso private, todos seus membros ( public, private ou protected ) tornam-se membros privados da classe derivada. Quando necessrio restaurar o acesso aos membros da classe base, utiliza-se uma declarao de acesso . Forma de usar: nome_da_classe_base :: membro; Observao: Uma declarao de acesso no funciona para atributos ou mtodos declarados como private. Programa exemplo (90): O programa demonstra a utilizao de declarao de acesso em uma classe derivada declarada como privada.
// heranca.cpp #include <iostream> using namespace std; class Base { protected: int x, y; public: void Inicializa(int tx, int ty) { x = tx; y = ty; } void Exibe(void) { cout << "x = " << x << " | y = " << y << endl; } }; class Derivada : private Base { public: Base :: Inicializa; // declarao de acesso, mtodo Inicializa tornou-se pblico Base :: Exibe; // declarao de acesso, mtodo Exibe tornou-se pblico void Move(int tam) { x = x + tam; y = y + tam; } }; int main(void) { Derivada d; d.Inicializa(1,2); d.Exibe(); d.Move(10); // d.x = 7; ... erro, pois x protegido, a no ser que seja feito Base :: x; na classe Derivada

107

d.Exibe();

5.6 Classes base virtuais


Na herana mltipla pode haver problema de ambigidade, pois quando uma classe derivada herda duas outras classes derivadas que herdaram uma mesma classe base, existe duas cpias desta classe base na classe derivada mltipla. Desta forma, quando se tenta acessar um atributo de uma classe das classes derivadas, o compilador no sabe a qual das classes derivadas o atributo pertence, dois existem duas cpias da classe base. Existem duas formas de resolver este problema. A primeira atravs do operador de resoluo de escopo (veja programas exemplos 91 e 92). Programa exemplo (91): O programa demonstra a utilizao do operao de resoluo de escopo em herana mltipla para resolver o problema citado acima.
// multipla.cpp #include <iostream> using namespace std; class Base { public: int i; }; class Derivada1 : public Base { public: int j; }; class Derivada2 : public Base { public: int k; }; class Derivada3 : public Derivada1 , public Derivada2 { public: int soma; public: void Exibe(void) { cout << "Soma = " << soma << endl; } }; int main(void) { Derivada3 d3;

108

d3.Derivada1 :: i = 1 ; // operador de resoluo de escopo d3.Derivada2 :: i = 2 ; // operador de resoluo de escopo d3.j = 3; d3.k = 4; d3.soma = d3.Derivada1::i + d3.Derivada2::i + d3.j + d3.k; d3.Exibe(); } Resultado do Programa : Soma = 10

Programa exemplo (92): O programa demonstra a utilizao do operao de resoluo de escopo em herana mltipla para resolver o problema citado acima.
// multipla.cpp #include <iostream> using namespace std; class Base { public: int x; public: void Inicializa_Base(int tx) { x = tx; } void Exibe_Base(void) { cout << "x = " << x << " |" << endl; } int Retorna_Base(void) { return(x); } }; class Derivada1 : public Base { public: int y; public: void Inicializa(int ty, int tx) { y = ty; Inicializa_Base(tx); Exibe_Base(); } void Exibe(void) { cout << "y = " << y << " |" << endl; } }; class Derivada2 : public Base

109

{ public: int z; public: void Inicializa(int tz, int tx) { z = tz; Inicializa_Base(tx); Exibe_Base(); } void Exibe(void) { cout << "z = " << z << " |" << endl; } }; class Derivada3 : public Derivada1 , public Derivada2 { public: int soma; public: void Exibe(void) { cout << "Soma = " << soma << endl; } }; int main(void) { Derivada1 d1; Derivada2 d2; Derivada3 d3; d1.Inicializa(1,2); d1.Exibe(); d2.Inicializa(3,4); d2.Exibe(); d3.soma = d1.Derivada1::x + d2.Derivada2::x ;// diferena entre os programas 70 e 71 d3.Exibe(); d3.soma = d3.soma + (d1.y + d2.z); d3.Exibe(); } Resultado do Programa : x=2| y=1| x=4| z=3| Soma = 6 Soma = 10

Outra forma de resolver o problema citado acima a utilizao de classes virtuais, pois quando se utiliza herana mltipla atravs de classes bases virtuais no so criadas cpias mltiplas da classe base, ou seja, criado apenas uma cpia da classe base (veja os programas exemplo 93 e 94).

110

Programa exemplo (93): O programa demonstra a utilizao de classes virtuais em herana mltipla para resolver o problema citado acima.
// multipla.cpp #include <iostream> using namespace std; class Base { public: int i; }; class Derivada1 : virtual public Base { public: int j; }; class Derivada2 : virtual public Base { public: int k; }; class Derivada3 : public Derivada1 , public Derivada2 { public: int soma; public: void Exibe(void) { cout << "Soma = " << soma << endl; } }; int main(void) { Derivada3 d3; d3.i = 2; d3.j = 3; d3.k = 4; d3.soma = d3.i + d3.j + d3.k; d3.Exibe(); } Resultado do Programa : Soma = 9

Programa exemplo (94): O programa demonstra a utilizao de classes virtuais em herana mltipla para resolver o problema citado acima.
// multipla.cpp

111

#include <iostream> using namespace std; class Base { public: int x; public: void Inicializa_Base(int tx) { x = tx; } void Exibe_Base(void) { cout << "x = " << x << endl; } int Retorna_Base(void) { return(x); } }; class Derivada1 : virtual public Base { public: int y; public: void Inicializa(int ty, int tx) { y = ty; Inicializa_Base(tx); Exibe_Base(); } void Exibe(void) { cout << "y = " << y << endl; } }; class Derivada2 : virtual public Base { public: int z; public: void Inicializa(int tz, int tx) { z = tz; Inicializa_Base(tx); Exibe_Base(); } void Exibe(void) { cout << "z = " << z << endl; } }; class Derivada3 : public Derivada1 , public Derivada2 {

112

public: int soma; public: void Exibe(void) { cout << "Soma = " << soma << endl; } }; int main(void) { Derivada1 d1; Derivada2 d2; Derivada3 d3; d1.Inicializa(1,2); d1.Exibe(); d2.Inicializa(3,4); d2.Exibe(); d3.soma = d1.x + (d1.y + d2.z); d3.Exibe(); d3.soma = d2.x + (d1.y + d2.z); d3.Exibe(); } Resultado do Programa : x=2 y=1 x=4 z=3 Soma = 6 Soma = 8

// Soma = 6 // Soma = 8

6. Funes Virtuais e Polimorfismo


6.1 Funes virtuais
Uma funo dita virtual quando declarada com o especificador virtual em uma classe base e depois redefinida em classes derivadas. A redefinio da funo na classe derivada precede a funo da classe base, ou seja, a declarao da funo virtual na classe base demonstra o funcionamento bsico do mtodo virtual, enquanto que as redefinies funcionam como funcionamento especfico do mtodo virtual. Observao: Uma funo virtual em OOP chamado de mtodo virtual. Programa exemplo (95): O programa demonstra a utilizao de uma funo virtual em herana simples.
// virtual.cpp

113

#include <iostream> using namespace std; class Base { protected: int x; public: Base(int tx) { x = tx; } virtual void Exibe(void) { cout << "x = " << x << " |" << endl; } }; class Derivada1 : public Base { public: int y; public: Derivada1(int ty, int tx) : Base(tx) { y = ty; } void Exibe(void) // redefinio da funo virtual { cout << "x = " << x << " | y = " << y << " | " << endl; } }; class Derivada2 : public Base { public: int z; public: Derivada2(int tz, int tx) : Base(tx) { z = tz; } void Exibe(void) // redefinio da funo virtual { cout << "x = " << x << " | z = " << z << " |" << endl; }; int main(void) { Base base(1); Derivada1 d1(4,2); // 2 um valor para a varivel x Derivada2 d2(5,3); // 3 um valor para a varivel x base.Exibe(); d1.Exibe(); d2.Exibe(); } Resultado do Programa :

114

x=1| x=2|y=4| x=3|z=5|

O acesso a funes virtuais pode ser feita atravs de ponteiros. O programa exemplo abaixo demonstra a utilizao de ponteiros para funes virtuais (mtodos virtuais).
// virtual.cpp #include <iostream> using namespace std; class Base { protected: int x; public: Base(int tx) { x = tx; } virtual void Exibe(void) { cout << "x = " << x << " |" << endl; } }; class Derivada1 : public Base { public: int y; public: Derivada1(int ty, int tx) : Base(tx) { y = ty; } void Exibe(void) { cout << "x = " << x << " | y = " << y << " | " << endl; } }; class Derivada2 : public Base { public: int z; public: Derivada2(int tz, int tx) : Base(tx) { z = tz; } void Exibe(void) { cout << "x = " << x << " | z = " << z << " |" << endl; };

115

int main(void) { Base *pt, base(1); Derivada1 d1(4,2); Derivada2 d2(5,3); pt = &base; pt->Exibe(); pt = &d1; pt->Exibe(); pt = &d2; pt->Exibe(); } Resultado do Programa : x=1| x=2|y=4| x=3|z=5|

Restries na utilizao de funes virtuais :


a) Se o prottipo de uma funo virtual nas classes derivadas modificado, a funo virtual considerada sobrecarga de funes; b) As funes virtuais devem ser membros das classes a que pertencem; c) No podem ser funes amigas ( friend); d) Construtores no podem ser virtuais, mas destrutores podem.

6.2 Funes virtuais puras


O objetivo de uma funo virtual pura que quando uma funo virtual no for redefinida por uma classe derivada, a funo virtual pura declarada na classe base executada. U m a funo virtual pura no possui nenhuma definio no seu interior. Ela declarada assim:
virtual tipo_de_retorno_do_mtodo nome_do_mtodo_virtual (lista_de_argumentos) = 0;

Quando uma funo virtual pura declarada em uma classe base, todas as classes derivadas devem obrigatoriamente redefinir a funo virtual. Programa exemplo (97): O programa demonstra a utilizao de uma funo virtual pura em herana simples.
// virtualpura.cpp #include <iostream>

116

using namespace std; class Base { protected: int valor; public: Base(int x) { valor = x; } virtual void Exibe(void) = 0; };

// funo virtual pura

class Hexadecimal : public Base { public: Hexadecimal(int x): Base(x) { } void Exibe(void) { cout << "Valor em Hexadecimal = " << uppercase << hex << valor << endl; } }; class Decimal : public Base { public: Decimal(int x): Base(x) { } void Exibe(void) { cout << "Valor em Decimal = " << dec << valor << endl; } }; class Octal : public Base { public: Octal(int x): Base(x) { } void Exibe(void) { cout << "Valor em Octal = " << oct << valor << endl; } }; const int num = 26; int main(void) { Hexadecimal hexadecimal(num); Decimal decimal(num); Octal octal(num); hexadecimal.Exibe(); decimal.Exibe(); octal.Exibe(); } Resultado do Programa : Valor em Hexadecimal = 1A Valor em Decimal = 26 Valor em Octal = 32

117

6.3 Classes abstratas


Uma classe abstrata quando possui pelo menos uma funo virtual pura. Uma classe abstrata no pode criar objetos (veja observao abaixo). Uma classe abstrata considerada uma classe incompleta que utilizada apenas como base para classes derivadas. Apesar de no ser possvel criar objetos neste tipo de classe, pode-se criar ponteiros que apontem para este tipo de classe, isto fornece suporte a polimorfismo em tempo de execuo. Observao: No programa exemplo anterior (97) tente inserir a seguinte linha na funo main: Base base(5); Note que dar um erro de compilao.

6.4 Usando funes virtuais


Uma das caractersticas mais importantes da orientao objetos a capacidade de polimorfismo ( ... uma interface, vrios mtodos ... ). Para tanto pode-se declarar uma classe base como interface, ou seja, utilizada para definir a natureza da interface e cada classe derivada implementa operaes especficas a esta interface. Para criar hierarquias de classes que representem este contexto ... uma interface, vrios mtodos ... , deve-se utilizar: funes virtuais, classes abstratas e polimorfismo em tempo de execuo . Desta forma, define-se todas as caractersticas comuns e a interface na classe base e as aes sobre a interface nas classes derivadas. Programa exemplo (98): O programa demonstra a utilizao de funes virtuais em herana simples.
// abstrata.cpp #include <iostream> using namespace std; class Base { protected: double valor, celsius, fahrenheit; public: Base(double temperatura) { valor = temperatura; } void Exibe(void) { cout << "Celsius = " << celsius << endl; cout << "Fahrenheit = " << fahrenheit << endl << endl; } virtual void Converte(void) = 0; }; class Celsius_Fahrenheit : public Base { public: Celsius_Fahrenheit(double temperatura): Base(temperatura) { } void Converte(void)

118

};

{ fahrenheit = (9 * valor) / 5 + 32; celsius = valor; }

class Fahrenheit_Celsius : public Base { public: Fahrenheit_Celsius(double temperatura): Base(temperatura) { } void Converte(void) { celsius = ((valor - 32) / 9) * 5; fahrenheit = valor; } }; int main(void) { Celsius_Fahrenheit celsius(40.0); Fahrenheit_Celsius fahrenheit(104.0); celsius.Converte(); celsius.Exibe(); fahrenheit.Converte(); fahrenheit.Exibe(); } Resultado do Programa : Celsius = 40 Fahrenheit = 104 Celsius = 40 Fahrenheit = 104

7. Utilizao Bsica do Sistema de I/O do C++


7.1 Fluxos do C++
U m f l u x o ( stream) u m d i s p o s i t i v o l g i c o d e e n t r a d a e s a d a (io input output ) que est ligado a um dispositivo fsico, normalmente a entrada est ligada ao teclado e a sada ao monitor de vdeo. Alm destes dispositivos, pode-se ainda utilizar uma impressora ou ler e gravar em arquivos.

7.2 Classes bsicas dos streams


C++ permite acessar os fluxos de entrada e sada atravs do arquivo de cabealho (header) iostream.h ou simplesmente iostream. Neste arquivo definida uma hierarquia de classes de entrada e sada.

Hierarquia das classes (fluxos):


streambuf: Mtodos para buffers de memria. Esta classe base a de mais baixo nvel,

119

proporcionando operaes bsicas de entrada e sada para as outras classes derivadas.

ios: Manipula o estado das variveis dos fluxos e erros. istream : Manipula converses formatadas e no formatadas da classe streambuf . ostream : Manipula converses formatadas e no formatadas da classe streambuf . iostream : istream e ostream juntas para manipular operaes bi-direcionais em um nico fluxo. istream _withassign : F o r n e c e c o n s t r u t o r e s e o p e r a d o r e s d e a t r i b u i o p a r a o f l u x o cin. ostream _withassign : Fornece construtores e operadores de atribuio para os fluxos cout, cerr e clog. iostream _withassign : Fornece construtores e operadores de atribuio para os fluxos cin, cout, cerr e clog .

7.3 Streams pr-definidos do C++


Quando um programa em C++ comea a ser executado quatro fluxos so abertos: cin, cout, cerr e clog.

cin: Entrada padro via teclado. cout: Sada padro via monitor de vdeo. cerr: Sada padro de erro via tela. clog: Sada padro de erro bufferizada via tela.

7.4 Entrada e sada formatada


Todas as formataes possveis feitas em C padro pelas funes printf e scanf podem ser realizadas pelos mtodos cin e cout e pelos operadores << e >>. C++ permite a utilizao das funes printf e scanf, mas por outro lado possui duas formas de formatar dados atravs das funes cin e cout: 1) Acessando diretamente os membros da classe ios (atributos ou mtodos) ou seja, possvel configurar os flags de formatao (veja item 7.5 a seguir); 2) Utilizando manipuladores (funes especiais) nos mtodos cin e cout (veja item 7.7 logo abaixo).

7.5 Formatando utilizando os membros de entrada e sada


Existe um conjunto de flags, associados a cada fluxo, que permitem controlar a forma que a informao tratada em cada fluxo. Os flags de formatao so armazenados em um inteiro longo ( long int). Na classe ios existe a seguinte enumerao:

120

enum { skipws = 0x0001; left = 0x0002; right = 0x0004; internal = 0x0008; dec = 0x0010; oct = 0x0020; hex = 0x0040; showbase = 0x0080; showpoint = 0x0100; uppercase = 0x0200; showpos = 0x0400; scientific = 0x0800; fixed = 0x1000; unitbuf = 0x2000; stdio = 0x4000; }; flags ios::skipws ios::left ios::right ios::internal ios::dec ios::oct ios::hex ios::showbase ios::showpoint ios::uppercase ios::showpos ios::scientific ios::fixed ios::unitbuf ios::stdio Significado Ignorar espaos em branco na entrada Alinhar esquerda na sada Alinhar direita na sada Preencher aps o sinal ou indicador de base Imprimir sada como decimal Imprimir sada como octal Imprimir sada como hexadecimal Exibir indicador de base na sada Exibir ponto decimal (ponto flutuante) Exibir sada hex em maisculo Exibir '+' com inteiros positivos Exibir em notao cientfica (1.23e+00 ou 1.23E+00 se usar uppercase) Utilizar a notao em ponto flutuante (123.45) Apagar todos os fluxos aps insero Apagar os fluxos stdout e stderr aps insero

7.6 Setando flags de formato


Para configurar um flag de formato utiliza-se o mtodo setf(). Este mtodo pertence a classe ios. Sintaxe: long setf(long flags) ; Funcionamento: O mtodo retorna o valor corrente dos flags e seta os flags especificados por flags, no afetando os demais flags. Forma de usar: fluxo.setf(ios:flag); Exemplo: cout.setf(ios:flag); Programa exemplo (99): O programa demonstra a utilizao da funo setf para formatar o mtodo cout.

121

// setf.cpp #include <iostream> using namespace std; int main(void) { cout.setf(ios::uppercase); cout.setf(ios::hex); for (int i = 0;i <= 10000;i++) cout << i << endl; }

7.7 Formatando usando manipuladores


Como foi dito anteriormente, existe uma segunda forma de formatar o fluxo cout, a utilizao de manipuladores. Existem vrios manipuladores de entrada e sada que permitem formatar o que ser impresso na tela com o mtodo c o u t . Estes manipuladores esto definidos em iomanip e so: dec, endl, ends, flush, hex, oct, resetiosflag, setbase, setfill, setiosflags, setprecision , setw, ws, left, right, uppercase e scientific.

dec: Exibe um nmero em decimal (sada). endl: Pula uma linha (sada). ends: Envia um NULL (sada). flush: Esvazia o fluxo (sada). hex: Exibe um nmero em hexadecimal (sada). oct: Exibe um nmero em octal (sada). resetiosflag(long flag) : Apaga os flags especificados por flag (entrada e sada). setbase(int base) : Seta a base numrica para base (sada). setfill(char ch) : Indica que caracter ser impresso no lugar de um nmero (sada). setiosflags(long flag) : Liga os flags especificados por flag (entrada e sada). setprecision(int n): Especifica o nmero de dgitos (n) que sero impressos, antes e depois do ponto (sada). setw(int n): Indica quantos dgitos (n) sero impressos na tela (sada). ws: Salta espaos em branco ao final (entrada). left: Alinha pela esquerda. Deve ser usado antes do setw (sada). right: Alinha pela direita. Deve ser usado antes do setw (sada). uppercase : Exibe os caracteres maisculos (sada). scientific : Exibe um nmero em notao cientfica (sada).
Programa exemplo (100) : O programa demonstra a utilizao do manipulador setprecision para formatar o mtodo cout.
// setprecision.cpp #include <iostream>

122

#include <iomanip> using namespace std; int main (void) { double pi = 3.14159; cout << setprecision (3) << pi << endl; cout << setprecision (4) << pi << endl; }

Programa exemplo (101) : O programa demonstra a uso dos manipuladores setfill e setw para formatar o mtodo cout.
// formata.cpp #include <iostream> #include <iomanip> using namespace std; int main (void) { for (int i = 0;i <= 10000;i++) cout << setfill('0') << setw(5) << i << endl; }

Programa exemplo (102) : O programa demonstra a uso dos manipuladores right e setw para formatar o mtodo cout.
// right.cpp #include <iostream> #include <iomanip> using namespace std; int main (void) { for (int i = 0;i <= 10000;i++) cout << "|" << right << setw(10) << i << "|" << endl; }

Programa exemplo (103) : O programa demonstra a uso dos manipuladores uppercase e hex para formatar o mtodo cout.
// hex.cpp #include <iostream> #include <iomanip> using namespace std; int main (void) { for (int i = 0;i <= 10000;i++)

123

cout << uppercase << hex << i << endl; }

8. Tratamento de Excees
Uma exceo um erro que ocorre em tempo de execuo e pode ou no ser tratado pela aplicao. O tratamento de excees especifica uma ou mais solues para uma situao de erro quando o programa est sendo executado. Quando registrado uma situao de exceo (ou seja, um erro detectado) ocorre um desvio para um local que ir trat-lo diretamente, cruzando as fronteiras de funes e do controle do fluxo do programa. Excees so executadas quando ocorre alguma falha. Excees executadas so capturadas e tratadas.

Sintaxe:
try: Delimita o incio do bloco com cdigo protegido. catch: Delimita o final de um bloco protegido e o incio das instrues de tratamento de excees. throw: Gera novas excees ou propaga uma j existente.
try { // cdigo a ser protegido de um erro; } catch (varivel inteiro) { // cdigo de tratamento do erro; }

Vantagens no uso do tratamento de excees : Com o uso de excees h uma separao entre o cdigo que identifica uma
condio de erro do cdigo que reporta o erro; (substitui diversos if's);

O cdigo da aplicao no precisa ficar cheio de pontos que verifiquem erros O programador no tem como fugir das excees geradas, ele tm que trat-las; Aumento da confiabilidade da aplicao; Se o programador deseja tratar algum tipo de exceo ele adiciona na aplicao o
cdigo necessrio para tal, seno ele pode fornecer um tratamento padro para as todas as excees;

A gerao de uma exceo chama destrutores.

124

Observao: Podem haver vrios blocos catch para cada comando try. Podem haver vrios comandos throw. Programa exemplo (104): O programa demonstra a utilizao dos comandos try, throw e catch.
// catch1.cpp #include <iostream> #include <limits> using namespace std; float div(float a, float b) { if (b not_eq 0) // b != 0 return(a/b); else throw 100; } int main(void) { float x, y, resp; try { cout << "Digite um valor: "; cin >> x; cout << "Digite outro valor: "; cin >> y; resp = div(x, y); cout << "Resposta: " << resp << endl; } catch (int i) { if (i == 100) cout << "Erro: Diviso por Zero" << endl; else cout << "Erro desconhecido" << endl; } }

Observao: Quando no for especificado uma varivel inteira no comando catch ele genrico. Veja exemplo abaixo: Programa exemplo (105): O programa demonstra a utilizao dos comandos try, throw e com um comando catch genrico.
// catch2.cpp #include <iostream> #include <limits> using namespace std; float div(float a, float b) { if (b not_eq 0) return(a/b); else

125

throw 100; } int main(void) { float x, y, resp; try { cout << "Digite um valor: "; cin >> x; cout << "Digite outro valor: "; cin >> y; resp = div(x, y); cout << "Resposta: " << resp << endl; } catch (...) { // (...) catch genrico cout << "Erro: Diviso por Zero" << endl; } }

9. Jogo escrito em C++


Para demonstrar a capacidade da linguagem de programao C++, ser mostrado o programa fonte de um jogo da forca escrito em C++ utilizando a biblioteca ncurses . Tela do Jogo da Forca

Programa exemplo (106): O programa demonstra a utilizao da biblioteca ncurses em um do jogo da forca escrito em C++.
// JogoForca.cpp (Ubuntu 6.06 Dapper- Anjuta) // Autor: Paulo Roberto Gomes Luzzardi // Data: 07/08/2006 // --------------------------------------------------------- includes

126

#include <iostream> #include <string> #include <curses.h> using namespace std; // --------------------------------------------------------- constantes const char ESC = 27; const char ENTER = 13; const char SPACE = 32; const int LEFT = 260; const int RIGHT = 261; const char BLACK = COLOR_BLACK; const char RED = COLOR_BLUE; const char GREEN = COLOR_GREEN; const char BROWN = COLOR_YELLOW; const char BLUE = COLOR_BLUE; const char MAGENTA = COLOR_MAGENTA; const char CYAN = COLOR_CYAN; const char WHITE = COLOR_WHITE; const char COR_TEXTO = GREEN; const char COR_TELA = BROWN; const char COR_TEMPO = RED; const char COR_RELOGIO = BROWN; const char COR_WINNER = CYAN; const char COR_LETRAS = BLUE; const char COR_SELECAO = RED; const char COR_TITULO = MAGENTA; const char COR_STATUS = WHITE; const int NPAL = 30; const int PSORT = 8; const int NTIPOS = 4; // ----------------------------------------------- Palavras string nomes[NTIPOS] = {"Cidades","Pases","Carros","Frutas"}; string cidades[NPAL] = {"pelotas", "alegrete", "uruguaiana", "livramento", "chui", "rivera", "chuy", "piratini", "candiota", "marau", "erechin", "cachoerinha", "caxias", "gramado", "canela", "itaqui", "cacequi", "formigueiro", "parati", "buzios", "torres", "mostarda", "tapes", "agudo", "candiota","chiapeta","cassino","casca","cristal","cidreira"}; string paises[NPAL] = {"brasil", "peru", "uruguai", "argentina", "bolivia", "chile", "guatemala", "cuba", "alemanha", "suecia", "inglaterra", "china", "russia", "montenegro", "tibet", "nepal", "servia", "noruega", "portugal", "espanha", "grecia", "mongolia", "escocia", "palestina", "israel", "iraqui","australia","jamaica","egito","congo"}; string carros[NPAL] = {"mercedes", "fusca", "dodge", "palio", "omega", "kombi", "fiat", "ford", "dakota", "bmw", "ka", "elba", "gol", "golf", "vectra", "sportage", "idea", "corcel", "parati", "saveiro", "peuget", "citroen", "toyota", "nissan", "renaut", "frontier", "honda", "subaru", "corrola", "civic"}; string frutas[NPAL] = {"abacaxi", "banana", "ameixa", "pera", "goiaba", "amora", "bergamota", "morango", "lima", "abacate", "carambola", "laranja", "kiwi", "tangerina", "figo", "pitanga", "framboesa", "acerola", "cereja", "nectarina", "pomelo", "caqui", "caju", "marmelo", "uva","nectarina","damasco","manga","jaca","jabuticaba"}; // --------------------------------------------------------- Classe: Janela

127

class Janela { public: Janela(void); ~Janela(void); void clrscr(void); void gotoxy(int c, int l); void flushall(void); int Random(int n); void randomize(void); void textcolor(int cor); void textcolorlight(int cor); void tempo(int c, int l); }; // --------------------------------------------------------- Construtor Janela :: Janela(void) { initscr(); keypad(stdscr, TRUE); (void) nonl(); (void) cbreak(); (void) echo(); if (has_colors()) { start_color(); init_pair(1,COLOR_RED,COLOR_BLACK); init_pair(2,COLOR_GREEN,COLOR_BLACK); init_pair(3,COLOR_YELLOW,COLOR_BLACK); init_pair(4,COLOR_BLUE,COLOR_BLACK); init_pair(5,COLOR_CYAN,COLOR_BLACK); init_pair(6,COLOR_MAGENTA,COLOR_BLACK); init_pair(7,COLOR_WHITE,COLOR_BLACK); attrset(COLOR_PAIR(A_BOLD)); } } // --------------------------------------------------------- Destrutor Janela :: ~Janela(void) { endwin(); system("clear"); } // --------------------------------------------------------- Mtodo: clrscr void Janela :: clrscr(void) { clear(); refresh(); } // --------------------------------------------------------- Mtodo: gotoxy void Janela :: gotoxy(int c, int l) { move(l-1,c-1); refresh();

128

} // --------------------------------------------------------- Mtodo: flushall void Janela :: flushall(void) { getchar(); } // --------------------------------------------------------- Mtodo: Random int Janela :: Random(int n) { int t = rand() % n; return(t); } // --------------------------------------------------------- Mtodo: randomize void Janela :: randomize(void) { srand((unsigned int)time((time_t *)NULL)); } // --------------------------------------------------------- Mtodo: textcolor void Janela :: textcolor(int cor) { attrset(COLOR_PAIR(cor)); } // --------------------------------------------------------- Mtodo: textcolorlight void Janela :: textcolorlight(int cor) { attrset(COLOR_PAIR(cor)+A_BOLD); } // --------------------------------------------------------- tempo void Janela :: tempo(int c, int l) { time_t now; char s[30]; time(&now); strcpy(s,ctime(&now)); textcolor(COR_RELOGIO); gotoxy(c,l); printw("%s",s);

// --------------------------------------------------------- Classe: Boneco class Boneco { Janela janela; int col, lin; public:

129

Boneco(int c, int l) { col = c; lin = l; } void Monta_Boneco(int erro) { switch (erro) { case 1: janela.gotoxy(col,lin); printw(" O"); break; case 2: janela.gotoxy(col,lin+1); printw("/|"); break; case 3: janela.gotoxy(col,lin+1); printw("/|\\"); break; case 4: janela.gotoxy(col,lin+2); printw("/"); break; case 5: janela.gotoxy(col,lin+2); printw("/ \\"); break; } } }; // --------------------------------------------------------- Classe: Tela class Tela { public: void Monta_Tela(void); void Relogio(int *h, int *m, int *s); };

// --------------------------------------------------------- Monta_Tela void Tela :: Monta_Tela(void) { Janela janela; janela.textcolor(COR_TITULO); janela.gotoxy(33,1); printw("Jogo da Forca",199); janela.gotoxy(2,22); printw("[ESC] Abandona"); refresh(); janela.textcolorlight(COR_LETRAS); janela.gotoxy(16,20); printw("A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"); janela.tempo(56,1); } // --------------------------------------------------------- Relogio void Tela :: Relogio(int *h, int *m, int *s) {

130

time_t now; char st[30],temp[5]; time(&now); strcpy(st,ctime(&now)); int x = 0; for (int i = 11;i <= 12;i++) { temp[x] = st[i]; x++; } temp[x] = (char) NULL; *h = atoi(temp); x = 0; for (int i = 14;i <= 15;i++) { temp[x] = st[i]; x++; } temp[x] = (char) NULL; *m = atoi(temp); x = 0; for (int i = 17;i <= 18;i++) { temp[x] = st[i]; x++; } temp[x] = (char) NULL; *s = atoi(temp); } // ---------------------------------------------------- Classe: Jogo class Jogo { Janela janela; Tela tela; public: void Jogar(void); }; // ---------------------------------------------------- Mtodo: Jogar void Jogo :: Jogar(void) { Boneco boneco(60,10); int tecla; int hi, mi, si; int ma, sa; int ht, mt, st; string palavra; char vetor[26],s[10]; int row, col; getmaxyx(stdscr, row, col); // tamanho do terminal do { char ch = 'A'; int acertos = 0; int total = 0; int erros = 0;

131

bool sai = false; bool incrementa = false; bool click = false; int c = 16; int l = 20; hi = mi = si = 0; janela.clrscr(); janela.textcolor(WHITE); janela.gotoxy(60,24); printw("| row: %d | col: %d |",row,col); janela.randomize(); janela.textcolor(COR_TEXTO); tela.Monta_Tela(); for (int i = 0;i <= 25;i++) vetor[i] = '*'; tela.Relogio(&hi,&mi,&si); int ma = 0; int j = janela.Random(NPAL); int m = janela.Random(NTIPOS); switch (m) { case 0: palavra = cidades[j]; break; case 1: palavra = paises[j]; break; case 2: palavra = carros[j]; break; case 3: palavra = frutas[j]; break; } janela.textcolor(GREEN); janela.gotoxy(1,1); printw("Tipo: "); janela.textcolorlight(GREEN); janela.gotoxy(7,1); cout << nomes[m]; int n = palavra.length(); janela.gotoxy(20,10); cout << "PALAVRA: "; for (int i = 0;i < n;i++) printw("_ "); janela.textcolorlight(BROWN); janela.gotoxy(1,4); printw("Acertos: "); janela.gotoxy(1,5); printw(" Erros: "); do { tela.Relogio(&ht,&mt,&st); janela.textcolorlight(COR_STATUS); janela.gotoxy(10,4); printw("%d",acertos); janela.gotoxy(10,5); printw("%d",erros); sa = st - si; if (sa < 0) sa = sa + 60; if (sa == 58) incrementa = true; if (sa == 0 and incrementa) {

132

ma++; incrementa = false; } janela.textcolor(COR_TEMPO); janela.gotoxy(30,22); printw("Tempo Gasto: %02d:%02d\n",ma,sa); janela.gotoxy(c,l); tecla = getch(); if (tecla == ESC) sai = true; janela.textcolor(COR_TEMPO); janela.gotoxy(30,22); printw("Tempo Gasto: %02d:%02d\n",ma,sa); janela.textcolor(COR_RELOGIO); janela.tempo(56,1); switch (tecla) { case LEFT: c-=2; ch--; if (c < 16) { c = 66; ch = 'Z'; } break; case RIGHT: c+=2; ch++; if (c > 66) { c = 16; ch = 'A'; } break; case ENTER: case SPACE: janela.textcolor(COR_LETRAS); janela.gotoxy(34,18); printw("Caracter: [%c]",ch); janela.textcolorlight(GREEN); janela.gotoxy(c,l); printw("%c",ch); janela.textcolor(COR_SELECAO); col = 29; int lin = 10; bool acertou = false; int k = ch - 65; for (int i = 0;i < n;i++) { if (toupper(palavra[i]) == ch) { janela.gotoxy(col,lin); printw("%c",ch); if (not acertou and vetor[k] == '*') acertos++; total++; vetor[k] = '#'; acertou = true; } col = col + 2; } if (not acertou and vetor[k] == '*')

133

{ erros++; vetor[k] = '#'; } boneco.Monta_Boneco(erros); if (total == n) { janela.textcolor(COR_WINNER); janela.gotoxy(50,10); printw("(Winner)"); janela.gotoxy(30,24); sai = true; printw("Jogar Novamente [S/n]? "); do { tecla = getch(); } while(not strchr("SsNn",tecla) and tecla not_eq ESC); } break; } if (erros == 5) { janela.textcolorlight(RED); janela.gotoxy(34,14); cout << palavra; janela.textcolor(COR_WINNER); janela.gotoxy(50,10); printw("(Looser)"); janela.gotoxy(30,24); sai = true; printw("Jogar Novamente [S/n]? "); do { tecla = getch(); } while(not strchr("SsNn",tecla) and tecla not_eq ESC); } } while (not sai); } while (strchr("Ss",tecla) and tecla not_eq ESC);

// ------------------------------------------ Programa Principal int main(void) { Jogo jogo; jogo.Jogar(); }

10. Classes pr-definidas do C++


10.1 Classe <string>
C++ possui uma classe string que permite a manipulao de cadeias de caracteres

134

atravs de um conjunto de mtodos e operadores sobrecarregados desta classe.

Formas de declarar uma string :


Programa exemplo (108): O programa string8.cpp, a seguir, mostra vrias formas de declarar e inicializar um objeto string.
// string8.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s; string r("UCPel"); string t("UCPel", 10); string w = "Universidade"; string s1(r); string s2(r.begin(), r.end()); string s3(10, 'x'); s = "flor"; cout << s << endl; s = s + "es"; cout << s << endl; cout << r << endl; cout << t << endl; cout << w << endl; cout << s1 << endl; cout << s2 << endl; cout << s3 << endl; } Resultado do Programa : flor flores UCPel UCPelUniv Universidade UCPel UCPel xxxxxxxxxx

// s foi inicializada com "" // r foi inicializado com "UCPel" // t foi inicializada com "UCPel" , total de 10 caracteres // w foi inicializado com "Universidade" // s1 foi inicializada com "UCPel" // s2 foi inicializada com "UCPel" // s3 foi inicializada com "xxxxxxxxxx" // C++ aceita atribuio para string (ATRIBUIO) // imprime "flor" // C++ aceita concatenao de strings (CONCATENAO) // imprime "flores" // imprime "UCPel" // imprime "UCPel" + lixo // imprime "Universidade" // imprime "UCPel" // imprime "UCPel" // imprime "xxxxxxxxxx"

Programa exemplo (109): O programa string9.cpp, a seguir, mostra a utilizao dos mtodos: size (exibe o nmero de caracteres da string) , length (exibe o nmero de caracteres da string) e max_size (exibe o tamanho mximo de uma string pode ter) pertencentes a classe string. Sintaxe: int nome_string.size(void); Retorno: Nmero de caracteres da string.

135

Sintaxe: int nome_string.length(void); Retorno: Nmero de caracteres da string. Sintaxe: int nome_string.max_size(void); Retorno: Nmero mximo de caracteres permitido para uma string.
// string9.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s("Universidade"); cout << s.size() << endl; cout << s.length() << endl; cout << s.max_size() << endl; } Resultado do Programa : 12 12 1073741820 // 12 // 12 // 1073741820

Programa exemplo (110): O programa string10.cpp, a seguir, mostra a utilizao dos mtodos: insert (insere caracteres na string na posio especificada) e length (exibe o nmero de caracteres da string) pertencentes a classe string. Sintaxe: void nome_string.insert(int pos, string str); Onde: pos a posio da insero e str a string que ser inserida na posio.
// string10.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s("Universdade"); cout << s << endl; s.insert(7, "i"); cout << s << endl; s.insert(s.length(), "s"); cout << s << endl; } Resultado do Programa :

136

Universdade Universidade Universidades

Programa exemplo (111): O programa string11.cpp, a seguir, mostra a utilizao do mtodo: replace (troca n caracteres da string) pertencente a classe string. Sintaxe: void nome_string.replace(int pos, int n, string str); Onde: pos a posio da troca, n nmero de caracteres trocados e str a string que ser colocada na posio da troca.
// string11.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s("Universidade"); cout << s << endl; s.replace(7, 5, "o"); cout << s << endl; } Resultado do Programa : Universidade Universo

Programa exemplo (112): O programa string12.cpp, a seguir, mostra a utilizao do mtodo: c_str (converte string C++ para string C) pertencente a classe string. Sintaxe: char * nome_string.c_str(void); Retorno: String C padro.
// string12.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s("Universidade"); char st[30]; strcpy(st, s.c_str()); cout << st << endl; }

// vetor de caracteres string C padro // converte string C++ para string padro C

137

Resultado do Programa : universidade

Programa exemplo (113): O programa string13.cpp, a seguir, mostra a utilizao dos mtodos: find (encontrar a posio de uma string dentro de outra string procura da esquerda para direita) e rfind (encontrar a posio de uma string dentro de outra string procura da direita para esquerda) pertencentes a classe string. Sintaxe: int nome_string.find (string str, int pos); Onde: str a string a ser procurada e pos a posio inicial da busca (opcional). Retorno: posio da string str dentro da string (-1 se no for encontrado). Sintaxe: int nome_string.rfind(string str, int pos); Onde: str a string a ser procurada e pos a posio inicial da busca (opcional). Retorno: posio onde a string str no se encontra na s t r i n g (-1 se no for encontrado) .
// string15.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s("Universidade"); int i = s.find("a"); cout << i << endl; int j = s.rfind("bcd", 3); cout << j << endl; int k = s.rfind("a"); cout << k << endl; } Resultado do Programa : 9 -1 9

// retorna a posio da vogal 'a' (esquerda para direita) // 9 // retorna a posio da primeira destas consoantes (direita para esquerda) // -1 // retorna a posio da vogal 'a' (direita para esquerda) // 9

// fora da faixa

Programa exemplo (114): O programa string14.cpp, a seguir, mostra a utilizao dos mtodos: find_first_of (encontrar a posio de uma string dentro de outra string procura da esquerda para direita) e find_first_not_of (encontrar a posio de uma string no est dentro de outra s t r i n g - procura da esquerda para direita), find_last_of (encontrar a posio de uma string dentro de outra string procura da direita para esquerda) e find_last_not_of (encontrar a posio de uma string no est dentro de o u t r a s t r i n g - procura da direita para esquerda) pertencentes a classe string.

138

Sintaxe: int nome_string.find_first_of (string str, int pos); Onde: str a string a ser procurada e pos a posio inicial da busca (opcional). Retorno: posio da string str dentro da string (-1 se no for encontrado). Sintaxe: int nome_string.find_first_not_of (string str, int pos); Onde: str a string a ser procurada e pos a posio inicial da busca (opcional). Retorno: posio onde a string str no se encontra na s t r i n g (-1 se no for encontrado) . Sintaxe: int nome_string.find_last_of (string str, int pos); Onde: str a string a ser procurada e pos a posio inicial da busca (opcional). Retorno: posio da string str dentro da string (-1 se no for encontrado) . Sintaxe: int nome_string.find_last_not_of (string str, int pos); Onde: str a string a ser procurada e pos a posio inicial da busca (opcional). Retorno: posio onde a string str no se encontra na s t r i n g (-1 se no for encontrado) .
// string14.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s("Universidade"); int i = s.find_first_of("a"); cout << i << endl; int j = s.find_first_of("bcd", 3); cout << j << endl; int k = s.find_first_not_of ("a"); cout << k << endl; } Resultado do Programa : 9 8 0

// retorna a posio da vogal 'a' // 9 // retorna a posio da primeira consoante a partir da posio 3 'd' // 8 // exibe a posio do primeiro caracter que no "aeio" 'U' // 0

Programa exemplo (115): O programa string15.cpp, a seguir, mostra a utilizao do mtodo: resize (redimensiona uma string completando com n caracteres) pertencente a classe string. Sintaxe: void nome_string.resize(int n, char ch); Onde: n o novo nmero de caracteres da string e ch o caracter que ser usado para completar o tamanho da string (ch opcional).
// string15.cpp

139

#include <iostream> #include <string> using namespace std; int main(void) { string s(10, 'a'); cout << s << endl; cout << s.size() << endl << endl; s.resize(15, 't'); cout << s << endl; cout << s.size() << endl; } Resultado do Programa : aaaaaaaaaa 10 aaaaaaaaaattttt 15

Programa exemplo (116): O programa string16.cpp, a seguir, mostra a utilizao dos mtodos: empty (verifica se uma string est vazia ou no) e getline (permite a entrada de uma string via teclado) pertencentes a classe string. Sintaxe: void nome_string.getline(fluxo, string str); Onde: fluxo (cin) um fluxo e str a string que ser lida. Sintaxe: bool nome_string.empty(void); Retorno: true vazia e false no vazia.
// string16.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s; // string vazia if (s.empty()) // verifica se a string est vazia "" cout << "Digite seu nome: "; { // cin >> s; // no aceita espaos getline(cin, s); cout << "String: " << s << " -> Tamanho: " << s. size() << endl; } else cout << "String no est vazia" << endl; // cin.getline(s,80); no funciona para string }

140

Resultado do Programa : Digite seu nome: Paulo Roberto String: Paulo Roberto -> Tamanho: 13

Programa exemplo (117): O programa string17.cpp, a seguir, mostra a utilizao do mtodo: swap (permite fazer uma troca de valores entre duas strings) pertencente a classe string. Sintaxe: nome_string.swap(string str); Onde: str uma das strings que sero trocadas (a outra nome_string ).
// string17.cpp
#include <iostream> #include <string> using namespace std; int main(void) { string s("Paulo"), r("Roberto"); cout << "s " << s << " -> r " << r << endl; r.swap(s); cout << "s " << s << " -> r " << r << endl; } Resultado do Programa : s Paulo -> r Roberto s Roberto -> r Paulo

Programa exemplo (118): O programa string18.cpp, a seguir, mostra a utilizao do mtodo: substr (permite criar uma substring de uma string) pertencente a classe string, alm de demonstrar que uma string pode ser acessada caracter a caracter, ou seja, como se fosse um vetor de caracteres. Sintaxe: string nome_string.substr(int pos); Onde: pos a posio aonde comea a substring .
// string18.cpp #include <iostream> #include <string> using namespace std; int main(void) { string s("C++ for Linux"); string r;

141

for (int i = 0;i < s.length();i++) cout << s[i]; cout << endl; r = s.substr(4); cout << r << endl; } Resultado do Programa : C++ for Linux for Linux

10.2 Classe <vector>


A classe vector um tipo de container que faz parte da STL (Standart Template Library). A STL uma biblioteca de objetos que tem as seguintes caractersticas: a) no usar polimorsmo por causa do desempenho; b) utiliza templates (classes genricas, tambm chamados de gabaritos) e c) possui trs conceitos bsicos: containers , iteradores (ponteiros inteligentes para os container's ) e cdigo genrico (templates ).

Container um grupo de objetos do mesmo tipo.


Existem trs diferentes tipos de containers : seqenciais, associativos adaptativos. Cada container possui: nome, caractersticas bsicas e iteradores. Seqenciais: vector, list e deque . Associativos: set, multiset, map e multimap. Adaptativos: stack e queue. vector: Vetores. list: Lista duplamente encadeada. deque: Fila de duas extremidades. set: Conjunto de chaves sem repetio. multiset: Conjunto de chaves com repetio. map: Conjunto de pares [chave, objeto] sem repeties. multimap: Conjunto de pares [chave, objeto] com repeties. stack: Pilha. queue: Fila. Programa exemplo (119): O programa vector1.cpp, a seguir, mostra a utilizao dos mtodos comuns a todos os containers : size, push_back , front, back, empty, max_size e clear pertencentes a classe vector . size: Retorna o nmero de elementos utilizados. Sintaxe: int nome_container.size(void); Retorno: Nmero de elementos. push_back: Insere um elemento no final do vetor. e

142

Sintaxe: void nome_container.push_back(tipo data); front: Retorna o primeiro elemento do vetor. Sintaxe : tipo_vetor nome_container. front(void); Retorno: Primeiro elemento do vetor. back: Retorna o ltimo elemento do vetor. Sintaxe : tipo_vetor nome_container. back(void); Retorno: ltimo elemento do vetor empty: Retorna true se o container estiver vazio. Sintaxe: bool nome_container.empty(void); Retorno: true se vazio e false se no estiver vazio max_size: Retorna o nmero mximo de elementos do container. Sintaxe: int nome_container.max_size(void); Retorno: Nmero mximo de elementos do vetor. clear: Apaga todos os elementos do container. Sintaxe: void nome_container.clear(void);
// vector.cpp #include <iostream> #include <vector> using namespace std; int main (void) { vector <float> v; float data ;

// declarao de um vetor

cout << "[0] - Abandonar" << endl; do { cout << "Vetor [" << v. size() << "]: "; // 0, 1, 2, 3 ... cin >> data; cin.ignore(1,'\n'); // eliminar o enter if (cin.good() and data not_eq 0) v. push_back(data); } while (cin.good() and data not_eq 0.0); cout << "Primeiro elemento do vetor = " << v. front() << endl; cout "ltimo elemento do vetor = " << v. back() << endl; cout << "Elementos: "; for (int i = 0; i < v. size();i++) cout << "v[" << i << "]= " << v[i] << ' '; // indexando um vetor cout << endl; cout << (v.empty() ? "Status: Vetor Vazio " : "Status: Vetor no Vazio ") << endl ; v.clear(); // igual a v.erase(v.begin(),v.end()); cout << (v.empty() ? "Status: Vetor Vazio " : "Status: Vetor no vazio ") << endl ; cout << endl; }

Demais mtodos bsicos utilizados pelos container's :

143

begin: Retorna um iterador para o primeiro elemento do vetor. Sintaxe: tipo_container nome_container. begin(void); Retorno: Ponteiro para o primeiro elemento. end: Retorna um iterador para o ltimo elemento do vetor. Sintaxe: tipo_container nome_container. end(void); Retorno: Ponteiro para o ltimo elemento. erase: Apaga um ou mais elementos do vetor. Sintaxe: void nome_container.erase(begin, end); Exemplo: vetor.erase(vetor.begin(),vetor.end()); pop_back: Remove o ltimo elemento do vetor. Sintaxe: void nome_container.pop_back(void); Programa exemplo (120): O programa vector2.cpp, a seguir, demonstra a utilizao da classe vector para armazenar strings da classe string.
// vector2.cpp #include <iostream> #include <string> #include <vector> using namespace std; int main (void) { vector <string> v; string data; cout << "[enter] parar" << endl; do { cout << "Palavra: "; getline(cin,data); if (cin.good() and data not_eq "") v.push_back(data); } while (cin.good() and data not_eq ""); cout << "Palavras Digitados: " << endl; for (int i = 0; i < v.size();i++) cout << v[i] << endl; int n = v.size(); cout << "Nmero de Palavras: " << n << endl; int u = n - 1; bool trocou; string tmp; do { trocou = false; for (int i = 0;i < u;i++) if (v[i] > v[i+1]) { tmp = v[i]; v[i] = v[i+1]; v[i+1] = tmp; trocou = true;

144

} u--; } while (trocou); cout << "Palavras Ordenadas: " << endl; for (int i = 0; i < v.size();i++) cout << v[i] << endl; } Resultado do Programa : [enter] parar Palavra: Carla Palavra: Debora Palavra: Ana Palavra: Beatriz Palavra: Palavras Digitados: Carla Debora Ana Beatriz Nmero de Palavras: 4 Palavras Ordenadas: Ana Beatriz Carla Debora

11. Tabela ASCII


ASCII: Americam Standard Code for Information Interchange. url: http://www.asciitable.com Para imprimir caracteres especiais atravs do C++ for Linux necessrio enviar para a tela, com a funo printf ou cout, o seguinte: Funo: Funo:

printf("%c%c%c\n", 14, 106, 15); cout << (char) 14 << (char) cod << (char) 15;

Programa exemplo (121): O programa exemplo asctable.cpp , abaixo, exibe toda a tabela ascii, inclusive com os caracteres espaciais.
// asctable.cpp #include <iostream> using namespace std; int main(void) { for (int cod = 32;cod <= 255;cod++)

145

{ cout << "Cdigo: " << cod << "-> Caracter: " << (char) 14 << (char) cod << (char) 15; cin.get(); }

Programa exemplo (122): O programa exemplo table.cpp , abaixo, mostra como imprimir um retngulo (moldura) na tela em modo texto utilizando caracteres espaciais e utilizando a biblioteca ncurses .
// table.cpp (Ubuntu 6.06 Dapper- Anjuta) // --------------------------------------------------------- includes #include <iostream> #include <string> #include <curses.h> using namespace std; // --------------------------------------------------------- constantes const int LEFT = 260; const int RIGHT = 261; const char BLACK = COLOR_BLACK; const char RED = COLOR_BLUE; const char GREEN = COLOR_GREEN; const char BROWN = COLOR_YELLOW; const char BLUE = COLOR_BLUE; const char MAGENTA = COLOR_MAGENTA; const char CYAN = COLOR_CYAN; const char WHITE = COLOR_WHITE; // --------------------------------------------------------- Classe: Janela class Janela { public: Janela(void); ~Janela(void); void clrscr(void); void gotoxy(int c, int l); void flushall(void); int Random(int n); void randomize(void); void textcolor(int cor); void textcolorlight(int cor); void Moldura(int ci, int li, int cf, int lf, int cor); }; // --------------------------------------------------------- Construtor Janela :: Janela(void) { initscr(); keypad(stdscr, TRUE); (void) nonl(); (void) cbreak();

146

(void) echo(); if (has_colors()) { start_color(); init_pair(1,COLOR_RED,COLOR_BLACK); init_pair(2,COLOR_GREEN,COLOR_BLACK); init_pair(3,COLOR_YELLOW,COLOR_BLACK); init_pair(4,COLOR_BLUE,COLOR_BLACK); init_pair(5,COLOR_CYAN,COLOR_BLACK); init_pair(6,COLOR_MAGENTA,COLOR_BLACK); init_pair(7,COLOR_WHITE,COLOR_BLACK); attrset(COLOR_PAIR(A_BOLD)); } } // --------------------------------------------------------- Destrutor Janela :: ~Janela(void) { endwin(); system("clear"); } // --------------------------------------------------------- Mtodo: clrscr void Janela :: clrscr(void) { clear(); refresh(); } // --------------------------------------------------------- Mtodo: gotoxy void Janela :: gotoxy(int c, int l) { move(l-1,c-1); refresh(); } // --------------------------------------------------------- Mtodo: flushall void Janela :: flushall(void) { getchar(); } // --------------------------------------------------------- Mtodo: Random int Janela :: Random(int n) { int t = rand() % n; return(t); } // --------------------------------------------------------- Mtodo: randomize void Janela :: randomize(void) { srand((unsigned int)time((time_t *)NULL)); }

147

// --------------------------------------------------------- Mtodo: textcolor void Janela :: textcolor(int cor) { attrset(COLOR_PAIR(cor)); } // --------------------------------------------------------- Mtodo: textcolorlight void Janela :: textcolorlight(int cor) { attrset(COLOR_PAIR(cor)+A_BOLD); } // --------------------------------------------------------- Mtodo: Moldura void Janela :: Moldura(int ci, int li, int cf, int lf, int cor) { textcolor(cor); for (int l = li+1;l < lf;l++) { gotoxy(ci,l);ldur printf("%c%c%c",14,120,15); gotoxy(cf,l); printf("%c%c%c",14,120,15); refresh(); } for (int c = ci+1;c < cf;c++) { gotoxy(c,li); printf("%c%c%c",14,113,15); gotoxy(c,lf); printf("%c%c%c",14,113,15); refresh(); } gotoxy(ci,li); printf("%c%c%c",14,108,15); gotoxy(cf,li); printf("%c%c%c",14,107,15); gotoxy(cf,lf); printf("%c%c%c",14,106,15); gotoxy(ci,lf); printf("%c%c%c",14,109,15); refresh(); } // --------------------------------------------------------- main int main(void) { Janela janela; janela.Moldura(10, 10, 20, 20, BLUE); getch(); }

Programa exemplo (123): O programa exemplo TiroAlvo.cpp , abaixo, demonstra um jogo de tiro ao alvo escrito em C++ utilizando a biblioteca ncurses .

148

Tela do Jogo
// TiroAlvo.cpp (Ubuntu 6.06 Dapper- Anjuta) // Autor: Paulo Roberto Gomes Luzzardi // Data: 11/08/2006 // --------------------------------------------------------- includes #include <iostream> #include <string> #include <curses.h> using namespace std; // --------------------------------------------------------- constantes const char ESC = 27; const char SPACE = 32; const int DOWN = 258; const int UP = 259; const int LEFT = 260; const int RIGHT = 261; const char BLACK = COLOR_BLACK; const char RED = COLOR_BLUE; const char GREEN = COLOR_GREEN; const char BROWN = COLOR_YELLOW; const char BLUE = COLOR_BLUE; const char MAGENTA = COLOR_MAGENTA; const char CYAN = COLOR_CYAN; const char WHITE = COLOR_WHITE; // --------------------------------------------------------- Classe: Janela class Janela { public: Janela(void); ~Janela(void); void clrscr(void); void gotoxy(int c, int l); void flushall(void); int Random(int n); void randomize(void); void textcolor(int cor); void textcolorlight(int cor); }; // --------------------------------------------------------- Construtor Janela :: Janela(void) { initscr(); keypad(stdscr, TRUE); (void) nonl(); (void) cbreak(); (void) echo(); if (has_colors())

149

{ start_color(); init_pair(1,COLOR_RED,COLOR_BLACK); init_pair(2,COLOR_GREEN,COLOR_BLACK); init_pair(3,COLOR_YELLOW,COLOR_BLACK); init_pair(4,COLOR_BLUE,COLOR_BLACK); init_pair(5,COLOR_CYAN,COLOR_BLACK); init_pair(6,COLOR_MAGENTA,COLOR_BLACK); init_pair(7,COLOR_WHITE,COLOR_BLACK); attrset(COLOR_PAIR(A_BOLD)); } } // --------------------------------------------------------- Destrutor Janela :: ~Janela(void) { endwin(); system("clear"); } // --------------------------------------------------------- Mtodo: clrscr void Janela :: clrscr(void) { clear(); refresh(); } // --------------------------------------------------------- Mtodo: gotoxy void Janela :: gotoxy(int c, int l) { move(l-1,c-1); refresh(); } // --------------------------------------------------------- Mtodo: flushall void Janela :: flushall(void) { getchar(); } // --------------------------------------------------------- Mtodo: Random int Janela :: Random(int n) { int t = rand() % n; return(t); } // --------------------------------------------------------- Mtodo: randomize void Janela :: randomize(void) { srand((unsigned int)time((time_t *)NULL)); } // --------------------------------------------------------- Mtodo: textcolor

150

void Janela :: textcolor(int cor) { attrset(COLOR_PAIR(cor)); } // --------------------------------------------------------- Mtodo: textcolorlight void Janela :: textcolorlight(int cor) { attrset(COLOR_PAIR(cor)+A_BOLD); } // --------------------------------------------------------- Classe: Tela class Tela { public: void Monta_Tela(void); };

// --------------------------------------------------------- Monta_Tela void Tela :: Monta_Tela(void) { Janela janela; janela.textcolor(CYAN); janela.gotoxy(33,1); printw("Tiro ao Alvo",199); janela.gotoxy(2,22); printw("[ESC] Abandona"); refresh(); } // ---------------------------------------------------- Classe: Jogo class Jogo { int c, l; int coluna, linha; Janela janela; public: { Jogo(int col, int lin) c = col; l = lin; } void Jogar(void); void Insere_Alvo(void); bool Testa_Alvo(void); }; // ---------------------------------------------------- Mtodo: Jogar void Jogo :: Jogar(void) { Tela tela;

// torre // alvo

151

int row, col; bool sai; int tecla; getmaxyx(stdscr, row, col); // tamanho do terminal do { janela.textcolor(WHITE); janela.gotoxy(60,23); printw("| Lin: %d | Col: %d |",l,c); janela.gotoxy(60,24); printw("| row: %d | col: %d |",row,col); refresh(); tela.Monta_Tela(); sai = false; Insere_Alvo(); janela.textcolor(WHITE); janela.gotoxy(20,23); printw("Status: "); do { janela.gotoxy(c,l); do { tecla = getch(); } while (tecla not_eq LEFT and tecla not_eq RIGHT and tecla not_eq ESC and tecla not_eq SPACE); for (int j = l-1;j >= 3;j--) { janela.textcolor(RED); janela.gotoxy(c,j); printw(" "); } janela.gotoxy(60,23); printw("| Lin: %d | Col: %d |",l,c); janela.gotoxy(c,l); if (tecla == ESC) sai = true; switch (tecla) { case LEFT: c--; if (c < 1) c = 80; break; case RIGHT: c++; if (c > 80) c = 1; break; case SPACE: for (int j = l-1;j >= 2;j--) { janela.textcolor(RED); janela.gotoxy(c,j); printw("."); } if (Testa_Alvo()) { janela.textcolor(BROWN); janela.gotoxy(30,23); printw("Acertou o Alvo"); Insere_Alvo(); } else { janela.textcolor(RED);

152

} break; } } while (not sai); janela.gotoxy(20,22); printw("Jogar Novamente [S/n]? "); do { tecla = getch(); } while(not strchr("SsNn",tecla) and tecla not_eq ESC); } while (strchr("Ss",tecla) and tecla not_eq ESC);

janela.gotoxy(30,23); printw("Errou o Alvo ");

// --------------------------------------------------------- Insere_Alvo void Jogo :: Insere_Alvo(void) { int col, row; getmaxyx(stdscr, row, col); // tamanho do terminal coluna = 1 + janela.Random(col); linha = 2; janela.textcolor(RED); janela.gotoxy(coluna,linha); printf("%c%c%c",14,97,15); refresh(); } // --------------------------------------------------------- Testa_Alvo bool Jogo :: Testa_Alvo(void) { if (coluna == c) return(true); else return(false); } // ------------------------------------------ Programa Principal int main(void) { Janela janela; Jogo jogo(40,20); jogo.Jogar(); }

12. Glossrio
Objetos: So entidades lgicas que possuem atributos (variveis) e mtodos (funes) que manipulam estas propriedades. Atributos: So variveis definidas e declaradas para cada classe que definem as propriedades ou caractersticas de um objeto.

153

Mtodos: So funes definidas pelo programador que serviro para manipular os atributos de uma classe. Classe: um tipo de dado definido por class ou struct. Mensagens: So as chamadas dos mtodos (chamada das funes), ou seja, solicitaes enviadas objetos para alterar seu estado ou retornar um valor. Instncia: Os objetos so instncias de uma classe. Abstrao: Caracterstica onde os objetos devem representar dados do mundo real. Encapsulamento: Caracterstica onde os objetos possuem internamente atributos e mtodos agrupados no mesmo local, onde os mtodos manipulam os atributos. Herana: Processo pelo qual uma classe de objetos pode adquirir as propriedades de outra classe de objetos, podendo ser: simples ou mltipla. Herana simples: Quando uma classe herda as propriedades de uma nica classe base. Herana mltipla: Quando uma classe herda as propriedades de mais de uma classe base. Polimorfismo: a capacidade de objetos diferentes reagirem segundo a sua funo a uma ordem padro, ou seja, o nome de um objeto pode ser utilizado para vrios propsitos ligeiramente diferentes. ... uma interface, vrios mtodos ... . O polimorfismo ocorre na sobrecarga de funes e sobrecarga de operadores .

Templates (gabaritos): uma funo genrica em que o tipo dos dados (dos parmetros e do retorno da funo) so definidos em tempo de compilao.
Argumentos: Parmetros formais de funes ou mtodos. Construtor: Mtodo especial, que tem o mesmo nome da classe, que executado quando o objeto declarado servindo para inicializar os atributos de um objeto. Destrutor: M t o d o e s p e c i a l , q u e t e m o m e s m o n o m e d a c l a s s e m a i s u m ~, que executado quando o programa termina ou quando o objeto desalocado. Classe base: Classe principal que possui as caractersticas bsicas de uma classe de objetos (propriedades bsicas). Classe derivada: Classe construda a partir de uma ou mais classes bsicas. Possui as demais caractersticas de uma determinada classe de objetos (propriedades diferentes). Sobrecarga de funes : Duas ou mais funes, com mesmo nome, recebem parmetros de tipos diferente podendo ainda ter retorno diferentes.

154

Sobrecarga de operadores : Caracterstica da orientao objetos onde um operador (aritmtico, relacional, lgico ou bit bit) passa a ter novas funes (caractersticas) sem perder a funo bsica. Ponteiros: Varivel que possui como valor um endereo de memria. Referncias: So variveis que ficam vinculadas diretamente localizao de memria de uma expresso. Uma referncia no alocada na memria, ou seja, no ocupa espao de memria. Hierarquia de objetos: um diagrama que exibe o relacionamento entre objetos ou classes de objetos. Funes amigas: Permitem o compartilhamento de mtodos e atributos para mtodos que no fazem parte de uma classe. Funo virtual: Mtodo especial executado por meio de uma referncia a uma classe base e carregado dinamicamente em tempo de execuo em classes derivadas.

this: Ponteiro criado automaticamente que aponta para cada mtodo de uma classe. utilizado para solucionar conitos entre identificadores. Threads : Representam uma seqncia de instrues nica (processo), executada paralelamente a outras seqncias de instrues, tanto por particionamento do tempo, como por multiprocessamento (ou multithread ). Uma thread uma forma de um programa dividir a si mesmo em duas ou mais tarefas simultneas.

155

13. Arquivos em C++


Em C++, um arquivo tratado como um fluxo de bytes, ou seja, no possui formato definido, o programador deve criar um formato aos dados. O fluxo para trabalhar com arquivos < fstream.h > ou simplesmente < fstream >.
Modo ios :: app ios :: ate ios :: in ios :: out ios :: trunc ios :: binary Descrio Insere no fim do arquivo. Abre um arquivo para gravao no fim do arquivo. Abre um arquivo de entrada. Abre um arquivo de sada. Elimina o contudo do arquivo, se ele existe. Abre um arquivo binrio para entrada ou sada.

Programa exemplo (124): O programa exemplo gravar.cpp , abaixo, demonstra a gravao de palavras (strings) em um arquivo qualquer.
// gravar.cpp #include <iostream> #include <fstream> #include <string> using namespace std; int main (void) { ofstream file; string palavra; char nome[256];

// cria o arquivo file para gravao (out)

cout << "Nome do Arquivo: "; cin >> nome; file.open(nome, ios::app); // abre o arquivo, insere no fim if (file.fail()) { cout << "ERRO: Arquivo Inexistente" << endl; return(1); } cin.ignore(1,'\n'); // limpa o buffer de teclado do { cout << "Palavra: "; getline(cin,palavra); // leitura de uma string via teclado if (not palavra.empty()) file << palavra << endl; // grava uma palavra no arquivo } while (not palavra.empty()); file.close() ; // fecha o arquivo }

Programa exemplo (125): O programa exemplo ler.cpp, abaixo, demonstra a leitura de palavras (string) de um arquivo qualquer.
// ler.cpp

156

#include <iostream> #include <fstream> #include <string> using namespace std; int main (void) { ifstream file; string palavra; char nome[256];

// liga o arquivo file para leitura (in)

cout << "Nome do Arquivo: "; cin >> nome; file.open(nome); if (file.fail()) { cout << "ERRO: Arquivo Inexistente" << endl; return(1); } cin.ignore(1,'\n'); do { getline( file,palavra); // leitura de uma string do arquivo file cout << "Palavra: " << palavra << endl; } while (not palavra.empty()); file.close() ; }

Programa exemplo (126): O programa exemplo gravar_texto.cpp , abaixo, demonstra a gravao de texto (linha a linha) em um arquivo qualquer.
// gravar_texto.cpp #include <iostream> #include <fstream> #include <string> using namespace std; #define end_of_line '\a' int main (void) { ofstream file; string linha; char nome[256];

// cria o arquivo file para gravao ( out)

cout << "Nome do Arquivo: "; cin >> nome; file.open(nome, ios::app); // abre o arquivo, insere no fim if (file.fail()) { cout << "ERRO: Arquivo Inexistente" << endl; return(1); } cin.ignore(1,'\n'); // limpa o buffer de teclado cout << "Digite um texto qualquer: " << endl; do { getline(cin, linha); // leitura de uma string via teclado

157

if (not linha.empty()) file << linha << end_of_line << endl; } while (not linha.empty()); file.close() ; // fecha o arquivo }

// grava uma palavra no arquivo

Programa exemplo (127): O programa exemplo ler_texto.cpp , abaixo, demonstra a leitura de um arquivo contento texto, caracter por caracter.
// ler_texto.cpp #include <iostream> #include <fstream> #include <string> #define end_of_line '\a' using namespace std; int main (void) { ifstream file; // liga o arquivo file para leitura ( in) string linha; char nome[256], str[256]; cout << "Nome do Arquivo: "; cin >> nome; file.open(nome); if (file.fail()) { cout << "ERRO: Arquivo Inexistente" << endl; return(1); } cin.ignore(1,'\n'); do { getline( file,linha); // leitura de uma linha do arquivo strcpy(str,linha.c_str()); for (int i = 0;i < strlen(str);i++) if (str[i] == end_of_line) cout << endl; else cout << str[i]; } while (not linha.empty()); file.close() ; } // caracter finalizador, escolher um

Programa exemplo (128): O programa exemplo gravar_string.cpp , abaixo, demonstra a gravao de strings (classe string) em um arquivo qualquer.
// gravar_string.cpp #include <iostream> #include <fstream> #include <string> using namespace std; int main (void)

158

{ ofstream file; // cria o arquivo file para gravao ( out) char nome[256], palavra[31]; cout << "Nome do Arquivo: "; cin >> nome; file.open(nome); // abre o arquivo if (file.fail()) { cout << "ERRO: Arquivo Inexistente" << endl; return(1); } cin.ignore(1,'\n'); // limpa o buffer de teclado do { cout << "Palavra: "; cin.getline(palavra, 30); // leitura de uma string via teclado if (strcmp(palavra,"") not_eq 0) file << palavra << endl; // grava uma palavra no arquivo } while (strcmp(palavra,"") not_eq 0); file.close() ; // fecha o arquivo } Resultado do Programa : Nome do Arquivo: palavra.dat Palavra: abacate Palavra: abacaxi Palavra: ameixa Palavra: laranja Palavra: bergamota Palavra: pitanga Palavra:

Programa exemplo (129): O programa exemplo ler_string.cpp , abaixo, demonstra a leitura de strings (classe string) exibindo a posio do ponteiro get em um arquivo qualquer [existe um ponteiro put (para o fluxo ofstream ) e o ponteiro get (para o fluxo ifstream )].
// ler_string.cpp #include <iostream> #include <fstream> #include <string> using namespace std; int main (void) { ifstream file; // abre o arquivo file para leitura ( in) char nome[256],palavra[31]; cout << "Nome do Arquivo: "; cin >> nome; file.open(nome); // abre o arquivo if (file.fail()) { cout << "ERRO: Arquivo Inexistente" << endl;

159

return(1); } cin.ignore(1,'\n'); // limpa o buffer de teclado long pos_get; do { pos_get = file.tellg(); // retorna a posio do ponteiro get file >> palavra; if (file) cout << "Posio: " << pos_get << " -> Palavra: " << palavra << endl; } while ( file); file.close() ; // fecha o arquivo } Resultado do Programa : Nome do Arquivo: palavra.dat Posio: 0 -> Palavra: abacate Posio: 7 -> Palavra: abacaxi Posio: 15 -> Palavra: ameixa Posio: 22 -> Palavra: laranja Posio: 30 -> Palavra: bergamota Posio: 40 -> Palavra: pitanga

Programa exemplo (130): O programa exemplo gravar_int.cpp , abaixo, demonstra a gravao de nmeros inteiros em um arquivo qualquer.
// gravar_int.cpp #include <iostream> #include <fstream> #include <string> using namespace std; int main (void) { ofstream file; int idade; char nome[256];

// fluxo de gravao (out)

cout << "Nome do Arquivo: "; cin >> nome; file.open(nome, ios::app); // abre e anexa no fim do arquivo if (file.fail()) { cout << "ERRO: Arquivo no Existe" << endl; return(1); } cin.ignore(1,'\n'); // elimina um enter do buffer de teclado do { cout << "Idade: "; cin >> idade; // leitura de uma idade via teclado if (idade not_eq 0) file << idade << endl; // grava uma idade no arquivo } while (idade not_eq 0); file.close() ; }

160

Programa exemplo (131): O programa exemplo ler_int.cpp , abaixo, demonstra a leitura de nmeros inteiros em um arquivo qualquer.
// ler_int.cpp #include <iostream> #include <fstream> #include <string> using namespace std; int main (void) { ifstream file; int idade; char nome[256];

// fluxo de leitura

cout << "Nome do Arquivo: "; cin >> nome; file.open(nome); if (file.fail()) { cout << "ERRO: Arquivo Inexistente" << endl; return(1); } cin.ignore(1,'\n'); do { file >> idade; // leitura de uma idade do arquivo if (file) cout << "Idade: " << idade << endl; } while ( file); file.close() ; }

Programa exemplo (132): O programa exemplo gravar_float.cpp , abaixo, demonstra a gravao de nmeros reais (float) em um arquivo qualquer.
// gravar_float.cpp #include <iostream> #include <fstream> #include <string> using namespace std; int main (void) { ofstream file; float salario; char nome[256];

// fluxo de gravao ( out)

cout << "Nome do Arquivo: "; cin >> nome; file.open(nome, ios::app); // abre e anexa no fim do arquivo if (file.fail()) { cout << "ERRO: Arquivo no Existe" << endl; return(1);

161

} cin.ignore(1,'\n'); do { cout << "Salrio: "; cin >> salario; if (salario not_eq 0.0) file << salario << endl; } while (salario not_eq 0.0); file.close() ; }

Programa exemplo (133): O programa exemplo ler_float.cpp , abaixo, demonstra a leitura de nmeros reais (float) em um arquivo qualquer.
// ler_float.cpp #include <iostream> #include <fstream> #include <string> using namespace std; int main (void) { ifstream file; float salario; char nome[256];

// fluxo de leitura

cout << "Nome do Arquivo: "; cin >> nome; file.open(nome); if (file.fail()) { cout << "ERRO: Arquivo Inexistente" << endl; return(1); } cin.ignore(1,'\n'); do { file >> salario; if (file) cout << "Salrio: " << salario << endl; } while ( file); // verdadeiro enquanto existir dados file.close() ; }

Programa exemplo (134): O programa exemplo gravar_struct.cpp , abaixo, demonstra a gravao de uma estrutura ( struct) com: nome (string), idade (int), mesada (float) e sexo (char) em um arquivo qualquer.
// gravar_struct.cpp #include <iostream> #include <fstream> #include <string> using namespace std; struct REG {

162

string nome; int idade; float mesada; char sexo; } reg; int main (void) { ofstream file; char nome[256], ch;

// [M]asculino ou [F]eminino

// fluxo de gravao ( out)

cout << "Nome do Arquivo: "; cin >> nome; file.open(nome, ios::app); // abre e anexa no fim do arquivo if (file.fail()) { cout << "ERRO: Arquivo no Existe" << endl; return(1); } cin.ignore(1,'\n'); do { cout << "Nome: "; getline(cin,reg.nome); cout << "Idade: "; cin >> reg.idade; cout << "Mesada: "; cin >> reg.mesada; cout << "Sexo [M]asculino ou [F]eminino: "; do { reg.sexo = cin.get(); } while (not strchr("FfMm",reg.sexo)); file << reg.nome << endl; file << reg.idade << endl; file << reg.mesada << endl; file << reg.sexo << endl; cout << "Continua [S/N]? "; do { ch = cin.get(); } while (not strchr("SsNn",ch)); cin.ignore(5,'\n'); } while (strchr("Ss",ch)); file.close() ; } Resultado do Programa : Nome do Arquivo: pessoas.dat <enter> Nome: Paulo Roberto <enter> Idade: 44 <enter> Mesada: 1234.56 <enter> Sexo: m Continua [S/N/? s Nome: Adriane Maria <enter> Idade: 37 <enter> Mesada: 2345.67 <enter> Sexo: f Continua [S/N/? s Nome: Paola de Freitas Luzzardi <enter> Idade: 7 <enter>

163

Mesada: 12.34 <enter> Sexo: f Continua [S/N/? n

Programa exemplo (135): O programa exemplo ler_struct.cpp , abaixo, demonstra a leitura de uma estrutura ( struct) com: nome (string), idade (int), mesada (float) e sexo (char) em um arquivo qualquer.
// lerr_struct.cpp #include <iostream> #include <fstream> #include <string> using namespace std; struct REG { string nome; int idade; float mesada; char sexo; } reg; int main (void) { ifstream file; char nome[256], ch;

// [M]asculino ou [F]eminino

// fluxo de leitura (in)

cout << "Nome do Arquivo: "; cin >> nome; file.open(nome); // abre o arquivo if (file.fail()) { cout << "ERRO: Arquivo no Existe" << endl; return(1); } cin.ignore(1,'\n'); do { getline(file,reg.nome); file >> reg.idade; file >> reg.mesada; file >> reg.sexo; file.ignore(1,'\n'); cout << "Nome: " << reg.nome << endl; cout << "Idade: " << reg.idade << endl; cout << "Mesada: " << reg.mesada << endl; cout << "Sexo: " << reg.sexo << endl; } while (file); // verdadeiro enquanto tiver dados file.close() ; } Resultado do Programa : Nome do Arquivo: pessoas.dat Nome: Paulo Roberto Idade: 44 Mesada: 1234.56 Sexo: m

164

Nome: Adriane Maria Idade: 37 Mesada: 2345.67 Sexo: f Nome: Paola de Freitas Luzzardi Idade: 7 Mesada: 12.34 Sexo: f

Programa exemplo (136): O programa exemplo gravar_object.cpp , abaixo, demonstra a gravao de um objeto ( class) que possui dois atributos inteiros: x e y em um arquivo qualquer.
// gravar_objeto.cpp #include <iostream> #include <fstream> #include <string> #include <vector> using namespace std ; class Data { int x,y; public : Data(int tx, int ty) { x = tx; y = ty; } friend istream &operator >> (istream &file, Data &data); friend ofstream &operator << (ofstream &file, Data *&data); }; int main (void) { cout << "Nome do Arquivo: "; string nome; // ou char nome[256]; getline(cin, nome); ofstream file(nome.c_str()); // converte string para char * if (not file) { cout << "ERRO: Arquivo no Existe\n"; exit(1) ; } vector <Data> data; Data objeto(0,0); Data *pobjeto ; pobjeto = &objeto; cout << "[CTRL] + [D] para Sair" << endl; while (cin >> objeto) { file << pobjeto; data.push_back(objeto); }; file.close(); }

165

// ---------------------------------------------------- Sobrecarga do operador >> (cin) istream &operator >> (istream &file, Data &data) { cout << "x: "; file >> data.x; cout << "y: "; file >> data.y; return(file); } // ---------------------------------------------------- Sobrecarga do operador << (cout) ofstream &operator << (ofstream &file, Data *&data) { file.write((char*) data, sizeof(Data)); return(file); } Resultado do Programa : Nome do Arquivo: objeto.dat [CTRL] + [D] para Sair x: 1 y: 2 x: 3 y: 4 x: 5 y: 6 x: 7 y: 8 ... CTRL+D

Programa exemplo (137): O programa exemplo ler_object.cpp , abaixo, demonstra a leitura de um objeto que possui dois atributos inteiros: x e y em um arquivo qualquer.
// carrega_objeto.cpp #include <iostream> #include <fstream> #include <string> #include <vector> using namespace std; class Data { int x, y; public : Data(int tx, int ty) { x = tx; y = ty; } friend ostream &operator << (ostream &file, Data &data); friend ifstream &operator >> (ifstream &file, Data *&data); };

166

int main (void) { vector <Data> data; Data objeto(0,0); Data * ptobjeto = &objeto; cout << "Nome do Arquivo de Objetos: "; string nome; getline (cin, nome); ifstream file (nome.c_str()); if (not file) { cout << "ERRO: Arquivo no Existe\n"; exit (1); } while (file >> ptobjeto) { cout << objeto; data.push_back(objeto); } file.close(); } // ------------------------------------------------- Sobrecarga do Operador << (cout) ostream &operator << (ostream &file, Data &data) { file << "(x = " << data.x; file << " ,y = " << data.y << ")" << endl; return(file); } // ------------------------------------------------- Sobrecarga do Operador >> (cin) ifstream &operator >> (ifstream &file, Data *&data) { file.read ((char*)data , sizeof(Data)); return(file); } Resultado do Programa : Nome do Arquivo de Objetos: objeto.dat (x = 1 ,y = 2) (x = 3 ,y = 4) (x = 5 ,y = 6) (x = 7 ,y = 8)

167

14. Programas em C++


Programa exemplo (138): O programa exemplo calc.cpp , abaixo, demonstra a definio de uma classe Calculadora que possui as seguintes operaes:
[+] Adio [-] Subtrao [*] Multiplicao [/] Diviso [R] Raiz Quadrada [P] Potncia [I] Inverso [S] Seno [C] Cosseno [T] Tangente // Calc.cpp #include <iostream> #include <iomanip> #include <math.h> using namespace std; #define PI 4*atan(1) class Calculadora { private: double x,y,resp; char op; int erro; private: void Add(void) { resp = x + y; erro = 0; } void Sub(void) { resp = x - y; erro = 0; } void Mult(void) { resp = x * y; erro = 0; } void Div(void) { if (y not_eq 0) { resp = x / y; erro = 0; } else erro = 1; }

// Diviso por zero

168

void Raiz(void) { if (x >= 0) { resp = sqrt(x); erro = 0; } else erro = 2; // Raiz Negativa } void Pot(void) { resp = pow(x,y); erro = 0; } void Inv(void) { if (x not_eq 0) { resp = 1 / x; erro = 0; } else erro = 1; // Diviso por zero } void Sen(void) { float rads = x * PI / 180.0; // converte de graus para radianos resp = sin(rads); erro = 0; } void Cos(void) { float rads = x * PI / 180.0; resp = cos(rads); erro = 0; } void Tan(void) { float rads = x * PI / 180.0; if (x == 90.0 or x == 270.0) erro = 3; // Tangente Infinita else { resp = tan(rads); erro = 0; } } public: void Entrada(void) { cout << "Digite um valor: "; cin >> x; cout << "Operao:\n[+] Adio\n[-] Subtrao\n[*] Multiplicao\n[/] Diviso\n"; cout << "[R] Raiz Quadrada\n[P] Potncia\n[I] Inverso\n"; cout << "[S] Seno\n[C] Cosseno\n[T] Tangente\n"; cout << "Qual a sua opo? "; do {

169

};

op = cin.get(); } while (not strchr("+-*/RrPpIiSsCcTt",op)); if (strchr("+-*/Pp",op)) { cout << "Digite outro valor: "; cin >> y; } } void Calcula(void) { switch (op) { case '+': Add(); break; case '-': Sub(); break; case '*': Mult(); break; case '/': Div(); break; case 'R': case 'r': Raiz(); break; case 'P': case 'p': Pot(); break; case 'I': case 'i': Inv(); break; case 'S': case 's': Sen(); break; case 'C': case 'c': Cos(); break; case 'T': case 't': Tan(); break; } } void Exibe(void) { if (not erro) cout << "Resposta: " << setprecision(4) << resp << endl; else if (erro == 1) cout << "ERRO: Diviso por Zero" << endl; else if (erro == 2) cout << "ERRO: Raiz Negativa" << endl; else if (erro == 3) cout << "ERRO: Tangente Infinita" << endl; }

int main(void) { Calculadora calc; char tecla;

170

do { calc.Entrada(); calc.Calcula(); calc.Exibe(); cin.ignore(1,'\n'); cout << "Novo Clculo [S/N]? "; do { tecla = cin.get(); } while (not strchr("SsNn",tecla)); } while (strchr("Ss",tecla)); } Resultado do Programa : Digite um valor: 45 Operao: [+] Adio [-] Subtrao [*] Multiplicao [/] Diviso [R] Raiz Quadrada [P] Potncia [I] Inverso [S] Seno [C] Cosseno [T] Tangente Qual a sua opo? s Resposta: 0.7071 Novo Clculo [S/N]? s Digite um valor: 45 Operao: [+] Adio [-] Subtrao [*] Multiplicao [/] Diviso [R] Raiz Quadrada [P] Potncia [I] Inverso [S] Seno [C] Cosseno [T] Tangente Qual a sua opo? c Resposta: 0.7071 Novo Clculo [S/N]? s Digite um valor: -16 Operao: [+] Adio [-] Subtrao [*] Multiplicao [/] Diviso [R] Raiz Quadrada [P] Potncia [I] Inverso [S] Seno [C] Cosseno [T] Tangente Qual a sua opo? r ERRO: Raiz Negativa

171

Novo Clculo [S/N]? s Digite um valor: 90 Operao: [+] Adio [-] Subtrao [*] Multiplicao [/] Diviso [R] Raiz Quadrada [P] Potncia [I] Inverso [S] Seno [C] Cosseno [T] Tangente Qual a sua opo? t ERRO: Tangente Infinita Novo Clculo [S/N]? s Digite um valor: 2 Operao: [+] Adio [-] Subtrao [*] Multiplicao [/] Diviso [R] Raiz Quadrada [P] Potncia [I] Inverso [S] Seno [C] Cosseno [T] Tangente Qual a sua opo? i Resposta: 0.5 Novo Clculo [S/N]? s Digite um valor: 3 Operao: [+] Adio [-] Subtrao [*] Multiplicao [/] Diviso [R] Raiz Quadrada [P] Potncia [I] Inverso [S] Seno [C] Cosseno [T] Tangente Qual a sua opo? p Digite outro valor: 2 Resposta: 9 Novo Clculo [S/N]? n

Programa exemplo (139) : O programa exemplo juliano.cpp , abaixo, demonstra o Clculo do Dia Juliano, ou seja, por este clculo possvel descobrir que dia da semana (segunda, tera, quarta, quinta, sexta, sbado ou domingo) caiu ou cair uma determinada data (dia, mes e ano). Como calcular o Dia Juliano : http://www.rio.rj.gov.br/planetario/cent_pesq_calc.htm
// juliano.cpp

172

// --------------------------- Prototypes #include <iostream> #include <string> using namespace std; // --------------------------- Classe: Data class Data { int dia, mes, ano; public:

};

void Entrada_Data(void); void Exibe_Data_Extenso(void); int Calcula_Dia_Juliano(void); void Exibe_Dia_Semana(int resto);

// -------------------------------- Mtodo: Le_Atributos void Data :: Entrada_Data(void) { do { cout << "Dia [1..31]: "; cin >> dia; } while (dia < 1 or dia > 31); do { cout << "Mes [1..12]: "; cin >> mes; } while (mes < 1 or mes > 12); do { cout << "Ano [1900..2999]: "; cin >> ano; } while (ano < 1900 or ano > 2999); } // -------------------------------- Mtodo: Calcula_Dia_Juliano int Data :: Calcula_Dia_Juliano(void) { int a, b, c; long int d, e, dj; int dd = dia, mm = mes, aa = ano; double resp; if (mm < 3) { aa--; mm += 12; } a = aa / 100; b = a / 4; c = 2 - a + b; resp = 365.25 * (aa + 4716); d = (long int) resp; resp = 30.6001 * (mm + 1); e = (long int) resp; dj = d + e + dd + c - 1524;

173

int resto = dj % 7; return(resto); } // -------------------------------- Mtodo: Exibe_Dia_Semana void Data :: Exibe_Dia_Semana(int resto) { string nome[] = {"SEGUNDA-FEIRA","TERA-FEIRA","QUARTA-FEIRA", "QUINTA-FEIRA","SEXTA-FEIRA","SBADO","DOMINGO"}; cout << "\nDia da Semana: " << nome[resto] << endl; } // -------------------------------- Mtodo: Exibe_Data_Extenso void Data :: Exibe_Data_Extenso(void) { string nome[] = {"janeiro","fevereiro","maro","abril","maio","junho","julho", "agosto","setembro","outubro","novembro","dezembro"}; cout << "Data: " << dia << " de " << nome[mes - 1] << " de " << ano; } // --------------------------- Programa Principal int main(void) { Data data; char tecla; cout << "Clculo do Dia Juliano (Dia da Semana)" << endl; do { data.Entrada_Data(); data.Exibe_Data_Extenso(); int resto = data.Calcula_Dia_Juliano(); data.Exibe_Dia_Semana(resto); cout << "Novo Clculo [S/n]?"; do { tecla = cin.get(); } while (not strchr("SsNn", tecla)); } while (strchr("Ss", tecla)); } Resultado do Programa : Clculo do Dia Juliano (Dia da Semana) Dia [1..31]: 16 Mes [1..12]: 8 Ano [1900..2999]: 2006 Data: 16 de agosto de 2006 Dia da Semana: QUARTA-FEIRA Novo Clculo [S/n]?s Dia [1..31]: 10 Mes [1..12]: 2 Ano [1900..2999]: 1962 Data: 10 de fevereiro de 1962 Dia da Semana: SBADO Novo Clculo [S/n]?n

Programa exemplo (140): O programa exemplo cpf.cpp , abaixo, demonstra como calcular

174

os dgitos verificadores de um cpf qualquer. Como calcular o CPF: http://www.geocities.com/CapeCanaveral/4274/cgcancpf.htm


// cpf.cpp #include <iostream> #include <string> #include <cctype> using namespace std; // -------------------------------- classe: CPF class CPF { char cpf[15]; int n, final; public: void Entrada_CPF(void); int Valida_CPF(void); void Exibe_CPF(void); }; // -------------------------------- Mtodo: Entrada_CPF void CPF :: Entrada_CPF(void) { do { cout << "Cpf [99999999999]: "; cin.getline(cpf,12); n = strlen(cpf); if (n not_eq 11 and n not_eq 10) cout << "Formato: 9 ou 11 dgitos numricos" << endl; if (n == 10) { n--; cpf[n] = (char) NULL; } } while (n not_eq 11 and n not_eq 10); } // -------------------------------- Mtodo: Valida_CPF int CPF :: Valida_CPF(void) { int valor = 0, fator; for (int i = 0;i < 9;i++) valor = valor + (cpf[i] - 48) * (10 - i); fator = valor / 11; fator = fator * 11; valor = valor - fator; int digit1 = valor < 2 ? 0 : 11 - valor; valor = 0; for (int i = 0;i < 9;i++) valor = valor + (cpf[i] - 48) * (11 - i); valor = valor + digit1 * 2;

175

fator = valor / 11; fator = fator * 11; valor = valor - fator; int digit2 = valor < 2 ? 0 : 11 - valor; final = digit1 * 10 + digit2; if (digit1 == cpf[9] - 48 and digit2 == cpf[10] - 48) return(1); else return(0); } // -------------------------------- Mtodo: Exibe_CPF void CPF :: Exibe_CPF(void) { int t = 0; cout << "Dgito Verificador: "; if (final >= 10) cout << final << endl; else cout << "0" << final << endl; if (n == 11) { cout << "Cpf Digitado: "; for (int i = 0;i <= 7;i++) { cout << cpf[i]; t++; if (t == 3) { t = 0; cout << "."; } } cout << cpf[8] << "-"; for (int i = 9;i <= 10;i++) cout << cpf[i]; cout << endl; } } // -------------------------------- Programa Principal int main(void) { CPF cpf; char tecla; do {

cpf.Entrada_CPF(); if (cpf.Valida_CPF()) cout << "Status: CPF Vlido" << endl; else cout << "Status: CPF Invlido" << endl; cpf.Exibe_CPF(); cout << "Continua [S/n]?"; do { tecla = cin.get(); } while (not strchr("SsNn",tecla));

176

cout << endl; cin.ignore(1,'\n'); } while (strchr("Ss",tecla)); } Resultado do Programa : Cpf [99999999999]: 123456789 Formato: 9 ou 11 dgitos numricos Status: CPF Invlido Dgito Verificador: 09 Continua [S/n]?s Cpf [99999999999]: 12345678909 Status: CPF Vlido Dgito Verificador: 09 Cpf Digitado: 123.456.789-09 Continua [S/n]?n

15. Outros conceitos em C++


15.1 Mtodos const
Se o programador quiser definir um mtodo que no possa alterar os atributos do objeto, ele deve ser declarado como const. Desta forma, o compilador no permite que o mtodo altere o estado do objeto, ou seja, o mtodo no pode alterar os atributos do objeto. Modo de usar:
class Teste { int n; public: Teste(int tn) { n = tn; } void Exibe(void) const { cout << n = << n << endl; } };

// mtodo constante

15.2 Mtodos static


Existem dois tipos de atributos: da classe e de objeto. Para trabalhar com um mtodo que s acessa atributos estticos da classe, pode-se declar-lo como sendo um mtodo esttico. Desta forma possvel passar informaes de um objeto para outro atravs de atributos e mtodos estticos da classe.

177

Se um mtodo esttico e pblico, pode ser acessado sem que exista um objeto da classe, basta apenas referenciar: nome da classe, operador de resoluo de escopo (::) e o nome do mtodo.

tipo_varivel varivel = nome_classe :: nome_mtodo_esttico();


Programa exemplo (141): O programa exemplo metodo_static.cpp , abaixo, demonstra a utilizao de um mtodo esttico.
// metodo_static.cpp #include <iostream> using namespace std; class Math { static int n; public: static int Consulta(void) { return(n); } }; int Math :: n = 7; int main(void) { int x; x = Math :: Consulta(); cout << "x = " << x << endl; } // acessando um atributo esttico atravs de um mtodo esttico // sem ser atravs de um objeto

// ... atributo da classe, coletivo para todos os objetos

// inicializao do atributo da classe (tem que ser fora da classe)

15.3 Referncias para Ponteiros


Em C++ possvel utilizar referncias para ponteiros, ou seja, a referncia no alocada na memria, apenas uma referncia a uma posio de memria. Programa exemplo (142): O programa exemplo ref.cpp, abaixo, demonstra a utilizao de referncia para ponteiro.
// ref.cpp #include <iostream> using namespace std; int main(void) { int n = 7; int *p = &n; int &ref_n = n;

// varivel comum // ponteiro aponta para uma varivel comum // referncia para uma varivel comum

178

int *&ref_p = p; // referncia para ponteiro cout << "n = " << n << endl; cout << "*p = " << *p << endl; cout << "ref_n = " << ref_n << endl; cout << "ref_p = " << ref_p << endl; cout << "ref_p = " << *ref_p << endl; } Resultado do Programa : n=7 *p = 7 ref_n = 7 ref_p = 0xbfb35cc8 ref_p = 7

// contedo da referncia para ponteiro

15.4 Arquivos conio.c e conio.h em C++


Aqui mostrado uma forma alternativa de utilizar as funes: clrscr, gotoxy , textcolor, getche, getch e kbhit sem utilizao da biblioteca ncurses . Programa exemplo (143): O programa exemplo conio.cpp , abaixo, demonstra a utilizao da biblioteca conio.h.
// conio.cpp #include <iostream> #include "conio.h" using namespace std; #define ESC 27 int main(void) { int tecla; clrscr(); do { textcolor(BLUE); gotoxy(10,5); cout << "Tecla: "; tecla = getche(); // troque por tecla = getch(); textbackcolor(CYAN); gotoxy(10,7); cout << "Cdigo: " << tecla << " -> Caracter: " << tecla; } while (tecla != ESC); } // conio.h #include <termios.h> #include <unistd.h> #include <sys/time.h>

// arquivo conio.h contm as funes citadas acima

179

#define BLACK 0 #define RED 1 #define GREEN 2 #define BROWN #define BLUE 4 #define MAGENTA #define CYAN 6 #define DARKGRAY #define SUBLINHA #define black #define red #define green #define brown #define blue #define magenta #define cyan #define darkgray #define sublinha 0 1 2 3 4 5 6 7 8

3 5 7 8

// ---------------------------- funo: clrscr void clrscr(void) { printf("\x1B[2J"); } // ---------------------------- funo: gotoxy void gotoxy(int c, int l) { printf("\033[%d;%df",l, c); } // --------------------------- funo: getch int getch(void) { struct termios oldt, newt; int ch; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &newt); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); return(ch); } // --------------------------- funo: getche int getche(void) { struct termios oldt, newt; int ch; tcgetattr(STDIN_FILENO, &oldt); newt = oldt; newt.c_lflag &= ~(ICANON | ECHO);

180

tcsetattr(STDIN_FILENO, TCSANOW, &newt); ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); putchar(ch); return(ch); } // --------------------------- funo: kbhit int kbhit(void) { struct timeval tv; fd_set read_fd; tv.tv_sec=0; tv.tv_usec=0; FD_ZERO(&read_fd); FD_SET(0,&read_fd); if (select(1, &read_fd, NULL, NULL, &tv) == -1) return(0); if (FD_ISSET(0,&read_fd)) return(1); return(0); } // --------------------------- funo: textcolor void textcolor(int cor) { printf("\033[0m"); switch (cor) { case BLACK: printf("\033[30m"); break; case RED: printf("\033[31m"); break; case GREEN: printf("\033[32m"); break; case BROWN: printf("\033[33m"); break; case BLUE: printf("\033[34m"); break; case MAGENTA: printf("\033[35m"); break; case CYAN: printf("\033[36m"); break; case DARKGRAY: printf("\033[37m"); break; case SUBLINHA: printf("\033[38m"); break; } } // --------------------------- funo: textbackcolor void textbackcolor(int cor) { switch (cor) { case BLACK: printf("\033[40m");

181

break; case RED: printf("\033[41m"); break; case GREEN: printf("\033[42m"); break; case BROWN: printf("\033[43m"); break; case BLUE: printf("\033[44m"); break; case MAGENTA: printf("\033[45m"); break; case CYAN: printf("\033[46m"); break; case DARKGRAY: printf("\033[47m"); break; }

// --------------------------- funo: random int random(int n) { int t = rand() % n; return(t); } // --------------------------- funo: randomize void randomize(void) { srand(time(NULL)); } // --------------------------- funo: delay void delay(int espera) { clock_t t; t = clock() + espera; while (clock() <= t); }

Programa exemplo (144): O programa exemplo cores.cpp , abaixo, demonstra a utilizao da biblioteca conio.h em relao as cores, ou seja, funes textcolor e textbackcolor.
// cores.cpp #include <iostream> #include "conio.h" using namespace std; int main(void) { textcolor(BLACK); cout << "Black" << endl; textcolor(RED); cout <<"Red" << endl;

182

textcolor(GREEN); cout << "Green" << endl; textcolor(BROWN); cout << "Brown" << endl; textcolor(BLUE); cout << "Blue" << endl; textcolor(MAGENTA); cout << "Magenta" << endl; textcolor(CYAN); cout << "Cyan" << endl; textcolor(DARKGRAY); cout << "DarkGray" << endl; textcolor(SUBLINHA); cout << "Sublinha" << endl; textbackcolor(BLACK); cout << " Black " << endl; textbackcolor(RED); cout << " Red " << endl; textbackcolor(GREEN); cout << " Green " << endl; textbackcolor(BROWN); cout << " Brown " << endl; textbackcolor(BLUE); cout << " Blue " << endl; textbackcolor(MAGENTA); cout << " Magenta " << endl; textbackcolor(CYAN); cout << " Cyan " << endl; textbackcolor(DARKGRAY); cout << " DarkGray " << endl; getchar(); }

Programa exemplo (145): O programa exemplo abaixo quebra.cpp demonstra a utilizao da biblioteca conio.h (listada acima) em relao ao sorteio de nmeros aleatrios atravs de um jogo chamado Quebra-Cabeas.
// quebra.cpp #include <iostream> #include "conio.h" using namespace std; const int UP = 65; const int LEFT = 68; const int RIGHT = 67; const int DOWN = 66; // ------------------------------------- Funo: Imprime void Imprime(int c, int l, int cod, int cor) { textcolor(cor); gotoxy(c,l); cout << (char) 14 << (char) cod << (char) 15; }

// imprime caracteres especiais

// ------------------------------------- Funo: Moldura

183

void Moldura(int ci, int li, int cf, int lf, int cor) { for (int c = ci+1;c < cf;c++) { Imprime(c,li,113,cor); Imprime(c,lf,113,cor); } for (int l = li+1;l < lf;l++) { Imprime(ci,l,120,cor); Imprime(cf,l,120,cor); } Imprime(ci,li,108,cor); Imprime(cf,li,107,cor); Imprime(cf,lf,106,cor); Imprime(ci,lf,109,cor); } // ------------------------------------- Classe Grade class Grade { private: int ci, li, cf, lf, grade, numeros; char vetor[3][3]; int jogadas, tecla; private: bool Testa_Jogada(void); void troca(int &x, int &y) { int temp = x; x = y; y = temp; } public: Grade(int c, int l, int cor_grade, int cor_numeros) { ci = c; li = l; cf = ci + 12; lf = li + 6; grade = cor_grade; numeros = cor_numeros; } void Desenha_Grade(void); void Sorteia_Numeros(void); void Exibe_Numeros(void); void Jogar(int total_jogadas); void Posiciona_Cursor(int col, int lin); };

// construtor

// ------------------------------------- Mtodo: Desenha_Grade (pblico) void Grade :: Desenha_Grade(void) { Moldura(ci, li, cf, lf, grade); for (int c = ci+1;c < cf;c++) { Imprime(c,li+2,113,grade);

184

Imprime(c,li+4,113,grade); } for (int l = li+1;l < lf;l++) { Imprime(ci+4,l,120,grade); Imprime(ci+8,l,120,grade); } int c = ci + 4; for (int i = 1;i <= 2;i++) { Imprime(c,li,119,grade); Imprime(c,li,119,grade); Imprime(c,lf,118,grade); Imprime(c,lf,118,grade); c = c + 4; } int l = li + 2; for (int i = 1;i <= 2;i++) { Imprime(ci,l,116,grade); Imprime(ci,l,116,grade); Imprime(cf,l,117,grade); Imprime(cf,l,117,grade); l = l + 2; } c = ci + 4; for (int i = 1;i <= 2;i++) { Imprime(c,li+2,110,grade); Imprime(c,li+2,110,grade); Imprime(c,li+4,110,grade); Imprime(c,li+4,110,grade); c = c + 4; } } // ------------------------------------- Mtodo: Sorteia_Numeros (pblico) void Grade :: Sorteia_Numeros(void) { int n = 0; int c, l; randomize(); for (l = 0;l <= 2;l++) for (c = 0;c <= 2;c++) vetor[l][c] = -1; do { c = random(3); l = random(3); if (vetor[l][c] == -1) { vetor[l][c] = n + 48; n++; } } while (n <= 8); } // ------------------------------------- Mtodo: Exibe_Numeros (pblico)

185

void Grade :: Exibe_Numeros(void) { int i = 0, j = 0; textcolor(numeros); for (int l = 6;l <= 10;l=l+2) { for (int c = 12;c <= 20;c=c+4) { gotoxy(c,l); cout << " "; gotoxy(c,l); if (vetor[i][j] not_eq '0') cout << vetor[i][j]; j++; } i++; j = 0; } if (Testa_Jogada()) { textcolor(BROWN); gotoxy(12,14); cout << "Winner"; getch(); exit(0); } }

// testa fim do jogo

// ------------------------------------- Mtodo: Testa_Jogada (privado) bool Grade :: Testa_Jogada(void) { char correto[3][3] = {{'1','2','3'}, {'4','5','6'}, {'7','8','0'}}; for (int l = 0;l <= 2;l++) for (int c = 0;c <= 2;c++) if (vetor[l][c] != correto[l][c]) return(false); return(true); } // ------------------------------------- Mtodo: Jogo (pblico) void Grade :: Jogar(int total_jogadas) { int col, lin; int c, l; jogadas = total_jogadas; for (l = 0;l <= 2;l++) for (c = 0;c <= 2;c++) if (vetor[l][c] == '0') { col = c; lin = l; break; }

// descobrir a posio do ZERO

186

textcolor(MAGENTA); gotoxy(9,4); cout << "Quebra Cabeas"; textcolor(numeros); gotoxy(11,12); cout << "Jogadas: "; textcolor(grade); gotoxy(11,13); cout << "Tecla: "; c = col; l = lin; do { textcolor(RED); gotoxy(20,12); cout << jogadas; Posiciona_Cursor(col,lin); tecla = getch(); gotoxy(18,13); switch (tecla) { case UP: cout << "Up "; if (l >= 0 and l <= 1) { l = lin + 1; int temp = vetor[lin][col]; vetor[lin][col] = vetor[l][c]; vetor[l][c] = temp; lin = l; jogadas--; Exibe_Numeros(); } break; case DOWN: cout << "Down "; if (l >= 1 and l <= 2) { l = lin - 1; int temp = vetor[lin][col]; vetor[lin][col] = vetor[l][c]; vetor[l][c] = temp; lin = l; jogadas--; Exibe_Numeros(); } break; case LEFT: cout << "Left "; if (c >= 0 and c <= 1) { c = col + 1; int temp = vetor[lin][col]; vetor[lin][col] = vetor[l][c]; vetor[l][c] = temp; col = c; jogadas--; Exibe_Numeros(); } break; case RIGHT: cout << "Right"; if (c >= 1 and c <= 2) { c = col - 1;

187

} } while (jogadas != 0);

int temp = vetor[lin][col]; vetor[lin][col] = vetor[l][c]; vetor[l][c] = temp; col = c; jogadas--; Exibe_Numeros(); } break;

// ------------------------------------- Mtodo: Posiciona_Cursor (pblico) void Grade :: Posiciona_Cursor(int col, int lin) { int c, l; c = 12 + col * 4; l = 6 + lin * 2; gotoxy(c,l); } // ------------------------------------- Programa Principal int main(void) { Grade grade(10, 5, BLUE, CYAN); clrscr(); Moldura(1,1,32,17,GREEN); grade.Desenha_Grade(); grade.Sorteia_Numeros(); grade.Exibe_Numeros(); grade.Jogar(99); }

Tela do Jogo

15.5 Templates em C++


Templates ou gabaritos so funes ou classes genricas em que o tipo dos dados, ou seja, parmetros (argumentos) e/ou retorno das funes ou mtodos so definidos em tempo de compilao.
O s templates pode m apare ce r de vrias f ormas, por e xe mplo: (a) funes templates ; (b) classes templates ; (c) especificao template e (e) parmetros no tipados para templates .

Funes templates : Permite definir uma funo template, ou seja, uma funo que
aceita qualquer tipo de parmetro ou retorno da funo, ou seja, uma forma eficiente de polimorfismo.

188

Classes templates : Permite declarar uma classe genrica, ou seja, os atributos e


mtodos podem aceitar qualquer tipos.

Especificao template: Permite definir uma diferente implementao para um


template quando um tipo especfico passado para este como parmetro.

Parmetros no tipados para templates : Os parmetros dos templates podem ser


precedidos por classes tipadas, os templates podem ter parmetros tipados ou notipados.

Programa exemplo (146) : O programa exemplo template1.cpp , abaixo, demonstra a utilizao de funes do tipo template em C++ .
// template1.cpp #include <iostream> using namespace std; // ----------------------------- funo template: Max template <class Type> Type Max (Type x, Type y) { if (x > y) return(x); else return(y); } // ----------------------------- funo template: Min template <class Type> Type Min (Type x, Type y) { if (x < y) return(x); else return(y); } // ----------------------------- Programa Principal int main (void) { int a = 3, b = 4; float x = 1.2, y = 3.4; cout << "a = 3 e b = 4, maior " << Max < int> (a, b) << endl; cout << "x = 1.2 e y = 3.4, maior " << Max < float> (x, y) << endl; cout << "a = 3 e b = 4, maior " << Min < int> (a, b) << endl; cout << "x = 1.2 e y = 3.4, maior " << Min < float> (x, y) << endl; } Resultado do Programa :

189

a = 3 e b = 4, maior 4 x = 1.2 e y = 3.4, maior 3.4 a = 3 e b = 4, maior 3 x = 1.2 e y = 3.4, maior 1.2

Programa exemplo (147): O programa exemplo template2.cpp , abaixo, demonstra a utilizao de classes do tipo template em C++.
// template2.cpp #include <iostream> using namespace std; // --------------------------- Classe template: Imprime template <class Type> class Imprime { private: Type inic, fim; public: Imprime(Type ti, Type tf) { inic = ti; fim = tf; } void Exibe(void); }; // --------------------------- Funo template: Imprime template <class Type> void Imprime <Type> :: Exibe(void) { for (Type i = inic;i <= fim;i++) cout << i << " "; cout << endl; } // --------------------------- Programa Principal int main (void) { Imprime <int> inteiro (1, 10); inteiro.Exibe(); Imprime <char> real ('A', 'Z'); real.Exibe(); } Resultado do Programa : 1 2 3 4 5 6 7 8 9 10 ABCDEFGHIJKLMNOPQRSTUVWXYZ

// objeto inteiro // objeto real

Programa exemplo (148): O programa exemplo template3.cpp , abaixo, demonstra a utilizao de especificao do tipo template em C++ .

190

// template3.cpp #include <iostream> using namespace std; template <class Type> class Classe { private: Type atributo; public: Classe(Type argumento) { atributo = argumento; } Type Add(void) { atributo++; return(atributo); } }; template <> // especificao da classe template para char class Classe <char> { private: char caracter; public: Classe (char argumento) { caracter = argumento; } char Tolower(void) { if (caracter >= 'A' and caracter <= 'Z') caracter = caracter + 32; return(caracter); } char Add(void) { caracter++; return(caracter); } }; int main (void) { Classe <int> inteiro (3); cout << "Inteiro: " << inteiro.Add() << endl; Classe <char> caracter ('A'); cout << "Caracter: " << caracter.Tolower() << endl; cout << "Caracter: " << caracter.Add() << endl; } Resultado do Programa : Inteiro: 4

191

Caracter: a Caracter: b

Programa exemplo (149): O programa exemplo template4.cpp , abaixo, demonstra a utilizao de parmetros no tipados do tipo template em C++ .
// template4.cpp #include <iostream> using namespace std; // ---------------------------------------------- Classe Template: Vetor template <class Type, int n> class Vetor { Type vetor[n]; public: void Gera_Vetor(int t, Type value); void Exibe_Vetor(int t); }; // ---------------------------------------------- Mtodo Template: Gera_Vetor template <class Type, int n> void Vetor <Type, n> :: Gera_Vetor(int t, Type valor) { for (int i = 0;i < t;i++) vetor[i] = valor++; } // ---------------------------------------------- Mtodo Template: Exibe_Vetor template <class Type, int n> void Vetor <Type, n> :: Exibe_Vetor(int t) { for (int i = 0;i < t;i++) cout << vetor[i] << ' '; cout << endl; } // ---------------------------------------------- Programa Principal int main(void) { const int n1 = 5; const int n2 = 4; Vetor <int, n1> inteiro; Vetor <char, n2> caracter; inteiro.Gera_Vetor(n1, 1); inteiro.Exibe_Vetor(n1); caracter.Gera_Vetor(n2,'a'); caracter.Exibe_Vetor(n2); } Resultado do Programa :

192

12345 abcd

16. Composio
Na composio de objetos , uma classe pode ter como membros objetos de outras classes. Desta forma:

Membros-objeto so inicializados antes dos objetos de que fazem parte; Os argumentos para os construtores dos membros objeto so indicados atravs da
sintaxe dos inicializadores de membros.

Exemplo:
class Pessoa { public: Pessoa(char *n, int d, int m, int a); // construtor private: char *nome; Data nascimento; // membro-objeto }; Pessoa :: Pessoa(char *n, int d, int m, int a) : nascimento(d, m, a) { }

A reutilizao na orientao a objetos pode ser de duas formas: Herana de classes : Chamada de reutilizao tipo caixa-branca, definio esttica (tempo de compilao), simples, mas expe classe base. Composio de objetos : Chamada de reutilizao tipo caixa-preta, definio dinmica (obter referncia durante execuo), mais complexo de compreender. Para o prximo programa exemplo, relembre os seguintes conceitos vistos anteriormente:

Mtodos const

Quando um mtodo da classe no altera o estado do objeto, ou seja, no altera nenhum atributo do objeto, ele deve ser declarado como mtodo const. Desta forma, o compilador sabe que este mtodo no pode alterar nenhum atributo (proteo aos dados).

Objetos const

193

Objetos const s podem executar mtodos const, por isto, necessrio que o objeto declarado como const tenha mtodos const e construtores que inicializem os atributos. Programa exemplo (150): O programa exemplo composicao.cpp , abaixo, demonstra a utilizao de composio em C++.
// composicao.cpp #include <iostream> using namespace std; class Date { private: int day, month, year; public: Date(int dd = 1, int mm = 1, int yy = 1900); void Print (void) const { cout << "Data: " << day << "/" << month << "/" << year << endl; } }; Date :: Date(int dd, int mm, int yy) { day = dd; month = mm; year = yy; } class Empregado { private: char first[25],last[25]; const Date dataNasc, dataInic; public: Empregado(char *f, char *l, int d, int m, int a, int dd, int mm, int aa) : dataNasc(d,m,a) , dataInic(dd,mm,aa) { int length = strlen(f); length = (length < 25 ? length : 24); strncpy(first,f,length); first[length] = (char) NULL; length = strlen(l); length = (length < 25 ? length : 24); strncpy(last,l,length); last[length] = (char) NULL; cout << "Construtor Empregado: " << first << " " << last << endl; } void Print(void) { cout << "Nome: " << first << " " << last << endl; cout << "Data da Contratao: "; dataInic.Print(); cout << "Data de Nascimento: ";

194

};

dataNasc.Print(); }

int main(void) { Empregado empregado("Paulo", "Roberto", 24, 7, 1949, 3, 12, 1988); empregado.Print(); cin.get(); }

16. Programas utilizando Herana Simples


Programa exemplo (151): O programa exemplo 'menu.cpp' demonstra a utilizao de Herana Simples em C++ atravs da definico de uma classe base 'Pessoa' e uma classe derivada 'Aluno' armazenado os dados em um vetor de objetos .
// menu.cpp #include <iostream> #include <string> #include <stdlib.h> using namespace std; #define max 50 // ------------------------------- classe: Pessoa class Pessoa { protected: string nome; int idade; char sexo; public: void Entrada_Dados_Pessoa(void) { cin.ignore(1,'\n'); cout << "Nome: "; getline(cin, nome); cout << "idade: "; cin >> idade; cout << "Sexo: [M/F]"; do { sexo = cin.get(); } while (!strchr("MmFf", sexo)); } void Lista_Dados_Pessoa(void) { cout << "Nome: " << nome << endl; cout << "Idade: " << idade << endl; cout << "Sexo: " << sexo << endl; }

195

string Consulta_Nome_Pessoa(void) { return(nome); } }; // ------------------------------- classe: Aluno class Aluno : public Pessoa { protected: float n1, n2, media; char conceito; public: void Entrada_Dados_Aluno(void) { cout << "Nota 1: "; do { cin >> n1; } while (n1 < 0.0 or n1 > 10.0); cout << "Nota 2: "; do { cin >> n2; } while (n2 < 0.0 or n2 > 10.0); } void Calcula_Media(void) { media = (n2 + n1) / 2; if (media >= 9.0 and media <= 10.0) conceito = 'A'; else if (media >= 8.0 and media < 9.0) conceito = 'B'; else if (media >= 7.0 and media < 8.0) conceito = 'C'; else conceito = 'D'; cout << "Media: " << media << endl; cout << "Conceito: " << conceito << endl; } void Lista_Dados_Aluno(void) { cout << "Nota 1: " << n1 << endl; cout << "Nota 2: " << n2 << endl; cout << "Media: " << media << endl; cout << "Conceito: " << conceito << endl << endl; } }; // ------------------------------- classe: Menu class Menu { private: Aluno aluno[max]; int n, u;

196

char tecla, op; public: Menu(void) { n = 0; u = n - 1; } void Incluir(void); void Listar(void); void Consultar(void); void Ordenar(void); void Gerencia(void); }; // ------------------------------- classe: Menu - Metodo: Gerencia void Menu :: Gerencia(void) { do { cout << "CADASTRO DE ALUNOS"<< endl; cout << " [I]ncluir" << endl; cout << " [L]istar" << endl; cout << " [C]onsultar" << endl; cout << " [O]rdenar" << endl; cout << " [F]im" << endl; cout << "SELECIONE: "; do { op = cin.get(); } while (!strchr("IiLlCcOoFf", op)); if (strchr("Ff", op)) exit(0); switch (op) { case 'I': case 'i': Incluir(); break; case 'L': case 'l': Listar(); break; case 'C': case 'c': Consultar(); break; case 'O': case 'o': Ordenar(); break; } cout << "Continua [S/N]?"; do { tecla = cin.get(); } while (!strchr("SsNn", tecla)); } while (strchr("Ss", tecla)); } // ------------------------------- classe: Menu - Metodo: Incluir void Menu :: Incluir(void) { cout << "Aluno: " << n << endl; aluno[n].Entrada_Dados_Pessoa();

197

aluno[n].Entrada_Dados_Aluno(); aluno[n].Calcula_Media(); u = n; n++; } // ------------------------------- classe: Menu - Metodo: Listar void Menu :: Listar(void) { for (int i = 0;i <= u;i++) { cout << "Aluno: " << i << endl; aluno[i].Lista_Dados_Pessoa(); aluno[i].Lista_Dados_Aluno(); } } // ------------------------------- classe: Menu - Metodo: Consultar void Menu :: Consultar(void) { int t; do { cout << "Consultar: "; cin >> t; if (t < 0 or t > u) cout << "ERRO: Registro Inexistente" << endl; } while (t < 0 or t > u); aluno[t].Lista_Dados_Pessoa(); aluno[t].Lista_Dados_Aluno(); } // ------------------------------- classe: Menu - Metodo: Ordenar void Menu :: Ordenar(void) { Aluno temp; for (int i = 0;i < u;i++) for (int j = i + 1;j <= u;j++) if (aluno[i].Consulta_Nome_Pessoa() > aluno[j].Consulta_Nome_Pessoa()) { temp = aluno[i]; aluno[i] = aluno[j]; aluno[j] = temp; } cout << "Ok, Dados Ordenados"<< endl; } // ------------------------------- main int main(void) { Menu menu; menu.Gerencia();

198

Programa exemplo (152): O programa exemplo 'file.cpp' demonstra a utilizao de Herana Simples em C++ atravs da definico de uma classe base 'Pessoa' e uma classe derivada 'Aluno' armazenado os dados em um arquivo em disco chamado 'alunos.luz'. O programa utiliza as funes de arquivo do C padro.
// file.cpp #include <iostream> #include <string.h> #include <stdio.h> #include <stdlib.h> using namespace std; typedef struct { char nome[31]; int idade; char sexo; float n1, n2, media; char conceito; } REGISTRO; // ------------------------------- classe: Pessoa class Pessoa { protected: char nome[31]; int idade; char sexo; public: void Entrada_Dados_Pessoa(void) { cin.ignore(1,'\n'); cout << "Nome: "; cin.getline(nome, 30); cout << "idade: "; cin >> idade; cout << "Sexo: [M/F]"; do { sexo = cin.get(); } while (!strchr("MmFf", sexo)); } void Lista_Dados_Pessoa(void) { cout << "Nome: " << nome << endl; cout << "Idade: " << idade << endl; cout << "Sexo: " << sexo << endl; } char *Consulta_Nome_Pessoa(void) { return(nome); } int Consulta_Idade_Pessoa(void) { return(idade);

199

} char Consulta_Sexo_Pessoa(void) { return(sexo); }

};

// ------------------------------- classe: Aluno class Aluno : public Pessoa { protected: float n1, n2, media; char conceito; public: void Entrada_Dados_Aluno(void) { cout << "Nota 1: "; do { cin >> n1; } while (n1 < 0.0 or n1 > 10.0); cout << "Nota 2: "; do { cin >> n2; } while (n2 < 0.0 or n2 > 10.0); } void Calcula_Media(void) { media = (n2 + n1) / 2; if (media >= 9.0 and media <= 10.0) conceito = 'A'; else if (media >= 8.0 and media < 9.0) conceito = 'B'; else if (media >= 7.0 and media < 8.0) conceito = 'C'; else conceito = 'D'; cout << "Media: " << media << endl; cout << "Conceito: " << conceito << endl; } float Consulta_Nota1_Aluno(void) { return(n1); } float Consulta_Nota2_Aluno(void) { return(n2); } float Consulta_Media_Aluno(void) { return(media); }

200

char Consulta_Conceito_Aluno(void) { return(conceito); } void Lista_Dados_Aluno(void) { cout << "Nota 1: " << n1 << endl; cout << "Nota 2: " << n2 << endl; cout << "Media: " << media << endl; cout << "Conceito: " << conceito << endl << endl; }

};

// ------------------------------- classe: Menu class Menu { private: Aluno aluno; char tecla, op; FILE *fp; REGISTRO registro; public: void Incluir(void); void Listar(void); void Consultar(void); void Ordenar(void); void Gerencia(void); Menu(void) { fp = fopen("alunos.luz", "r+b"); if (fp == NULL) { fp = fopen("alunos.luz", "w+b"); if (fp == NULL) { cout << "ERRO FATAL: Problema no Disco" << endl; exit(1); } else cout << "Arquivo [alunos.luz] CRIADO" << endl; } else cout << "Arquivo [alunos.luz] ABERTO" << endl; } ~Menu(void) { fclose(fp); cout << "Arquivo [alunos.luz] FECHADO" << endl; }

};

// ------------------------------- classe: Menu - Metodo: Gerencia void Menu :: Gerencia(void) { do { cout << "CADASTRO DE ALUNOS"<< endl;

201

cout << " [I]ncluir" << endl; cout << " [L]istar" << endl; cout << " [C]onsultar" << endl; cout << " [O]rdenar" << endl; cout << " [F]im" << endl; cout << "SELECIONE: "; do { op = cin.get(); } while (!strchr("IiLlCcOoFf", op)); if (strchr("Ff", op)) exit(0); switch (op) { case 'I': case 'i': Incluir(); break; case 'L': case 'l': Listar(); break; case 'C': case 'c': Consultar(); break; case 'O': case 'o': Ordenar(); break; } cout << "Continua [S/N]?"; do { tecla = cin.get(); } while (!strchr("SsNn", tecla)); } while (strchr("Ss", tecla)); } // ------------------------------- classe: Menu - Metodo: Incluir void Menu :: Incluir(void) { aluno.Entrada_Dados_Pessoa(); aluno.Entrada_Dados_Aluno(); aluno.Calcula_Media(); strcpy(registro.nome, aluno.Consulta_Nome_Pessoa()); cout << "NOME: " << registro.nome << endl; registro.idade = aluno.Consulta_Idade_Pessoa(); registro.sexo = aluno.Consulta_Sexo_Pessoa(); registro.n1 = aluno.Consulta_Nota1_Aluno(); registro.n2 = aluno.Consulta_Nota2_Aluno(); registro.media = aluno.Consulta_Media_Aluno(); registro.conceito = aluno.Consulta_Conceito_Aluno(); fseek(fp, 0, SEEK_END); fwrite(&registro, sizeof(registro), 1, fp); } // ------------------------------- classe: Menu - Metodo: Listar void Menu :: Listar(void) { int n = 0; rewind(fp); fread(&registro, sizeof(registro), 1, fp);

202

while (!feof(fp)) { cout << "Aluno: " << n << endl; cout << "Nome: " << registro.nome << endl; cout << "Idade: " << registro.idade << endl; cout << "Sexo: " << registro.sexo << endl; cout << "Nota 1: " << registro.n1 << endl; cout << "Nota 2: " << registro.n2 << endl; cout << "Media: " << registro.media << endl; cout << "Conceito: " << registro.conceito << endl; fread(&registro, sizeof(registro), 1, fp); n++; } } // ------------------------------- classe: Menu - Metodo: Consultar void Menu :: Consultar(void) { int i = 0, n; bool achou = false; rewind(fp); cout << "Registro: "; cin >> n; fread(&registro, sizeof(registro), 1, fp); while (!feof(fp)) { if (n == i) { cout << "Nome: " << registro.nome << endl; cout << "Idade: " << registro.idade << endl; cout << "Sexo: " << registro.sexo << endl; cout << "Nota 1: " << registro.n1 << endl; cout << "Nota 2: " << registro.n2 << endl; cout << "Media: " << registro.media << endl; cout << "Conceito: " << registro.conceito << endl; achou = true; } fread(&registro, sizeof(registro), 1, fp); i++; } if (!achou) cout << "Erro: Registro Inexistente" << endl; } // ------------------------------- classe: Menu - Metodo: Ordenar void Menu :: Ordenar(void) { int n = 0; REGISTRO *reg, temp; rewind(fp); fread(&registro, sizeof(registro), 1, fp); while (!feof(fp)) { fread(&registro, sizeof(registro), 1, fp); n++; }

203

reg = (REGISTRO *) malloc(n * sizeof(REGISTRO)); if (reg == NULL) { cout << "ERRO FATAL: Falta de Memoria" << endl; exit(1); } else { rewind(fp); for (int i = 0;i < n;i++) fread(&reg[i], sizeof(reg[i]), 1, fp); int u = n - 1; for (int i = 0;i < u;i++) for (int j = i + 1;j <= u;j++) if (strcmp(reg[i].nome, reg[j].nome) > 0) { temp = reg[i]; reg[i] = reg[j]; reg[j] = temp; } rewind(fp); for (int i = 0;i < n;i++) fwrite(&reg[i], sizeof(reg[i]), 1, fp); } cout << "Ok, Dados Ordenados -> "<< n << endl; } // ------------------------------- main int main(void) { Menu menu; menu.Gerencia();

Programa exemplo (153): O programa exemplo 'pessoa.cpp' demonstra a utilizao de Herana Simples em C++ atravs da definico de uma classe base 'Pessoa' e uma classe derivada 'Aluno' armazenado os dados em um arquivo em disco chamado 'alunos.luz'. O programa utiliza as funes de arquivo do C++.
// pessoa.cpp #include <iostream> #include <fstream> #include <string.h> #include <stdlib.h> using namespace std; typedef struct { string nome; int idade; char sexo; float n1, n2, media; char conceito; } REGISTRO;

204

// ------------------------------- classe: Pessoa class Pessoa { protected: string nome; int idade; char sexo; public: void Entrada_Dados_Pessoa(void) { cin.ignore(1,'\n'); cout << "Nome: "; getline(cin, nome); cout << "idade: "; cin >> idade; cout << "Sexo: [M/F]"; do { sexo = cin.get(); } while (!strchr("MmFf", sexo)); } void Lista_Dados_Pessoa(void) { cout << "Nome: " << nome << endl; cout << "Idade: " << idade << endl; cout << "Sexo: " << sexo << endl; } string Consulta_Nome_Pessoa(void) { return(nome); } int Consulta_Idade_Pessoa(void) { return(idade); } char Consulta_Sexo_Pessoa(void) { return(sexo); } }; // ------------------------------- classe: Aluno class Aluno : public Pessoa { protected: float n1, n2, media; char conceito; public: void Entrada_Dados_Aluno(void) { cout << "Nota 1: "; do { cin >> n1; } while (n1 < 0.0 or n1 > 10.0); cout << "Nota 2: ";

205

do { cin >> n2; } while (n2 < 0.0 or n2 > 10.0); } void Calcula_Media(void) { media = (n2 + n1) / 2; if (media >= 9.0 and media <= 10.0) conceito = 'A'; else if (media >= 8.0 and media < 9.0) conceito = 'B'; else if (media >= 7.0 and media < 8.0) conceito = 'C'; else conceito = 'D'; cout << "Media: " << media << endl; cout << "Conceito: " << conceito << endl; } float Consulta_Nota1_Aluno(void) { return(n1); } float Consulta_Nota2_Aluno(void) { return(n2); } float Consulta_Media_Aluno(void) { return(media); } char Consulta_Conceito_Aluno(void) { return(conceito); } void Lista_Dados_Aluno(void) { cout << "Nota 1: " << n1 << endl; cout << "Nota 2: " << n2 << endl; cout << "Media: " << media << endl; cout << "Conceito: " << conceito << endl << endl; } }; // ------------------------------- classe: Menu class Menu { private: Aluno aluno; char tecla, op; public: void Incluir(void);

206

};

void Listar(void); void Consultar(void); void Ordenar(void); void Gerencia(void);

// ------------------------------- classe: Menu - Metodo: Gerencia void Menu :: Gerencia(void) { do { cout << "CADASTRO DE ALUNOS"<< endl; cout << " [I]ncluir" << endl; cout << " [L]istar" << endl; cout << " [C]onsultar" << endl; cout << " [O]rdenar" << endl; cout << " [F]im" << endl; cout << "SELECIONE: "; do { op = cin.get(); } while (!strchr("IiLlCcOoFf", op)); if (strchr("Ff", op)) exit(0); switch (op) { case 'I': case 'i': Incluir(); break; case 'L': case 'l': Listar(); break; case 'C': case 'c': Consultar(); break; case 'O': case 'o': Ordenar(); break; } cout << "Continua [S/N]?"; do { tecla = cin.get(); } while (!strchr("SsNn", tecla)); } while (strchr("Ss", tecla)); } // ------------------------------- classe: Menu - Metodo: Incluir void Menu :: Incluir(void) { ofstream file; file.open("alunos.luz", ios::app); if (file.fail()) { cout << "ERRO FATAL: Problema no Disco" << endl; exit(1); } else { aluno.Entrada_Dados_Pessoa();

207

aluno.Entrada_Dados_Aluno(); aluno.Calcula_Media(); file << aluno.Consulta_Nome_Pessoa() << endl; file << aluno.Consulta_Idade_Pessoa() << endl; file << aluno.Consulta_Sexo_Pessoa() << endl; file << aluno.Consulta_Nota1_Aluno() << endl; file << aluno.Consulta_Nota2_Aluno() << endl; file << aluno.Consulta_Media_Aluno() << endl; file << aluno.Consulta_Conceito_Aluno() << endl; file.close(); } } // ------------------------------- classe: Menu - Metodo: Listar void Menu :: Listar(void) { REGISTRO registro; ifstream file; int n = 0; file.open("alunos.luz"); do { getline(file, registro.nome); file >> registro.idade; file >> registro.sexo; file >> registro.n1; file >> registro.n2; file >> registro.media; file >> registro.conceito; file.ignore(1,'\n'); if (not registro.nome.empty()) { cout << "Aluno: " << n << endl; cout << "Nome: " << registro.nome << endl; cout << "Idade: " << registro.idade << endl; cout << "Sexo: " << registro.sexo << endl; cout << "Nota 1: " << registro.n1 << endl; cout << "Nota 2: " << registro.n2 << endl; cout << "Media: " << registro.media << endl; cout << "Conceito: " << registro.conceito << endl; } n++; } while (file); file.close(); } // ------------------------------- classe: Menu - Metodo: Consultar void Menu :: Consultar(void) { int n, i = 0; bool achou = false; REGISTRO registro; ifstream file; file.open("alunos.luz"); cout << "Registro: "; cin >> n; while (file)

208

{ getline(file, registro.nome); file >> registro.idade; file >> registro.sexo; file >> registro.n1; file >> registro.n2; file >> registro.media; file >> registro.conceito; file.ignore(1,'\n'); if (n == i && not registro.nome.empty()) { cout << "Aluno: " << n << endl; cout << "Nome: " << registro.nome << endl; cout << "Idade: " << registro.idade << endl; cout << "Sexo: " << registro.sexo << endl; cout << "Nota 1: " << registro.n1 << endl; cout << "Nota 2: " << registro.n2 << endl; cout << "Media: " << registro.media << endl; cout << "Conceito: " << registro.conceito << endl; achou = true; } i++; } if (not achou) cout << "ERRO: Registro Inexistente" << endl; file.close(); } // ------------------------------- Tamanho_Arquivo int Tamanho_Arquivo(void) { int n = 0; REGISTRO registro; ifstream file; file.open("alunos.luz"); while (file) { getline(file, registro.nome); file >> registro.idade; file >> registro.sexo; file >> registro.n1; file >> registro.n2; file >> registro.media; file >> registro.conceito; file.ignore(1,'\n'); n++; } file.close(); return(n); } // ------------------------------- classe: Menu - Metodo: Ordenar void Menu :: Ordenar(void) { const int tam = 50; int i = 0, n = Tamanho_Arquivo(); REGISTRO reg[tam], temp;

209

ifstream file; if (n > tam) { cout << "ERRO FATAL: Arquivo muito grande" << endl; exit(1); } else { file.open("alunos.luz"); while (file) { getline(file, reg[i].nome); file >> reg[i].idade; file >> reg[i].sexo; file >> reg[i].n1; file >> reg[i].n2; file >> reg[i].media; file >> reg[i].conceito; file.ignore(1,'\n'); i++; } file.close(); int u = n - 2; for (int i = 0;i < u;i++) for (int j = i + 1;j <= u;j++) if (reg[i].nome > reg[j].nome) { temp = reg[i]; reg[i] = reg[j]; reg[j] = temp; } ofstream out; out.open("alunos.luz", ios::out); if (out.fail()) { cout << "ERRO FATAL: Problema no Disco" << endl; exit(1); } else { for (int i = 0;i <= u;i++) { out << reg[i].nome << endl; out << reg[i].idade << endl; out << reg[i].sexo << endl; out << reg[i].n1 << endl; out << reg[i].n2 << endl; out << reg[i].media << endl; out << reg[i].conceito << endl; } out.close(); cout << "Ok, Registro(s) Ordenado(s) " << u+1 << endl; } } }

// ------------------------------- main

210

int main(void) { Menu menu; menu.Gerencia(); }

211