Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Rodrigo Canellas
rodrigo.canellas@gmail.com
agosto / 2008
-
Índice
5 Desenhando o CD Player............................................................................42
5.1 Exercício: Diagrama de Classes...........................................................42
5.2 Exercício: Diagrama de Estados..........................................................42
5.3 Exercício: Diagrama de Sequencia......................................................42
5.4 Uma pausa: buscando generalizações.................................................42
5.5 Morre um CD Player, nasce um Media Player.....................................42
5.6 Exercício: Rever os diagramas para o Media Player...........................42
-2-
-
-3-
-
-4-
-
11 Literatura...............................................................................................131
-5-
-
Índice de figuras
-6-
-
-7-
-
Ilustração 57: Definindo valores dos campos de uma estrutura – parte 1....84
-8-
1 -Por que usar Orientação por Objetos?
Vimos ao longo dos mais de sessenta anos da, não tão longinquamente
reconhecida, Ciência da Computação, várias tentativas de conseguir estes
objetivos.
Por exemplo, era possível criar um novo tipo de dados chamado Carro, e
associar a este novo Tipo as ações Parar, Ligar, Acender Faróis, etc. Assim
Carro passou a funcionar exatamente como um Tipo nativo de Simula, isto é,
somente ações formalmente definidas podiam ser realizadas sobre uma
variável do Tipo Carro. Também como um Tipo original, era desnecessário ao
-9-
1 -Por que usar Orientação por Objetos?
programador que usasse o Tipo Carro conhecer como este foi implementado.
Assim, Carro se assemelha a, por exemplo, Integer, onde somente
determinadas ações são possíveis, e não necessitamos conhecer sua
implementação para usá-lo.
- 10 -
1 -Por que usar Orientação por Objetos?
Nível 0.0
Problema Identificar Conceitos
Solução Conceitos Departamento e Funcionário identificados
Nível 0.1
Problema Conceitos Departamento e Funcionário identificados
- 11 -
1 -Por que usar Orientação por Objetos?
Nível 0.2
Problema Conceitos Departamento e Funcionário identificados
Solução Um Funcionário é identificado pela sua Matrícula, e um Departamento
por seu Código de Departamento
Nível 1.0
Problema A criação e desativação de Departamentos ocorre com baixa
frequencia
Solução A coleção necessária para guardar os Departamentos terá um volume
baixo de inserções e exclusões
Nível 1.1
Problema A coleção necessária para guardar os Departamentos terá um volume
baixo de inserções e exclusões
Solução Usar um Vetor para armazenar os Departamentos
Nível 2.0
Problema Existe uma alta rotatividade de Funcionários
Solução A coleção necessária para guardar os Funcionários terá um volume
alto de inserções e exclusões
Nível 2.1
Problema A coleção necessária para guardar os Funcionários terá um volume
alto de inserções e exclusões
Solução Usar uma Lista para armazenar os Funcionários
- 12 -
1 -Por que usar Orientação por Objetos?
Suponha que uma Classe Carro tenha uma relação com a Classe Motor. O
programador que implementará a Classe Carro não precisa esperar que a
Classe Motor esteja acabada para ao menos iniciar sua tarefa. Isto é possível
porque a Classe Motor tem uma Interface bem definida, logo a Classe Carro
pode ter sua implementação iniciada, confiando que Motor funcionará
segundo aquela Interface. A fim de minimamente testar a Classe Carro, o
programador pode criar uma Classe Motor temporária, com os Métodos de
Motor implementados de maneira rudimentar (stub).
- 13 -
1 -Por que usar Orientação por Objetos?
classe: Data
fimclasse;
// declara um objeto do tipo Data
d0 : Data;
// executa o método inicializa sobre o objeto d0
d0.inicializa(13,8,2008);
d0 : Data;
se d0.inicializa(13,8,2008) = verdadeiro
imprime “data valida”
senao
- 14 -
1 -Por que usar Orientação por Objetos?
imprime “data invalida”
fimse
- 15 -
1 -Por que usar Orientação por Objetos?
devido às Interfaces bem definidas. Ou seja, um erro tem seu “culpado” mais
facilmente identificado, na medida que sabemos exatamente o que cada
Classe de Objetos faz.
- 16 -
1 -Por que usar Orientação por Objetos?
- 17 -
2 -Apresentação dos conceitos básicos
2.1 Classe
Como vimos, uma Classe é a representação de um Conceito, ou Objeto,
identificado no problema. Estudamos este Objeto, procurando identificar as
relações com outros Objetos, e seus Comportamentos, ou seja, o conjunto de
ações que este Objeto realiza.
2.2 Objeto
Em termos computacionais, um Objeto, também chamado de Instância é a
concretização de uma Classe.
// declara um objeto do tipo Data
- 18 -
2 -Apresentação dos conceitos básicos
d0 : Data;
2.3 Método
O conjunto de Métodos, ou Funções, associadas a uma Classe, define sua
Interface (Protocolo da Classe), isto é, o que é possível realizar com, ou
sobre, um Objeto.
// executa o método inicializa sobre o objeto d0
d0.inicializa(13,8,2008);
// declara um outro objeto do tipo Data
Data d1;
// aplica o método inicializa sobre d1
d1.inicializa (16,2,1966);
2.4 Atributo
Na Classe Data, quando invocamos o Método inicializa sobre a Instância
d1, fornecemos três informações, na forma de parâmetros: 16, 2 e 1966,
para o dia, mês e ano da Data, respectivamente.
classe: Data
- 19 -
2 -Apresentação dos conceitos básicos
método: qual_ano() : inteiro;
fimclasse;
// declara um outro objeto do tipo Data
Data d1;
// aplica o método inicializa sobre d1
d1.inicializa (16,2,1966);
// imprime o valor do ano de d1
imprime d1.qual_ano();
classe: Data
método: qual_ano() : inteiro;
atributo: ano_ : inteiro;
atributo: mes_ : inteiro;
atributo: dia_ : inteiro;
fimclasse;
Data.inicializa(dia: inteiro, mes: inteiro, ano : inteiro): boleano
inicio
- 20 -
2 -Apresentação dos conceitos básicos
retorno : boolean;
retorno = verdadeiro; // esperamos o melhor
// o método data_invalida não será mostrado
se data_invalida(dia, mês, ano) entao
retorno = falso;
senao
// não serão mostradas as críticas dos valores
dia_ = dia;
mes_ = mês;
ano_ = ano;
fimse
retorna retorno;
fimmetodo;
Data.qual_ano() : inteiro
inicio
retorna ano_;
fim
Para reforçar este conceito, vamos supor que exista uma classe
Compromisso, que tenha como Atributo um Objeto da Classe Data:
classe: Compromisso
método: agendar(dia : inteiro;
- 21 -
2 -Apresentação dos conceitos básicos
mes : inteiro;
ano : inteiro ;
descricao : Texto) : booleano;
atributo: data : Data;
atributo: desc : Texto;
fimclasse;
Compromisso.agendar(dia : inteiro;
mes : inteiro;
ano : inteiro ;
descricao : Texto);
inicio
retorno : booleano;
retorno = data.inicializa(dia, mes, ano)
se retono == verdadeiro entao
// estamos supondo que Texto tenha um Método atribui
desc.atribui(descricao);
retorna retorno;
fimmetodo;
Este exemplo, embora não tenha este objetivo, mostra um dos mecanismos
de construção de Classes em um ambiente Orientado por Objetos:
composição. A Classe Compromisso é composta por uma Instância da Classe
Data. Falaremos mais detalhadamente sobre os mecanismos e técnicas de
construção de Classes adiante.
- 22 -
2 -Apresentação dos conceitos básicos
classe: Data
método: qual_ano() : inteiro;
atributo: valores: vetor[3] de inteiro;
fimclasse;
Data.inicializa(dia: inteiro, mes: inteiro, ano : inteiro): boleano
inicio
retorno : boolean;
retorno = verdadeiro; // esperamos o melhor
// o método data_invalida não será mostrado
se data_invalida(dia, mês, ano) entao
retorno = falso;
senao
// não serão mostradas as críticas dos valores
valores[0] = dia;
valores[1] = mês;
valores[2] = ano;
fimse
retorna retorno;
fimmetodo;
Data.qual_ano() : inteiro
inicio
- 23 -
2 -Apresentação dos conceitos básicos
retorna valores[2];
fim
2.5 Visibilidade
Quando afirmamos que os Atributos somente são acessados através de
Métodos, estamos faltando com a verdade. Na prática, isto fica a cargo do
desenhista. É possível definir Atributos que sejam acessados “de fora” da
Classe, não por intermédio de um Método, apenas tendo um Objeto da
Classe instanciado. Portanto, ao definirmos um Atributo ou Método,
precisamos especificar sua visibilidade, isto é, como será possível acessar o
Atributo ou Método. As linguagens de programação, em geral, definem três
tipos de visibilidade: pública, protegida ou privativa.
- 24 -
2 -Apresentação dos conceitos básicos
classe: Data
públicos:
método: qual_ano() : inteiro;
protegidos:
atributo: ano_ : inteiro;
atributo: mes_ : inteiro;
atributo: dia_ : inteiro;
fimclasse;
d0 : Data;
d0.inicializa(19,8,2004);
imprime d0.dia_;
classe: Data
públicos:
- 25 -
2 -Apresentação dos conceitos básicos
método: qual_ano() : inteiro;
protegidos:
atributo: ano_ : inteiro;
atributo: mes_ : inteiro;
atributo: dia_ : inteiro;
fimclasse;
d0 : Data;
se d0.data_invalida(19,8,2004) entao
imprime “invalido”;
senao
imprime “valido”;
fimse.
2.6 Herança
Apresentamos detalhadamente o mecanismo de Herança, mencionado
rapidamente em Efeitos na Manutenção.
- 26 -
2 -Apresentação dos conceitos básicos
Um pequeno exemplo:
classe Veiculo;
classe VeiculoMotorizado herda Veiculo;
classe CarroEsporte herda VeiculoMotorizado;
classe Porsche herda CarroEsporte;
Mas, na prática o que significa dizer que uma Classe herda de uma outra,
isto é, qual o efeito desta herança nos Atributos e Métodos?
- 27 -
2 -Apresentação dos conceitos básicos
2.8 Polimorfismo
Nem tanto uma técnica, mais uma consequencia da hierarquia de Classes,
Polimorfismo, no âmbito de Orientação por Objetos, é a capacidade de,
embora não sabendo de que Classe um Objeto a0 é instância, mas sabendo
que esta Classe faz parte de uma hierarquia, podermos aplicar um Método
m0, que seguramente está implementado em toda a Hierarquia, a a0. Além
disso, mesmo não sabendo exatamente de que Classe a0 é Objeto, o Método
m0 executado será o da Classe de a0.
Imagine que Orlando quer comprar um cão, um que tenha um latido bem
assustador. Orlando vai ao canil e explica ao proprietário que tipo de cão
quer. Ele venda os olhos do Orlando, o leva até a porta do canil, e pede que
fale, em tom baixo e firme, a palavra “late”. Orlando obedece, e uma
enxurrada de latidos enchem seus ouvidos, que imediatamente distingue um
- 28 -
2 -Apresentação dos conceitos básicos
latido bem feroz. O proprietário retira a venda e Orlando logo reconhece que
o dono do latido é um enorme pastor-alemão, em meio a dois buldogues, três
beagles, um pequinês, dois setter-irlandeses e quatro collies.
classe Cao;
públicos:
método late;
fimclasse;
class Buldogue : herda Cao;
públicos:
método late;
fimclasse;
class Beagle : herda Cao;
públicos:
método late;
fimclasse;
class Pequines : herda Cao;
públicos:
método late;
fimclasse;
class SetterIrlandes : herda Cao;
públicos:
método late;
fimclasse;
class Collie : herda Cao;
públicos:
- 29 -
2 -Apresentação dos conceitos básicos
método late;
fimclasse;
class PastorAlemao : herda Cao;
públicos:
método late;
fimclasse;
classe Canil;
privativos:
caes : colecao (cao);
públicos:
late;
novo_cao(novo : cao);
fimclasse;
Canil.late
inicio
para_cada (cao em caes) faca
cao.late;
fimpara;
- 30 -
2 -Apresentação dos conceitos básicos
fimmetodo;
Nada mais natural, se quero que todo os cães latam, aplico o Método late
para cada Cao da coleção caes.
Canil.novo_cao(novo : Cao)
inicio
caes.inserir(novo);
fimmetodo;
Canil c;
c.latam;
Canil c;
b : Buldogue;
c.novo_cao(b);
- 31 -
2 -Apresentação dos conceitos básicos
Mas para que isso seja possível, o Método late em Cao deve ter uma
característica especial na Classe base da Hierarquia: ele deve ser virtual.
classe Cao;
públicos:
método late; virtual;
fimclasse;
classe Cao;
públicos:
método late; virtual; abstrato;
fimclasse;
- 32 -
3 -Estudo de Caso – Definição
- 33 -
3 -Estudo de Caso – Definição
Objetos:
- 34 -
3 -Estudo de Caso – Definição
- 35 -
3 -Estudo de Caso – Definição
- 36 -
4 -Introdução a Unified Modeling Language
Este diagrama informa que a Classe A tem uma relação, neste nível de
1 Booch, Grady - “The Unified Modeling Language – User Guide”, Preface, pg xviii
2 www.omg.org
- 37 -
4 -Introdução a Unified Modeling Language
Um outro exemplo:
Além de informar que a Classe C tem uma associação com vários Objetos
da Classe D, este diagrama também revela que é possível acessar os Objetos
da Classe D, a partir de um Objeto da Classe C, mas dado um Objeto da
Classe D, relacionado a um Objeto da Classe C, não temos como acessar
este Objeto da Classe C a partir daquele Objeto da Classe D.
Ilustração 6: Agregação em
UML
Este diagrama nos diz que um Objeto da Classe G terá, como um de seus
atributos, um Objeto da Classe H, e que este será criado quando um Objeto
da Classe G for criado. Assim, quando o destrutor do Objeto da Classe G for
executado, o Objeto da Classe H será destruído.
- 38 -
4 -Introdução a Unified Modeling Language
Basicamente, este diagrama nos diz que um Objeto da Classe E terá, como
um de seus atributos, um Objeto da Classe F, mas este não será criado
quando um Objeto da Classe E for criado. Assim, quando o destrutor do
Objeto da Classe E for executado, o Objeto da Classe F não será destruído.
Logo, em uma relação de composição, o Objeto usado como atributo
provavelmente será passado como parâmetro no construtor da Classe.
Este diagrama nos diz que um Objeto Classe J, será usado por um Objeto
da Classe I provavelmente durante a execução de um Método. Ao longo dos
sucessivos refinamentos, esta relação, muito provavelmente, será
reinterpretada como um Objeto da Classe J sendo passado por parâmetro
para um Método da Classe I.
- 39 -
4 -Introdução a Unified Modeling Language
Ilustração 9:
Herança em
UML
4.3 Diagrama de Sequencia
Os diagramas de Sequencia são usados para definir como um Método
funciona, mostrando a chamada a Métodos de outros Objetos.
- 40 -
4 -Introdução a Unified Modeling Language
emitido, caso contrário, um Objeto da Classe F não seria visível pela Classe
E.
- 41 -
5 -Desenhando o CD Player
5 Desenhando o CD Player
- 42 -
6 -(Re) Desenho: Orientação por Objetos e Arquitetura em Camadas
- 43 -
6 -(Re) Desenho: Orientação por Objetos e Arquitetura em Camadas
Como exemplo, suponha que temos uma Classe Cifrador, responsável por
criptografar arquivos. Exercitando nosso conhecimento, podemos conceber
os seguintes refinamentos, ilustrados usando UML:
- 44 -
6 -(Re) Desenho: Orientação por Objetos e Arquitetura em Camadas
3 http://bouml.free.fr/
- 45 -
6 -(Re) Desenho: Orientação por Objetos e Arquitetura em Camadas
- 46 -
6 -(Re) Desenho: Orientação por Objetos e Arquitetura em Camadas
Mas como este valor resumo será calculado, para em seguida ser passado
para cifra? O desenho abaixo ilustra a cração de uma Classe que gerencia a
criação de Objetos intermediários para o cálculo da criptografia.
- 47 -
6 -(Re) Desenho: Orientação por Objetos e Arquitetura em Camadas
valor resumo ter sido calculado, invocar o Método cifra de cifrador. Mas
como um Objeto desta Classe terá acesso ao valor original, para passar para
digester, e em pequenos blocos, se necessário?
Examinemos o desenho:
- 48 -
6 -(Re) Desenho: Orientação por Objetos e Arquitetura em Camadas
- 49 -
6 -(Re) Desenho: Orientação por Objetos e Arquitetura em Camadas
- 50 -
6 -(Re) Desenho: Orientação por Objetos e Arquitetura em Camadas
- 51 -
6 -(Re) Desenho: Orientação por Objetos e Arquitetura em Camadas
processador_cifragem.cifra(in id_cifrador : string;
in id_digester : string;
in valor : byte_array) : byte_array
inicio
cif : cifrador;
cif = forn_cifra.obtem_cifrador(id_cifrador);
dig : digester;
dig = forn_dig.obtem_digester(id_digester);
val_orig : valor_original;
val_orig = forn_valor_orig.obtem_valor_original(valor);
bloco : byte_array;
bloco = val_orig.proximo_bloco();
enq bloco.nao_vazio() faca
dig.acumula(bloco);
bloco = val_orig.proximo_bloco();
fimenq
valor_resumo : byte_array;
valor_resumo = dig.calcula();
valor_cifrado : byte_array;
valor_cifrado = cif.cifra(valor_resumo);
retorna valor_cifrado;
fim;
- 52 -
7 -Programação básica em C++
7.1 Delimitadores
7.1.1 De comandos
Todo comando em C++ é delimitado por ; , como estes exemplos:
using namespace std;
int c;
cout << “Olá. Mundo!” << endl;
7.2 Comentários
Um comentário em C++ é todo texto após barras duplas //, até o fim da
linha, ou o texto após uma barra, seguida de um asterisco /*, até o próximo
asterisco seguido de uma barra */.
Exemplo:
// o texto até o fim da linha é um comentário
/* aqui começa um comentário
que só termina aqui */
- 53 -
7 -Programação básica em C++
bool e void.
7.4 Variáveis
Variável é um sinônimo para um endereço de memória, onde existe um
conteúdo, limitado por um tipo, que também define um tamanho. Podemos
visualizar assim uma variável:
O nome de uma variável em C++ não tem limite de tamanho, e pode ser
formados por letras, dígitos e sublinhado (underscore), mas não podem
começar por dígitos:
int Inteiro;
int Inteiro1;
int Inteiro_1;
int Inteiro_1_1_a;
Podemos definir o valor de uma variável no momento da sua declaração:
float f0 = 0.82;
double pi = 3.14;
A variável pi tem essa visualização:
- 54 -
7 -Programação básica em C++
É possível definir uma variável de modo que seu conteúdo não possa ser
alterado:
const char opcao_sair = 's';
7.4.1 Vetores
7.4.1.1 Declarando
Não há em C++ uma palavra reservada para declarar um vetor, para tal
usamos o operador colchetes []:
int a [8];
Esta instrução declara um vetor de 8 posições, contadas a partir de 0, de
inteiros. Sua representação gráfica seria:
- 55 -
7 -Programação básica em C++
a[0] = 0;
a[1] = 0;
a[2] = 0;
a[3] = 0;
- 56 -
7 -Programação básica em C++
a[4] = 0;
a[5] = 0;
a[6] = 0;
a[7] = 0;
a[8] = 0;
Ou, a maneira mais eficiente e genérica:
int contador = 0;
while (contador < 8) {
a [contador] = 0;
contador = contador + 1;
}
7.5 Operadores
Neste tópico examinaremos os diversos operadores existentes em C++.
7.5.1 Atribuição
Como em qualquer linguagem de programação, uma atribuição copia o
conteúdo de uma variável para outra:
int i = 9;
int j = 17;
- 57 -
7 -Programação básica em C++
j = i;
7.5.2 Igualdade/Desigualdade
O operador de igualdade compara o conteúdo de duas variáveis, e o
resultado da avaliação é uma valor do tipo bool, ou seja, true ou false.
int u = 9;
int w = 5;
if (u == w) {
cout << “'u' igual a 'w'”;
}
else {
cout << “'u' diferente de 'w'”;
}
int t = 5;
if (t != w) {
cout << “'t' diferente de 'w'”;
}
else {
cout << “'t' igual de 'w'”;
}
- 58 -
7 -Programação básica em C++
7.5.3 Relacionais
Os operadores relacionais em C++ são:
● >
● <
● >=
● <=
7.5.4 Lógicos
Os operadores lógicos em C++ são:
! (not)
|| (or)
&& (and)
Sempre que o conteúdo de uma variável for diferente de zero, o uso
apenas do nome da variável em uma expressão resulta em true:
int var = 2;
if (var) {
cout << “true”;
}
else {
cout << “false”;
}
int i = 9;
i = i + 1;
++i;
Os comandos i = i + 1 e ++i são equivalentes. Da mesma forma:
- 59 -
7 -Programação básica em C++
int p = 11;
p = p – 1;
p;
Os comandos p = p – 1 e –p são equivalentes.
int * i0;
i0 é uma variável cujo conteúdo é um endereço de memória, que ainda
não foi definido, onde estará um conteúdo inteiro:
- 60 -
7 -Programação básica em C++
int * i0 = NULL;
ou
int * i0 = 0;
- 61 -
7 -Programação básica em C++
int * i = 0;
.
.
.
i = new int (3);
int * i = 0;
.
.
.
i = new int (3);
if (i != 0) {
cout << “Memória alocada!”;
}
- 62 -
7 -Programação básica em C++
else {
cout << “Memória NÃO alocada!”
}
A expressão (i != 0) resulta em true o conteúdo de i não for zero, ou
seja, o endereço referenciado por i for válido.
int * i = 0;
.
.
.
i = new int (3);
if (i != 0) {
cout << “Memória alocada!”;
}
else {
cout << “Memória NÃO ALOCADA!”
}
*i = 142;
- 63 -
7 -Programação básica em C++
7.6.7 Atribuição
E como seria uma atribuição de ponteiros?
int * p = 0;
p = new int (12);
int * r = 0;
- 64 -
7 -Programação básica em C++
r = p;
*p = 5;
- 65 -
7 -Programação básica em C++
*r = 193;
7.6.8 Igualdade/Desigualdade
Ponteiros também podem ser comparados, mas devemos ter cuidado, pois
se compararmos o conteúdo de dois ponteiros, estaremos comparando dois
- 66 -
7 -Programação básica em C++
int *var1 = new int (43);
int *var2 = new int (55);
Portanto, se escrevermos:
if (var1 == var2) {
cout << “Conteúdo de 'var1' igual a 'var2'”;
}
else {
cout << “Conteúdo de 'var1' diferente de 'var2'”;
}
Estamos comparando e2 a e4, o que sempre resultará false.
if (*var1 == *var2) {
cout << “Conteúdo da área apontada por 'var1' igual ao ”;
cout << “conteúdo da área apontada por 'var2'”;
}
else {
cout << “Conteúdo da área apontada por 'var1' diferente do ”;
cout << “conteúdo da área apontada por 'var2'”;
}
- 67 -
7 -Programação básica em C++
int * i = new int (4);
if (i) {
cout << “true”;
}
else {
cout << “false”;
}
Se a alocação for be sucedida, o conteúdo de i será um endereço de
memória diferente de zero, logo a expressão if (i) resulta em true.
- 68 -
7 -Programação básica em C++
int * a = new int[8];
- 69 -
7 -Programação básica em C++
char * s = “um string”;
char * s = 0;
s = new char[10];
- 70 -
7 -Programação básica em C++
strcpy(s, “um string”);
Repare que o “um string” tem nove caracteres, mas a instrução s = new
char[10]; aloca memória para 10 caracteres. Isto porque, como mostra a
figura acima, é necessário um byte para armazenar o caracter '\0', que
marca o fim do string.
int * a = new int[8]; // ver Ponteiro Como Vetor acima
int * b = a;
++b;
- 71 -
7 -Programação básica em C++
*b = 444;
*(a + 1) = 444;
Esta instrução soma 1 ao conteúdo de a, e como a aponta para um inteiro,
a área referenciada será duas posições de memória subsequentes à e0, ou
seja, e0 + 2, em seguida acessa esta área através do operador *, e
finalmente atribui a área de memória endereçada o valor 444.
- 72 -
7 -Programação básica em C++
int a = 8;
int *b = &a;
if (expressão verdadeira) {
bloco de comandos;
}
else {
outro bloco de comandos;
}
- 73 -
7 -Programação básica em C++
for ( inicialização das condições;
enquanto condições forem verdadeiras;
comandos que modificam as condições) {
bloco de comandos;
}
Exemplificando:
for (int i = 0; i < 18; ++i) {
cout << “i = “ << i << endl;
}
O outro comando é o while:
while (condição verdadeira) {
bloco de comandos;
}
Novamente um exemplo:
int i = 0;
while (i < 18) {
cout << “i = “ << i << endl;
++i;
}
O dowhile executa o teste ao final;
do {
bloco de comandos;
} while (condição verdadeira);
Outro exemplo:
int i = 0;
do {
cout << “i = “ << i << endl;
++i;
} while (i < 17);
- 74 -
7 -Programação básica em C++
7.10 Funções
Todo algoritmo em C++ é implementado em forma de uma função, mesmo
que não haja valor de retorno.
7.10.1 Declaração
Na declaração de uma função identifica que tipo de dados a função
devolverá ao fim da sua execução, qual o seu nome, e quais os argumentos
que devem ser fornecidos quando a função for executada:
tipoderetorno nomedafunção ( argumentos ) ;
Onde:
tipodoargumento nomedoargumento = valorpadraoopcional,
Exemplos:
// uma função que retorna um inteiro, mas não tem argumentos
int funcao1();
// uma função que retorna um float, e tem como argumento um inteiro
float funcao_2(int i);
// uma função que retorna um char, que tem como argumentos um char, e
// um double, com valor default 0.0321
char _FunCao3(char c, double d = 0.0321);
- 75 -
7 -Programação básica em C++
7.10.2 Definição
A definição da função define a implementação da função:
int funcao1() {
return 19;
}
float funcao_2(int i) {
float f = 3.14 * i;
return f;
}
char _FunCao3(char c, double d) {
char retorno = 'f';
if (d > 4.75) {
if (c == 'A) {
retorno = 'F';
}
else {
retorno = 'Z';
}
}
else {
if (c == 'R') {
retorno = 'K';
}
else {
retorno = 'W';
}
}
return retorno;
}
Reparem que na definição da função _FuncCao3, o valor padrão do
argumento d não é repetido.
- 76 -
7 -Programação básica em C++
7.10.3 Execução
Como todo algoritmo é implementado em C++ como uma função, é
razoável concluir que uma função sempre terá sua execução iniciada e
finalizada dentro do escopo de uma outra função, criando uma relação de
função-chamadora e função-chamada.
int funcaoF0 (int i = 8);
int funcaoF1();
Seguidas das definições:
int funcaoF1() {
return 18;
}
int funcaoF0(int i) {
int rc = 0;
if (i > 10) {
rc = funcaoF1();
}
else {
rc = 1;
}
return rc;
}
Reparem que a instrução rc = funcaoF1(); efetua uma chamada a
funcaoF1, iniciando sua execução. Quando funcaoF1 terminar, o valor 18
será retornado, e em seguida atribuído a variável rc.
- 77 -
7 -Programação básica em C++
// declaração
float m (int i);
// definição
float m (int i) {
return i * 4.09;
}
// execução
int k = 8;
float f = m (k);
- 78 -
7 -Programação básica em C++
// declaração
float w (int * i);
// definição
float w (int * i) }
return (*i) * 4.09;
}
// execução
int r0 = 8;
float f = w( &r0 );
int r1 = new int (8);
- 79 -
7 -Programação básica em C++
f = w (r1);
- 80 -
7 -Programação básica em C++
int main () {
int rc = 0;
// código que será executado quando o programa for executado
return rc;
}
Este exemplo mostra uma função main que permite ao programa receber
parâmetros:
int main (int argc, char *argv[]) {
int rc = 0;
// código que será executado quando o programa for executado
return rc;
}
Suponhamos que o programa pgm00 possa receber três parâmetros: um
inteiro, um real, e uma palavra, e a seguinte chamada ao programa:
pgm00 86 3.019 doce
- 81 -
7 -Programação básica em C++
- 82 -
7 -Programação básica em C++
int main (int argc, char *argv[]) {
int rc = 0;
if (argc != 4) { // o nome do programa é sempre
// o primeiro parâmetro
cout << “Uso: pgm00 <inteiro> <real> <string>”;
rc = 1;
}
else {
cout << “O primeiro parâmetro é “ << argv[1] << endl;
cout << “O segundo parâmetro é “ << argv[2] << endl;
cout << “O terceiro parâmetro é “ << argv[3] << endl;
}
return rc;
}
Vejamos o exemplo:
typedef struct estrutura_a {
int campo1;
float campo2;
char *campo3;
};
Podemos declarar variáveis do “tipo” estrutura_a:
- 83 -
7 -Programação básica em C++
estrutura_a var_a;
var_a.campo1 = 4;
var_a.campo2 = 0.13;
var_a.campo3 = new char [4];
- 84 -
7 -Programação básica em C++
strcpy(var_a.campo3, “ola”);
// declarando um tipo de função, que tem um argumento inteiro e
retorna um float
typedef float (*t_f) ( int) ;
// definindo uma função que tem um argumento inteiro e retorna um
float
- 85 -
7 -Programação básica em C++
float g ( int i)
{
return ( i * 9.2) ;
}
// a função main
int main( )
{
// declarando uma variável que de um tipo de função
// esta variável é na verdade um ponteiro para uma
// função do tipo t_f
t_f f ;
// aqui acontece uma simples atribuição de ponteiros,
// como visto em Atribuição de ponteiros
f = g;
// aqui usamos o ponteiro para função para executar a função
cout << ( *f) ( 4) << endl;
return 0;
}
7.13 Pré-processamento
É possível tomar algumas decisões antes do código começar a ser
compilado. Neste momento são avaliadas macro definições – constantes e
comados – e as diretivas de compilação, que permitem mudar
completamente o código que será compilado.
#define MAX 10
#define SAUDACAO “Ola!”
#define PI 3.14
- 86 -
7 -Programação básica em C++
#define area_circulo( x ) (PI * ( x ) * ( x ) )
O compilador irá substituir todas os símbolos area_circulo(4) pelos
símbolos PI * 4 * 4.
float m (int i) {
float f = 0.0;
#ifdef A
f = i * 3.91;
#else
f = i * 4.01;
#endif
return f;
}
Assim, se o símbolo A estiver definido, o código compilado será f = i *
3.91;, caso contrário será compilada a instrução f = i * 4.01;.
- 87 -
8 -Orientação por Objetos e C++
8.1 Classes
A declaração de Classes em C++ tem esta sintaxe:
class nome_da_classe {
public:
atributos_públicos
métodos_públicos
protected:
atributos_protegidos
métodos_protegidos
private:
atributos_privativos
métodos_privativos
};
8.2 Objetos
Como dissemos em Objeto, um Objeto está para uma variável, assim como
uma Classe está para um tipo. E isso ainda é mais patente porque a sintaxe
de declaração de um Objeto é a mesma de uma variável:
classe_a objeto_da_classe_a;
8.3 Atributos
Atributos são essencialmente Objetos, ou ponteiros para Objetos,
declarados dentro de uma Classe:
// uma classe classe_b
class classe_b {
.
- 88 -
8 -Orientação por Objetos e C++
.
.
};
// uma classe classe_a
class classe_a {
private:
// um Objeto da classe_b declarado dentro da class_a
classe_b b_;
};
8.4 Herança
Como foi dito em Herança, quando uma Classe herda de outra, recebe os
métodos e atributos públicos, que se mantém públicos; os atributos e
métodos protegidos, que se tornam privativos; e não recebe os atributos ou
métodos privativos.
class classe_a {
};
class classe_b : public classe_a {
};
Entretanto, podemos definir a herança como protegida ou privativa. Na
protegida, os métodos e atributos públicos se tornam protegidos; os
atributos e métodos protegidos, e os atributos ou métodos privativos, não
são herdados.
class classe_a {
};
class classe_b : protected classe_a {
};
Na herança privativa, os os métodos e atributos públicos se tornam
privativos, e os demais não são herdados.
class classe_a {
- 89 -
8 -Orientação por Objetos e C++
};
class classe_b : private classe_a {
};
class classe_a {
};
class classe_b {
};
class classe_a : public classe_a, public classe_b {
};
Os tipos de herança, e suas consequencias na visibilidade dos atributos e
métodos herdados, descritas no tópico acima, continuam valendo para a
herança múltipla.
8.5 Construtores
Construtores são métodos que são executados quando um Objeto é criado.
É possível declarar mais de um construtor para uma Classe.
Class classe_a {
public:
// construtor sem argumentos
classe_a();
// construtor com um argumento
classe_a(int i);
private:
// um atributo de um tipo básico
int i_;
};
- 90 -
8 -Orientação por Objetos e C++
// definição do primeiro construtor
classe_a::classe_a() :
i_(1) {
}
// definição do segundo construtor
classe_a::classe_a(int i) :
i_(i) {
}
Reparem que os métodos construtores admitem uma sintaxe especial para
inicializar os atributos:
nome_da_classe::construtor(lista_argumentos) :
atributo_1(valor_1),
atributo_2(valor_2) {
}
Esta inicialização dos atributos garante que os construtores das Classes
dos atributo serão chamados, e assim teremos também os atributos
construídos correta e confiavelmente.
// declaração de um Objeto da classe_a usando o primeiro construtor
classe_a a0;
class_a a1(9);
class classe_a {
public:
// um construtor com argumentos
classe_a (int i);
// construtor que tem como argumento um outro Objeto
// também da classe_a
// como não iremos modificar este outro Objeto,
- 91 -
8 -Orientação por Objetos e C++
// qualificamos o argumento como const, e para evitar que ao
// passarmos o outro Objeto, uma cópia seja feita do Objeto
// passado para o parâmetro, passamos o endereço, assim, o
// parâmetro vai conter o endereço do Objeto passado
classe_a(const classe_a &outro_obj);
private:
int i_;
};
// Definindo o construtor com um argumento
classe_a::classe_a(int i) :
i_(i) {
}
// Definindo o construtor de cópia
classe_a::classe_a (const classe_a &outro_obj) :
i_(outro_obj.i_) {
}
Reparem que embora i_ seja atributo privativo de classe_a, eu consigo
acessar o i_ pertencente ao parâmetro outro_obj. Isto é possível porque o
código está dentro do escopo da classe_a.
// usando o construtor com um parâmetro
classe_a a0(7);
// usando o construtor por cópia
classe_a a1(a0);
Vamos ilustrar o que aconteceria se declarássemos o construtor de cópia
assim classe_a(classe_a outro_obj);. Após a linha classe_a a0(7)
teríamos:
- 92 -
8 -Orientação por Objetos e C++
- 93 -
8 -Orientação por Objetos e C++
8.6 Destrutores
Destrutor é um método que é chamado automaticamente quando um
Objeto termina seu ciclo de vida, ou seja, perde o escopo.
classe_a {
public:
~classe_a();
};
// declarando um Objeto da classe_a em um bloco de comando:
{
classe_a a0;
// outro comandos..
} // exatamente neste fechachaves, o destrutor da
- 94 -
8 -Orientação por Objetos e C++
// classe_a é chamado para a0
No destrutor é colocado código para liberar memória, fechar arquivos,
enfim, liberar recursos que foram alocados durante o ciclo de vida de um
Objeto.
8.7 Métodos
Métodos são funções declaradas dentro de uma Classe.
class classe_a {
public:
// construtor
classe_a(const int &i);
// destrutor
~classe_a(const int &i);
// a declaração do método
float m1(int k = 0);
// a declaração de um método que garante que nenhum atributo de
classe_a será modificado
const & i get_i() const;
private:
int i_;
};
// as definições dos métodos
classe_a::classe_a(const int & i)
: i_(i) {
}
classe_a::~classe_a() {
}
- 95 -
8 -Orientação por Objetos e C++
float class_a::m1(int k) {
return 7.5 * (i_ + k);
}
const int &class_a::get_i() const {
return i_;
}
8.7.1 Sobrecarga
É possível ter dois métodos com o mesmo nome, mas tendo diferentes
argumentos.
classe_a {
public:
// construtor com um argumento
classe_a(int i);
// método m com um argumento
void m(int i);
// método m com nenhum argumento
void m();
private:
int i_;
};
// definição do construtor
classe_a::classe_a(int i) :
i_(i) {}
// definição do método m com um parâmetro
void classe_a::m(int i) {
i_ += i;
}
// definição do método m com nenhum parâmetro
void classe_a::m() {
- 96 -
8 -Orientação por Objetos e C++
i_ += 8;
}
Quando declaramos um Objeto de classe_a, e usarmos os dois método, o
compilador sabe qual deles deve associar o endereço a ser colocado no
Instruction Pointer.
classe_a a0(18);
a0.m(3);
a0.m();
Ao final, a0::i_ terá o valor 29.
classe_a {
public:
classe_a();
// para ser virtual, o método deve ter na sua declaração a
// palavra reservada 'virtual' antes da especificação da Classe
// do Objeto que irá retornar
virtual float m(int i);
private:
int i_;
};
// uma subclasse
classe_b : public classe_b {
public:
classe_b();
float m(int i);
};
// definindo classe_a
classe_a::classe_a() :
i_(1) {
- 97 -
8 -Orientação por Objetos e C++
}
float classe_a::m(int i) {
return 6.2 + (i_ * i);
}
// definindo classe_b
classe_b::classe_b() :
classe_a() {
}
float classe_b::m(int i) {
return 0.23 * (i_ / i);
}
// usando...
classe_b b;
b.m(3);
O método que será executado em b.m(3) será o método classe_b::m(int
i);.
classe_a {
public:
classe_a();
// para ser abstrato, o método deve ter na sua declaração a
// palavra reservada 'virtual' antes da especificação da Classe
// do Objeto que irá retornar, e antes do ';' deve ter
// os símbolos '= 0'
virtual float m(int i) = 0;
private:
int i_;
};
// uma subclasse
- 98 -
8 -Orientação por Objetos e C++
classe_b : public classe_b {
public:
classe_b();
float m(int i);
};
// definindo classe_a
classe_a::classe_a() :
i_(1) {
}
// definindo classe_b
classe_b::classe_b() :
classe_a() {
}
float classe_b::m(int i) {
return 0.23 * (i_ / i);
}
8.8 Polimorfismo
Vamos mostrar uma implementação do exemplo do Canil de Polimorfismo.
//
// classe base da hierarquia
class cao {
public:
// construtor default
cao();
// destrutor virtual, necessário pois a classe haverá subclasses
~cao();
// método virtual abstrato, ou virtual puro, que garante, na
// verdade, obriga, que toda subclasse implemente
virtual void late() = 0;
};
- 99 -
8 -Orientação por Objetos e C++
// implementação dos métodos de cao
cao::cao() {
}
cao::~cao() {
}
//
class pastor_alemao : public cao {
public:
pastor_alemao();
~pastor_alemao();
void late();
};
// implementação dos métodos da classe pastor_alemao
pastor_alemao::pastor_alemao() {
}
pastor_alemao::~pastor_alemao() {
}
void pastor_alemao::late() {
cout << “eu sou um pastor alemao” << endl;
}
//
class buldogue : public cao {
public:
buldogue();
~buldogue();
- 100 -
8 -Orientação por Objetos e C++
void late();
};
// implementação dos métodos da classe buldogue
buldogue::buldogue() {
}
buldogue::~buldogue() {
}
void pastor_alemo::late() {
cout << “eu sou um buldogue” << endl;
}
//
// declaração da classe canil, que conterá os vários objetos da classe
// cao
// vamos limitar o número de cães em 10
#define MAX_CAES 10
class canil {
public:
// construtor
canil();
// destruttor
~canil();
// método que fará todos os cães latirem
void late();
// método que insere um novo cão
// retorna true se foi possível inserir, ou false se o canil
// estiver cheio
bool novo_cao(cao *c);
private:
// vamos implementar o canil como um array criado dinamicamente
- 101 -
8 -Orientação por Objetos e C++
cao *caes_;
// guarda a quantidade de cães realmente existentes
int qtde_caes;
};
// implementação dos métodos da classe canil
canil::canil() :
caes_(new cao[MAX_CAES]),
qtde_caes(0) {}
canil::~canil() {
if (caes_)
delete caes_[];
}
void late() {
if (qtde_caes == 0) {
cout << “canil vazio!” << endl;
}
else {
for (int i = 0; i < qtde_caes; ++i) {
caes_[i]>late();
}
}
}
bool novo_cao (cao *c) {
bool rc = false;
if (qtde_caes < MAX_CAES) {
caes_[qtde_caes] = c;
++qtde_caes;
rc = true;
}
return rc;
}
- 102 -
8 -Orientação por Objetos e C++
//
// um extrato do programa que usaria a classe canil
canil c;
if (!c.novo_cao(new buldogue()) {
cout << “canil cheio!” << endl;
}
else if (!c.novo_cao(new pastor_alemao()) {
cout << “sem vaga para o pastor alemão...” << endl;
}
c.late();
// a saída desse programa seria:
eu sou um buldogue
eu sou um pastor alemao
class classe_a {
public:
classe_a (int i);
void m(int i);
private:
int i_;
};
classe_a::classe_a(int i) :
i_(i) {
}
classe_a::m(int i) {
this>i_ = i;
}
- 103 -
8 -Orientação por Objetos e C++
8.10 Operadores
Com o objetivo de mais fielmente possível construir objetos virtuais que
sejam semelhantes aos objetos concretos que representam, C++ permite
definir operadores em uma Classe.
class complexo {
public:
// um número complexo é composto de uma parte real,
// e outra imaginária
// este construtor define valores padrões para os argumentos
complexo (float r = 0, float i = 0);
// como um número complexo concreto, como definido na matemática
// é possível comparar dois números complexos
// a palavra reservada 'const' antes do ';' indica que este
método não irá
// modificar atributos da classe complexo
bool operator == (const complexo &c) const;
// novamente, imitando a matemática, queremos saber se um número
// complexo é diferente de outro
bool operator != (const complexo &c) const;
// como um número complexo matemático, queremos atribuir um
// número complexo a outro
complexo &operator = (const complexo &c);
private:
// a parte real
float r_;
// a parte imaginária
float i_;
};
- 104 -
8 -Orientação por Objetos e C++
// definindo a classe complexo
complexo::complexo(float r, float i) :
r_(r), i_(i) {
}
bool complexo::operator == (const complexo &c) {
return ( (r_ == c.r_) && (i_ == c.i_) );
}
bool complexo::operator != (const complexo &c) {
return ( !(*this == c));
}
const complexo &complexo::operator = (const complexo &c) {
if (this != &c) {
this>i_ = c.i_;
}
return *this;
}
Reparem que usamos o ponteiro this no operador == e no operador =,
neste usamos primeiramente para checar se o parâmetro c não é o próprio
Objeto, ou seja, se estou atribuindo um número complexo a ele mesmo.
Usando...
complexo c0(4.5, 0.2);
complexo c1 (0.2, 4.5);
if (c1 == c0) {
cout << “c1 == c0”;
}
else {
cout << “c1 != c0”;
}
// aqui usamos o construtor comm os valores padrão padrões
// para os parâmetros
complexo c2;
c2 = c1;
if (c1 == c2) {
cout << “c1 == c2”;
- 105 -
8 -Orientação por Objetos e C++
}
else {
cout << “c1 != c2”;
}
namespace n0 {
class classe_a {...}
}
namespace n1 {
class classe_a{...}
}
Para identificarmos completamente um símbolo devemos explicitamente
identificar o namespace onde está incluído.
n0::classe_a a0;
n1::classe_a a1;
a0 e a1 são Objetos de Classes completamente distintas, pois a0 é instância
de classe_a, definida em n0; enquanto que a1 é instância de classe_a
definida em n1.
- 106 -
8 -Orientação por Objetos e C++
Arquivo cao.h:
#ifndef __cao_h__
#define __cao_h__
//
// classe base da hierarquia
class cao {
public:
// construtor default
cao();
// destrutor virtual, necessário pois a classe haverá subclasses
~cao();
// método virtual abstrato, ou virtual puro, que garante, na
// verdade, obriga, que toda subclasse implemente
virtual void late() = 0;
};
#endif
Arquivo cao.cpp:
#include “cao.h”
// implementação dos métodos de cao
cao::cao() {
}
cao::~cao() {
- 107 -
8 -Orientação por Objetos e C++
Arquivo pastor_alemao.h:
#ifndef __pastor_alemao_h__
#define __pastor_alemao_h__
//
class pastor_alemao : public cao {
public:
pastor_alemao();
~pastor_alemao();
void late();
};
#endif
Arquivo pastor_alemao.cpp:
#include “pastor_alemao.h”
// em iosteam.h estão declarados os símbolos cout e endl
// os arquivos de cabeçalho da biblioteca padrão C++ não tem
// (infelizmente) a extensão .h
#include <iostream>
// implementação dos métodos da classe pastor_alemao
pastor_alemao::pastor_alemao() {
}
pastor_alemao::~pastor_alemao() {
}
void pastor_alemao::late() {
std::cout << “eu sou um pastor alemao” << std::endl;
}
- 108 -
8 -Orientação por Objetos e C++
Arquivo buldogue.h:
#ifndef __buldogue_h__
#define __buldogue_h__
//
class buldogue : public cao {
public:
buldogue();
~buldogue();
void late();
};
#endif
Arquivo buldogue.cpp:
#include “buldogue.h”
// em iosteam.h estão declarados os símbolos cout e endl
#include <iostream>
// implementação dos métodos da classe buldogue
buldogue::buldogue() {
}
buldogue::~buldogue() {
}
void buldogue::late() {
std::cout << “eu sou um buldogue” << std::endl;
}
Arquivo canil.h:
#ifndef __canil_h__
#define __canil_h__
//
// declaração da classe canil, que conterá os vários objetos da classe
// cao
- 109 -
8 -Orientação por Objetos e C++
// vamos limitar o número de cães em 10
#define MAX_CAES 10
class canil {
public:
// construtor
canil();
// destruttor
~canil();
// método que fará todos os cães latirem
void late();
// método que insere um novo cão
// retorna true se foi possível inserir, ou false se o canil
// estiver cheio
bool novo_cao(cao *c);
private:
// vamos implementar o canil como um array criado dinamicamente
cao *caes_;
// guarda a quantidade de cães realmente existentes
int qtde_caes;
};
#endif
Arquivo canil.cpp:
#include “canil.h”
#include <iostream>
// implementação dos métodos da classe canil
canil::canil() :
caes_(new cao[MAX_CAES]),
qtde_caes(0) {}
- 110 -
8 -Orientação por Objetos e C++
canil::~canil() {
if (caes_)
delete caes_[];
}
void late() {
if (qtde_caes == 0) {
std::cout << “canil vazio!” << std::endl;
}
else {
for (int i = 0; i < qtde_caes; ++i) {
caes_[i]>late();
}
}
}
bool novo_cao (cao *c) {
bool rc = false;
if (qtde_caes < MAX_CAES) {
caes_[qtde_caes] = c;
++qtde_caes;
rc = true;
}
return rc;
}
#include “canil.h”
#include “cao.h”
#include “pastor_alemao.h”
#include “buldogue.h”
#include <iostream>
int main() {
canil c;
- 111 -
8 -Orientação por Objetos e C++
if (!c.novo_cao(new buldogue()) {
std::cout << “canil cheio!” << std::endl;
}
else if (!c.novo_cao(new pastor_alemao()) {
std::cout << “sem vaga para o pastor alemão!” << std::endl;
}
c.late();
return 0;
}
Importante observar as instruções:
#ifndef __cao_h__
#define __cao_h__
.
.
#endif
- 112 -
9 -A biblioteca padrão C++
- 113 -
9 -A biblioteca padrão C++
template <typename T>
classe_a {
public:
a (T & t0);
~a();
- 114 -
9 -A biblioteca padrão C++
const T & get_t() const;
string to_str() const;
private:
T t_;
};
// definições
template <typename T>
classe_a<T>::a(T &t0) :
t_(t0) {
}
template <typename T>
classe_a<T>::~a(T &t0) {
}
template <typename T>
const T & classe_a<T>::get_t() const {
return t_;
}
template <typename T>
string & classe_a<T>::to_str() const {
return t_.to_str();
}
// declaração da classe_b
classe_b {
public:
classe_b(const int & i) ;
~classe_b();
classe_b(const classe_b &r);
string to_str() const;
private:
int i_;
};
- 115 -
9 -A biblioteca padrão C++
// definições da classe_b
classe_b::classe_b(const int & i) :
i_(i) }
}
classe_b::~classe_b() {
}
classe_b::classe_b(const classe_b &r) :
i_(r.i) {
}
string classe_b::to_str() const {
stringstream s;
s << i_;
return s.str();
}
// declaração da classe_c
classe_c {
public:
classe_c(const float & f) ;
~classe_c();
classe_c(const classe_c &r);
string to_str() const;
private:
float f_;
};
// definições da classe_c
classe_c::classe_c(const float & i) :
f_(f) }
}
classe_c::~classe_c() {
}
classe_c::classe_c(const classe_c &r) :
f_(r.f) {
}
string classe_c::to_str() const {
- 116 -
9 -A biblioteca padrão C++
stringstream s;
s << f_;
return s.str();
}
// uso
int main () {
classe_a<classe_b> a0(classe_b(9));
cout << a0.to_str() << endl;
classe_a<classe_c> a1(classe_c(0.32));
cout << a1.to_str() << endl;
return 0;
}
- 117 -
9 -A biblioteca padrão C++
● Vectors
● Lists
● Double-Ended Queues
● Stacks
● Queues
● Priority Queues
● Bitsets
● Maps
● Multimaps
● Sets
● Multisets
- 118 -
9 -A biblioteca padrão C++
#include <vector>
#include <iostream>
#include <cstdlib>
using namespace std;
int main () {
// cria um vetor de inteiros de 10 posições, e inicializa
// cada uma com 4
vector <int> v(10, 4);
// vamos percorrer o vetor, atualizando o valor do
// inteiro armazenado em cada posição
vector<int>::iterator i = v.begin();
while (i != v.end()) {
*i = *i * rand();
// agora vamos percorrer novamente o vetor, e imprimir o valor
- 119 -
9 -A biblioteca padrão C++
// do inteiro em cada posição
// primeiro reposicionamos o iterator no início do vetor
i = v.begin();
// aqui declaramos um inteiro compatível com o tipo de tamanho do
// vetor
vector<int>::size_type k = 0;
// agora percorremos o vetor
while (i != v.end()) {
cout << “v[“ << k++ << “] = ” << *i << endl;
9.5 String
Vimos em Ponteiros para caracteres uma maneira de trabalharmos com
uma sequencia de caracteres – string – usando ponteiros para caracteres. É
desta forma que a linguagem C manipula strings.
Em C++ existe uma classe específica para usarmos uma string, a classe
string, cuja interface é:
● string &append(const string &str);
● string &append(const string &str, size_type indx, size_type
len);
● string &append(const CharType *str);
● string &append(const CharType *str, size_type num);
● string &append(size_type len, CharType ch);
● template<class InIter> string &append(InIter start, InIter
end);
● string &assign(const string &str);
● string &assign(const string &str, size_type indx, size_type len);
● string &assign(const CharType *str);
● string &assign(const CharType *str, size_type len);
- 120 -
9 -A biblioteca padrão C++
● string &assign(size_type len, CharType ch);
● template<class InIter> string &assign(InIter start, InIter end);
● reference at(size_type indx);
● const_reference at(size_type indx) const;
● iterator begin( );
● const_iterator begin( ) const;
● const CharType *c_str( ) const;
● size_type capacity( ) const;
● int compare(const string &str) const;
● int compare(size_type indx, size_type len, const string &str)
const;
● int compare(size_type indx, size_type len, const string &str,
size_type indx2,size_type len2) const;
● int compare(const CharType *str) const;
● int compare(size_type indx, size_type len, const CharType *str,
size_type len2 = npos) const;
● size_type copy(CharType *str, size_type len, size_type indx = 0)
const;
● const CharType *data( ) const;
● bool empty( ) const;
● iterator end( );
● const_iterator end( ) const;
● iterator erase(iterator i);
● iterator erase(iterator start, iterator end);
● string &erase(size_type indx = 0, size_type len = npos);
● size_type find(const string &str, size_type indx = 0) const;
● size_type find(const CharType *str, size_type indx = 0) const;
● size_type find(const CharType *str, size_type indx, size_type
len) const;
● size_type find(CharType ch, size_type indx = 0) const;
● size_type find_first_of(const string &str, size_type indx = 0)
const;
● size_type find_first_of(const CharType *str, size_type indx = 0)
const;
● size_type find_first_of(const CharType *str, size_type indx,
size_type len) const;
● size_type find_first_of(CharType ch, size_type indx = 0) const;
● size_type find_first_not_of(const string &str, size_type indx =
- 121 -
9 -A biblioteca padrão C++
0) const;
● size_type find_first_not_of(const CharType *str, size_type indx =
0) const;
● size_type find_first_not_of(const CharType *str, size_type indx,
size_type len) const;
● size_type find_first_not_of(CharType ch, size_type indx = 0)
const;
● size_type find_last_of(const string &str, size_type indx = npos)
const;
● size_type find_last_of(const CharType *str, size_type indx =
npos) const;
● size_type find_last_of(const CharType *str, size_type indx,
size_type len) const;
● size_type find_last_of(CharType ch, size_type indx = npos) const;
● size_type find_last_not_of(const string &str, size_type indx =
npos) const;
● size_type find_last_not_of(const CharType *str, size_type indx =
npos) const;
● size_type find_last_not_of(const CharType *str, size_type indx,
size_type len) const;
● size_type find_last_not_of(CharType ch, size_type indx = npos)
const;
● allocator_type get_allocator( ) const;
● iterator insert(iterator i, const CharType &ch );
● string &insert(size_type indx, const string &str);
● string &insert(size_type indx1, const string &str, size_type
indx2, size_type len);
● string &insert(size_type indx, const CharType *str);
● string &insert(size_type indx, const CharType *str, size_type
len);
● string &insert(size_type indx, size_type len, CharType ch);
● void insert(iterator i, size_type len, const CharType &ch)
● template <class InIter> void insert(iterator i, InIter start,
InIter end);
● size_type length( ) const;
● size_type max_size( ) const;
● reference operator[ ](size_type indx) const;
● const_reference operator[ ](size_type indx) const;
● string &operator=(const string &str);
● string &operator=(const CharType *str);
- 122 -
9 -A biblioteca padrão C++
● string &operator=(CharType ch);
● string &operator+=(const string &str);
● string &operator+=(const CharType *str);
● string &operator+=(CharType ch);
● reverse_iterator rbegin( );
● const_reverse_iterator rbegin( ) const;
● reverse_iterator rend( );
● const_reverse_iterator rend( ) const;
● string &replace(size_type indx, size_type len, const string
&str);
● string &replace(size_type indx1, size_type len1, const string
&str, size_type indx2, size_type len2);
● string &replace(size_type indx, size_type len, const CharType
*str);
● string &replace(size_type indx1, size_type len1, const CharType
*str, size_type len2);
● string &replace(size_type indx, size_type len1, size_type len2,
CharType ch);
● string &replace(iterator start, iterator start, const string
&str);
● string &replace(iterator start, iterator start, const CharType
*str);
● string &replace(iterator start, iterator end, const CharType
*str, size_type len);
● string &replace(iterator start, interator end, size_type len,
CharType ch);
● template <class InIter> string &replace(iterator start1,
interator end1, InIter start2, InIter end2);
● void reserve(size_type num = 0);
● void resize(size_type num)
● void resize(size_type num, CharType ch);
● size_type rfind(const string &str, size_type indx = npos) const;
● size_type rfind(const CharType *str, size_type indx = npos)
const;
● size_type rfind(const CharType *str, size_type indx, size_type
len) const;
● size_type rfind(CharType ch, size_type indx = npos) const;
● size_type size( ) const;
● string substr(size_type indx = 0, size_type len = npos) const;
- 123 -
9 -A biblioteca padrão C++
● void swap(string &str);
● accumulate
● adjacent_difference
● adjacent_find
● binary_search
● copy
● copy_backward
● count_if
● equal
● equal_range
● fill
● find
● find_end
● find_first_of
● find_if
● for_each
● generate
● generate_n
● includes
● inner_product
● inplace_merge
● is_heap
● is_sorted
● iter_swap
● lexicographical_compare
● lower_bound
● make_heap
● max
- 124 -
9 -A biblioteca padrão C++
● max_element
● merge
● min
● min_element
● mismatch
● next_permutation
● nth_element
● partial_sort
● partial_sort_copy
● partial_sum
● partition
● pop_heap
● prev_permutation
● push_heap
● random_shuffle
● remove
● remove_copy
● remove_copy_if
● remove_if
● replace
● replace_copy
● replace_copy_if
● replace_if
● reverse
● reverse_copy
● rotate
● rotate_copy
● search
● search_n
● set_difference
● set_intersection
● set_symmetric_difference
● set_union
● sort
● sort_heap
● stable_partition
- 125 -
9 -A biblioteca padrão C++
● stable_sort
● swap
● swap_ranges
● transform
● unique
● unique_copy
● upper_bounds
- 126 -
10 -Implementação do Estudo de Caso
// C++ headers
// 3rds headers
// our headers
// namespaces
using namespace std;
// macro constants
// macro commands
namespace tenacitas { namespace <NAMESPACE> {
// predeclarations
/// brief documentation
///
/// detailed documentation
class <CLASS_NAME> {
// <CLASS_NAME> FRIENDS
// classes
- 127 -
10 -Implementação do Estudo de Caso
// methods
// operators
public:
// <CLASS_NAME> PUBLIC internal classes
// <CLASS_NAME> PUBLIC constructors
// <CLASS_NAME> PUBLIC gets
// <CLASS_NAME> PUBLIC sets
// <CLASS_NAME> PUBLIC helpers
// <CLASS_NAME> PUBLIC processors
// <CLASS_NAME> PUBLIC operators
// <CLASS_NAME> PUBLIC attributes
protected:
// <CLASS_NAME> PROTECTED internal classes
// <CLASS_NAME> PROTECTED constructors
// <CLASS_NAME> PROTECTED gets
// <CLASS_NAME> PROTECTED sets
// <CLASS_NAME> PROTECTED helpers
// <CLASS_NAME> PROTECTED processors
- 128 -
10 -Implementação do Estudo de Caso
// <CLASS_NAME> PROTECTED operators
// <CLASS_NAME> PROTECTED attributes
private:
// <CLASS_NAME> PRIVATE internal classes
// <CLASS_NAME> PRIVATE constructors
// <CLASS_NAME> PRIVATE gets
// <CLASS_NAME> PRIVATE sets
// <CLASS_NAME> PRIVATE helpers
// <CLASS_NAME> PRIVATE processors
// <CLASS_NAME> PRIVATE operators
// <CLASS_NAME> PRIVATE attributes
};
} }
#endif
- 129 -
10 -Implementação do Estudo de Caso
- 130 -
11 -Literatura
11 Literatura
- 131 -