SlideShare a Scribd company logo
1 of 150
Download to read offline
C++ 200
UM MINICURSO
Prof. Ms. Peter Jandl Junior
ADS & GTI
FATEC Jundiaí
POR QUÊ C++?
20/04/2017 (C) 2017, PJANDL. 2
20/04/2017 (C) 2017, PJANDL. 3
Não é razão
suficiente?
ROTEIRO
Parte I::Visão Geral
 Origens, Características, Abstração, Recursos
Necessários.
Parte II::Fundamentos
 Estrutura dos Programas, Variáveis, Palavras
Reservadas, Tipos de Dados, Constantes,
Conversão de Tipos, Console, Escopo,
Operadores, Precedência, Diretivas de
Controle.
Parte III::Estruturas de Dados
 Arranjos, Ponteiros, Alocação Dinâmica,
Enumerações, Estruturas, Uniões.
Parte IV::Funções
 Definição, Declaração, Prototipagem, Passagem
de Parâmetros, Valores Default, Sobrecarga.
Parte V::OO Básica
 Classes, Membros, Acessibilidade, Construtores,
Destrutores, Sobrecarga, Ponteiro this.
Parte VI::OO Intermediária
 Funções Amigas, Classes Amigas, Sobrecarga
de Operadores, Herança Simples, Herança
Múltipla, Polimorfismo.
Parte VII::OO Avançada
 Funções Virtuais, Classes Abstratas.
20/04/2017 (C) 2017, PJANDL. 4
PARTE I::
VISÃO GERAL
C++ 200
UM MINICURSO
20/04/2017 (C) 2017, PJANDL. 5
C++::ORIGENS
Para superar as limitações da linguagem C, Bjarne Stroustrup constrói, em 1980 nos
Laboratórios Bell (Nova Jérsei, EUA), um conjunto de extensões para permitir a
criação de programas melhores e mais complexos, principalmente do ponto de vista
de projeto.
 Estrutura sintática da linguagem C
 Conceitos de classe da linguagem Simula67
 Sobrecarga de operadores do Algol68
Resultou no “C with Classes”, cujo nome foi alterado para C++ (“C plus plus” cujo
sentido pretendido era “C com algo mais”).
A adoção surpreendentemente grande fez com que fosse padronizada pela ANSI e
ISO em 1990. Atualmente seu padrão é a ISO/IEC 14882.
20/04/2017 (C) 2017, PJANDL. 6
20/04/2017 (C) 2017, PJANDL. 7
C++::CARACTERÍSTICAS
Simplicidade
 Estrutura sintática simples e concisa. Oferece
sistema de divisão modular que favorece o
reuso.
Performance
 Ausência de restrições e mecanismos embutidos
de controle possibilitam a geração de código
em linguagem de máquina conciso e muito
eficiente.
Portabilidade
 A padronização efetiva faz com que, quando
seguida, possibilite a recompilação do código
fonte para diferentes plataformas sem
necessidade de qualquer ajuste ou alteração.
Versatilidade
 Embora com sintaxe simples, é uma linguagem
de alto nível que permite a expressão de
algoritmos e estruturas de dados sofisticadas,
acesso ao hardware e integração com outras
linguagens de programação.
20/04/2017 (C) 2017, PJANDL. 8
C++::ABSTRAÇÃO
C++ permite que a programação seja
realizada de maneira genérica.
Possibilita a definição de novos tipos.
Garante isolamento adequado entre
as funcionalidades existentes.
Permite uso amplo e eficiente dos
conceitos da programação orientada a
objetos.
20/04/2017 (C) 2017, PJANDL. 9
C++::RECURSOS NECESSÁRIOS
GNU C++ Compiler [“nativo” no Linux, disponível para Windows como MinGW:
http://www.mingw.org/ ]
Dev C++ [IDE free, open source, disponível para Windows e outras
plataformas: http://www.bloodshed.net/dev/devcpp.html ]
Eclipse C++ IDE [tradicional IDE Java com plugins para desenvolvimento C++:
http://www.bloodshed.net/dev/devcpp.html
Requer MinGW em sistemas Windows]
VisualStudio C++ [IDE popular da Microsoft também permite desenvolvimento
voltado para C++]
20/04/2017 (C) 2017, PJANDL. 10
PARTE II::
FUNDAMENTOS
C++ 200
UM MINICURSO
20/04/2017 (C) 2017, PJANDL. 11
(O)
EXEMPLO _HELLO
(MAIS TRADICIONAL DE TODO MUNDO)
/* Arquivo: main01.cpp
Autor: Prof. Peter Jandl Jr
*/
#include <iostream>
using namespace std;
int main() {
// impressão de mensagem no console
cout << "Hello world!" << endl;
// finalização do main (funcão principal)
return 0;
}
20/04/2017 (C) 2017, PJANDL. 12
include: efetua a
inclusão de uma
biblioteca no programa.
using namespace:
indica o uso de um
espaço declarativo
(no caso o padrão std).
Para um programa mínimo em
C++ basta remover a diretiva de
impressão cout.
C++::PROGRAMAÇÃO
20/04/2017 (C) 2017, PJANDL. 13
Editor
ASCII
Compilador
C/C++
Arquivo
Fonte
Arquivo
Objeto
Arquivo
Executável
Bibliotecas Ligador
C++::ESTRUTURA DOS PROGRAMAS
Programa em linguagem C++
são compostos de um ou mais
arquivos de programa fonte,
cada um considerado uma
unidade de compilação (ou
translation unit).
Cada unidade de compilação
pode conter:
diretivas do pré-processador
(include, define, if, ifdef...)
declarações de:
variáveis;
estruturas de dados;
funções; e
classes.
implementação de:
funções; e
classes.
20/04/2017 (C) 2017, PJANDL. 14
C++::VARIÁVEIS
Variáveis são nomes definidos pelo
programador para os quais podem ser
associados valores.
Em linguagens fortemente tipadas, como
C++, tais valores devem pertencer a um
tipo (que determina uma faixa de
valores aceitáveis ou pertencentes a um
elemento).
Sintaxe:
<Tipo> <nome1> [, <nome2> [...] ];
Identificadores válidos:
 sequência de um ou mais caracteres alfabéticos,
dígitos numéricos e `_` (sublinhado), iniciados
por letra ou sublinhado.
 usualmente apenas 32 primeiros caracteres são
usados para distinção dos identificadores.
 C++ é sensível ao caixa, ou seja, diferencia
maiúsculas de minúsculas.
 Palavras reservadas não podem ser usadas
como identificadores.
20/04/2017 (C) 2017, PJANDL. 15
C++::KEYWORDS*
(PALAVRAS RESERVADAS*)
auto bool break case catch char
class const const_cast continue default delete
do double dynamic_cast else enum explicit
export extern false float for friend
goto if inline int long mutable
namespace new operator private protected public
register reinterpret_cast return short signed sizeof
static static_cast struct switch template this
throw true try typedef typeid typename
union unsigned using virtual void volatile
while
20/04/2017 (C) 2017, PJANDL. 16
São destacadas as
47 que serão vistas
neste tutorial.
C++ possui 61
keywords.
*Emitálico,keywordscompatilhadascomC.
C++::TIPOS DE DADOS
Estão disponíveis os tipos de dados pré-
definidos típicos da maioria das LPs:
caracteres
inteiros
ponto flutuante
lógico
Também existem tipos derivados e a
possibilidade de definição de novos tipos
por parte do programador.
Tipos de
Dados C++
Tipos de
Dados C++
Pré-
definidos
Pré-
definidos
IntegraisIntegrais
charchar
intint
Ponto
flutuante
Ponto
flutuante
floatfloat
doubledouble
LógicoLógico boolbool
DerivadosDerivados
ArranjoArranjo
FunçãoFunção
PonteiroPonteiro
ReferênciaReferência
DefiníveisDefiníveis
EnumeraçãoEnumeração
EstruturaEstrutura
ClasseClasse
UniãoUnião
20/04/2017 (C) 2017, PJANDL. 17
C++::TIPOS DE DADOS
Existem modificadores
short
long
signed
unsigned
Quando aplicados aos tipos integrais
permitem reduzir/ampliar a faixa de
valores e também desconsiderando o
sinal.
Existe também o tipo void, especial,
que sinaliza a ausência de resultado.
20/04/2017 (C) 2017, PJANDL. 18
C++::TIPO DE DADOS
Caracteres
char letra = 'J';
char especial = 'n';
char hexa = 'x61';  caractere 'a'
20/04/2017 (C) 2017, PJANDL. 19
C++::TIPOS DE DADOS
Inteiros
int a = 2;
signed int x = -13;
long int y = 95000L; // sufixo L
unsigned int z = 765u; // sufixo u
int h = 0xCAFE; // prefixo 0x : hexa
int octal = 02000; // prefixo 0 : octal
Dica
Arquivo de cabeçalho (header file)
"climits.h" da biblioteca padrão contém
os tamanhos em bytes, bem como os
valores mínimos e máximos dos tipos
primitivos e outros eventualmente
adicionados pela implementação.
20/04/2017 (C) 2017, PJANDL. 20
C++::TIPOS DE DADOS
Ponto flutuante
float f = 1.46;
float c = -25.34e8;
double d = 534.789e-11;
long double ld = 143.2314673595l;
Lógico
bool flag = true;
bool error = false;
Também existe equivalência entre tipos
lógicos e numéricos, tal como na
linguagem C:
 valores iguais a zero equivalem a false
 valores diferentes de zero equivale a true
20/04/2017 (C) 2017, PJANDL. 21
long também se aplica ao tipo
double e suas constantes
requerem o sufixo l ou L.
EXEMPLO _SIZEOF
/* Arquivo: main02.cpp
Autor: Prof. Peter Jandl Jr
*/
#include <iostream>
using namespace std;
int main() {
cout << " char:" << sizeof(char) << "n bool:" << sizeof(bool) << endl;
cout << " short:" << sizeof(short) << "n int:" << sizeof(int) << endl;
cout << " long:" << sizeof(long) << "n float:" << sizeof(float) << endl;
cout << " double:" << sizeof(double) << "n long double:"
<< sizeof(long double) << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 22
sizeof retorna o
tamanho em bytes do
tipo indicado
endl é uma constante
e representa o fim de
uma linha de texto.
C++::CONSTANTES
Definidas
Identificador associado a um valor literal
constante.
#define <id> <valor>
Exemplos:
#define PI 3.1415926
#define MAX 1024
Durante pré-processamento do programa,
identificador será substituído pelo literal
previamente indicado.
Declaradas
Variável cujo conteúdo está associado
ao tipo especificado, mas que não pode
ter valor alterado durante execução do
programa.
const <tipo> <id> = <expr>;
Exemplos:
const double PI = 3.1415926;
const long MAX = 1024L;
20/04/2017 (C) 2017, PJANDL. 23
C++::MODIFICADORES DE ACESSO
const
Define um elemento que não pode ser
modificado pelo programa.
Pode ser usado para declaração de
constantes, como já visto, e também
para indicar parâmetros que não
podem ser modificados por funções ou
métodos:
<tipoRet> nomeF ( const <tipo> param [, ...] );
size_t strlen(cont char *str);
volatile
Indica ma variável cujo conteúdo pode
ser alterado de maneira indireta, não
causada pelo próprio programa.
volatile <tipo> id;
Exemplos dessa situação são variáveis
compartilhadas entre o programa e o
sistema operacional, onde este último é
responsável pela atualização do
conteúdo da variável.
volatile unsigned char *clock = 0x3F;
20/04/2017 (C) 2017, PJANDL. 24
C++::CONVERSÃO DE TIPOS
A promoção automática de tipos é a
conversão implícita e automática de um
tipo mais simples para outro mais
complexo adequado à avaliação de
uma expressão.
int a = 1;
long b = 99999; // conversão
b = a + b; // conversão
float c = b * 0.33; // conversão
20/04/2017 (C) 2017, PJANDL. 25
bool char
int
long
float
double
long double
C++::CONVERSÃO DE TIPOS
20/04/2017 (C) 2017, PJANDL. 26
long
char
float float
char
char char
intint
long
long
float
char
doubledouble
int
long
float
int
float
double
double
long
double
int
double
char
long double long double
long double
long double
long
int
char
float
long double
long double
long double
Este diagrama mostra apenas
os tipos de dados principais
C++::CONVERSÃO DE TIPOS
A conversão explícita de tipos (coerção ou
type casting) permite que o
programador especifique uma
conversão desejada.
(tipo) expressão forma comum
tipo(expressão) forma funcional
Exemplos:
int a = 3, b = 2;
float c1 = a / b;
cout << c1; // exibe 1
float c2 = (float) a / b;
cout << c2; // exibe 1.5
20/04/2017 (C) 2017, PJANDL. 27
C++::CONSOLE
Entrada
A entrada direta pode utilizar outro
objeto pré-definido, cin (console in) que
permite o uso do dispositivo de entrada
padrão (teclado).
int x;
cin >> x;
float f;
cin >> f;
Saída
Exibição simples de valores e mensagens
pode ser feita por meio de cout (console
out), um objeto pré-definido que permite
a impressão no dispositivo de saída
padrão (console).
cout << 10;
cout << "Mensagem";
cout << "Concatenação: " << x
<< endl;
20/04/2017 (C) 2017, PJANDL. 28
Também existe um objeto pré-
definido para saída de erros,
cerr, semelhante a cout.
C++::ESCOPO
Escopo são os locais do programa nos
quais uma declaração específica tem
validade.
É o espaço declarativo de variáveis e
outras construções válidas.
C++ permite declarar variáveis em
qualquer ponto do código, as quais
serão válidas até o final do bloco onde
foram declaradas.
C++ oferece três níveis de escopo:
global, local e imediato.
Global
Local
Imediato
• Visível em todo
código.
• Visibilidade
limitada à função
ou método.
• Visibilidade
restrita ao bloco.
20/04/2017 (C) 2017, PJANDL. 29
EXEMPLO _ESCOPO
#include <iostream>
using namespace std;
int x = 10; // variável global
int main() {
cout << "x: " << x << endl;
int x = 20; // variável local
cout << "x: " << x << endl;
{
int x = 30; // variável imediata
cout << "x: " << x << endl;
cout << "x: " << ::x << endl; // uso do operador ::
}
cout << "x: " << x << endl;
cout << "x: " << ::x << endl; // uso do operador ::
return 0;
}
20/04/2017 (C) 2017, PJANDL. 30
Operador ::
(resolução de escopo)
provê acesso ao nível
global.
Variáveis
redeclaradas ocultam
o escopo exterior.
C++::OPERADORES
Aritméticos
+, -, *, / operadores algébricos
% resto da divisão inteira
++, -- incremento e decremento
unitários
Relacionais
==, != igualdade e diferença
>, >=,
<, <= comparadores
20/04/2017 (C) 2017, PJANDL. 31
C++::OPERADORES
Lógicos
&& e lógico
|| ou lógico
! não lógico (negação)
Bit-a-bit
& e bitwise
| ou bitwise
ˆ ou-exclusivo bitwise
~ complemento
>>, << deslocamento (shift) à
direita e à esquerda
20/04/2017 (C) 2017, PJANDL. 32
C++::OPERADORES
Atribuição
= atribuição
+=, -=, atribuição compacta
*=, /=,
%=, &=,
|=, ˆ=,
>>=, <<=
Exemplo:
x = x + 10;
x += 10;
Ternário
? : operador ternário
Permite seleção de um resultado entre
dois para uma expressão, baseado no
resultado de uma expressão lógica:
exprLog ? expr1 : expr2
onde:
exprLog seleciona o resultado
true toma expr1
false toma expr2
20/04/2017 (C) 2017, PJANDL. 33
C++
::PRECEDÊNCIA
A precedência é a ordem padronizada
com que os operadores da linguagem
são executados na avaliação de uma
expressão.
A precedência garante consistência
matemática na avaliação de expressões
algébricas, lógicas e relacionais, além
das operações associadas às estruturas
de dados e objetos.
20/04/2017 (C) 2017, PJANDL. 34
C++::CONTROLE
As diretivas que permitem realizar o
controle do fluxo de execução.
C++ oferece:
 diretivas de repetição
 diretivas de decisão
(ou desvio de fluxo)
 construções para modularização
 diretivas de controle de erros
20/04/2017 (C) 2017, PJANDL. 35
C++::CONTROLE
20/04/2017 (C) 2017, PJANDL. 36
Controle de fluxo estabelece como e
quais diretivas serão executadas.
C++::SEQUENCIAÇÃO
Organização da sequência de diretivas
da linguagem que conduzem a execução
do programa no sentido de produzir o
resultado desejado.
Diretivas em C++ devem ser separadas
por um ; (ponto-e-vírgula), organizadas
tipicamente uma em cada linha. Mas
várias diretivas podem existir numa
mesma linha, quando separadas
adequadamente.
As chaves { } permitem delimitar um
bloco de diretivas, que passarão a ser
tratadas como uma unidade.
//Exemplo _Seq
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double raio;
cout << "Raio? "; cin >> raio;
double area = M_PI * pow(raio, 2);
cout << "Area = " << area << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 37
Exemplo _Seq
C++::WHILE
Diretiva de repetição condicional.
int k = 0, j = 20;
while (k < j) {
cout << k << " menor " << j << endl;
k++;
j = j - 2;
}
20/04/2017 (C) 2017, PJANDL. 38
expressão
diretiva
falsaverdadeira
Os fragmentos que seguem podem ser
testados, bastando incluí-los num
programa mínimo.
Exemplo
_Fragmentos
C++::DO/WHILE
Diretiva de repetição condicional.
float valor, min=0, max=10;
do {
cout << "Digite valor [0..10]? ";
cin >> valor;
} while (valor<min || valor>max);
20/04/2017 (C) 2017, PJANDL. 39
expressão
diretiva
falsa
verdadeira
Exemplo
_Fragmentos
C++::FOR
Diretiva automática de repetição
condicional.
const int MAX = 5;
double soma = 0, numero;
for (int i=0; i<MAX; i++) {
cout << "#" << i << "? " << endl;
cin >> numero;
soma += numero;
}
cout << "Soma: " << soma << endl;
20/04/2017 (C) 2017, PJANDL. 40
expressãodiretiva
falsa
verdadeira
incremento ou
decremento
inicialização
Exemplo
_Fragmentos
C++::IF
Diretiva de desvio condicional simples.
int x;
cout << "Digite um inteiro para x: ";
cin >> x;
if (x < 0) {
cout << "x menor do que zero";
}
20/04/2017 (C) 2017, PJANDL. 41
expressão
diretiva1
falsaverdadeira
Exemplo
_Fragmentos
C++::IF/ELSE
Diretiva de desvio condicional completa.
int y;
cout << "Digite um inteiro para y: ";
cin >> y;
if (y > 0 && y < 11) {
cout << "y no intervalo [1..10]" << endl;
} else {
cout << "y fora do intervalo [1..10]" << endl;
}
20/04/2017 (C) 2017, PJANDL. 42
expressão
diretiva1
falsaverdadeira
diretiva2
Exemplo
_Fragmentos
C++::SWITCH
Diretiva de desvio condicional múltiplo, baseado em
expressão ordinal.
char letra;
cout << "Digite uma letra maiúscula entre A e E: ";
cin >> letra;
switch (letra) {
case "A": cout << "Conceito máximo";
break;
// :
case "E": cout << "Conceito mínimo";
break;
default:
cout << "Conceito inválido";
}
20/04/2017 (C) 2017, PJANDL. 43
expressão
ordinal
diretiva1
defaultcase 1
diretivaNdiretiva2 diretiva3
case 2
case 3

Exemplo
_Fragmentos
C++::GOTO
Diretiva de desvio incondicional.
goto <label>;
Onde label é um rótulo, definido acima
(antes) ou abaixo (depois) da diretiva.
label:
diretiva1;
diretiva2;
:
Rótulos devem ser declarados no mesmo
escopo onde diretiva goto é usada.
Embora possível e disponível na
linguagem C++, o uso da diretiva goto
é fortemente desencorajado, pois em
raríssimas situações é, de fato a melhor
alternativa. Em geral seu uso esconde
alguma deficiência no projeto do
algoritmo.
20/04/2017 (C) 2017, PJANDL. 44
EXEMPLO _GOTO
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
cout << "Caracteres ASCII [33..132]" << endl;
unsigned char c = 33;
int i = 0;
laco:
cout << c << " " << setw(3) << int(c) << "| ";
i++; c++;
if (i%10==0) { cout << endl; }
if (c<=132) { goto laco; }
return 0;
}
20/04/2017 (C) 2017, PJANDL. 45
Resultados do
programa
C++::BREAK & CONTINUE
break
Diretiva de desvio incondicional que
interrompe o comando corrente (um laço
ou decisão múltipla com switch), fazendo
que a execução prossiga no comando
subsequente àquele em que foi usado.
continue
Diretiva de desvio incondicional que
abrevia a iteração corrente do laço,
fazendo que a expressão de controle do
comando de repetição seja novamente
avaliada, acelerando assim a
continuação do comando de repetição.
20/04/2017 (C) 2017, PJANDL. 46
EXEMPLO _GRAFICO
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
int main() {
cout << "Polinomio de 2o. grau" << endl;
// coeficientes do polinômio deveriam ser lidos
double a = -1.5, b = 3.0, c = 2.2, xi, xf;
// intervalo da ordenada
cout << "Valor inicial da ordenada? "; cin >> xi; // 0
cout << "Valor final da ordenada? "; cin >> xf; // 2.4
// desenha eixo da abcissa
cout << “______0";
for (int i=1; i<6; i++) {
cout << "---------"<< i;
}
cout << " (Y)" << endl;
// plota polinômio
for (double x=xi; x<=xf; x+=0.2) {
double aux = (int(10*x))/10.0;
cout << setw(6) << aux << " ";
double y = a*pow(x, 2) + b*x + c;
if (y<0 || y>5) {
cout << endl; // abcissa fora da escala
continue; // abrevia iteração
}
// plota abcissa em escala 10:1
for (int i=0, l=int(10*y)-1; i<l; i++) {
cout << " ";
}
cout << "+" << endl; // ponto da função
}
cout << " (X)" << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 47
Uso de continue
EXEMPLO _GRAFICO
20/04/2017 (C) 2017, PJANDL. 48
Resultados do
programa
PARTE III::
ESTRUTURAS DE DADOS
C++ 200
UM MINICURSO
20/04/2017 (C) 2017, PJANDL. 49
C++
::ESTRUTURAS DE DADOS
C++ oferece várias estruturas de dados.
 Derivadas
 Arranjo
 Função
 Ponteiro
 Referência
 Definíveis
 Enumeração
 Estrutura
 União
 Classe
20/04/2017 (C) 2017, PJANDL. 50
C++::ARRANJOS
Arranjos ou Arrays são:
conjuntos de elementos de um mesmo tipo;
organizados em posições consecutivas da
memória;
ocupando uma região de tamanho fixo
(capacidade máxima pré-definida);
seus elementos podem ser acessados individual
e aleatoriamente por meio de um índice
(primeira posição é zero).
Arranjos podem ser unidimensionais ou
multidimensionais,
Declaração (unidimensional):
<Tipo> <id>[<tamanho>];
Exemplos:
int a[10];
double f[1024];
float k[] = { 0.1, 2.3, 4.56, -78.9 };
20/04/2017 (C) 2017, PJANDL. 51
C++::ARRANJOS
20/04/2017 (C) 2017, PJANDL. 52
arranjo com
12 elementos
31
102
8
0
1
2
arranjo[ 0 ][ 0 ]
arranjo[ 2 ][ 0 ] arranjo[ 2 ][ 3 ]
arranjo[ 0 ][ 3 ]
arranjo[ 1 ][ 1 ]
713
-82
946
37
9
456
512
-28
91
0 1 2 3índices
arranjo com
5 elementos
13
-28
946
50
724
0
1
2
3
4
índices
conteúdos
arranjo[ 0 ]
arranjo[ 1 ]
arranjo[ 2 ]
arranjo[ 3 ]
arranjo[ 4 ]
elementos
individuais
unidimensional
bidimensional
EXEMPLO _ARRANJO
#include <iostream>
using namespace std;
const int MAX = 5;
int main() {
double a[MAX];
// lê arranjo
for (int i=0; i<MAX; i++) {
cout << "#" << i << "? ";
cin >> a[i];
}
// soma elementos do arranjo
double soma = 0;
for (int i=0; i<MAX; i++) {
soma = soma + a[i];
}
cout << "Soma = " << soma << endl;
return 0;
}
Cuidado!
C++ inicializa automaticamente apenas
arranjos (e variáveis) globais.
C++ não mantém o tamanho dos
arranjos, nem dispõe de função para tal
fim.
C++ não oferece qualquer mecanismo
de proteção ou restrição quanto ao uso
de índices inválidos para acesso aos
elementos do arranjo.
20/04/2017 (C) 2017, PJANDL. 53
Uso de array
unidimensional
EXEMPLO _MATRIZ
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
// declara e inicializa matriz
int matriz[3][4] = { { 31, 713, 37, 512 }, { 102, -82, 9, -28 },
{ 8, 946, 546, 91 } };
double res[3][4]; // declara matriz
cout << "Matriz dada:n";
for (int l=0; l<3; l++) {// exibe matriz organizada em linhas e colunas
cout << "[ ";
for (int c=0; c<4; c++) { cout << setw(6) << matriz[l][c] << " "; }
cout << "]n";
}
cout << "Normalizando Matriz...n";
double maior = matriz[0][0];
for (int l=0; l<3; l++) {// determina maior elemento da matriz
for (int c=0; c<4; c++) {
if (maior<matriz[l][c]) maior = matriz[l][c];
}
}
// normaliza matriz: maior=1 e outros proporcionais a maior
for (int l=0; l<3; l++) {
for (int c=0; c<4; c++) {
res[l][c] = matriz[l][c]/maior;
}
}
cout << "Matriz resultado:n";
// exibe matriz organizada em linhas e colunas
for (int l=0; l<3; l++) {
cout << "[ ";
for (int c=0; c<4; c++) {
cout << setw(10) << setprecision(3) << res[l][c] << " ";
}
cout << "]n";
}
return 0; // encerra programa
}
20/04/2017 (C) 2017, PJANDL. 54
Uso de arrays
bidimensional
C++::STRINGS
Uma string é uma sequência de
caracteres de comprimento arbitrário.
C++ compartilha com sua antecessora C
o uso de arrays de caracteres
terminados com nulo (caractere ‘0’ ou
0).
20/04/2017 (C) 2017, PJANDL. 55
Exemplos:
char nome[ ] = “Peter Jandl Jr.”;
char lang [ ] = { ‘C’, ‘+’, ‘+’, 0 };
char s[ ] = { ‘0’ };
C++::STRINGS
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char nome[20], linha[80]; // duas strings
// entrada de string com uso direto de cin
cout << "Qual o seu nome? ";
cin >> nome; // lê apenas 1a palavra
cin.ignore(80, 'n'); // ignora restante da entrada até 'ENTER'
cout << "Alo " << nome << "!n"
<< "Digite uma ou mais frases, '.' finaliza programa.n";
do { // entrada de string com uso de cin.getline
cin.getline(linha, 80); // lê tudo até 'ENTER'
cout << linha << " : " << strlen(linha) << endl;
} while (linha[0]!='.'); // encerra laço se 1o caractere='.'
cout << "Tchaun";
return 0; // encerra programa
}
20/04/2017 (C) 2017, PJANDL. 56
Exemplo _String
C++::ENUMERAÇÕES
Uma enumeração é uma construção da
linguagem que permite agrupar um
conjunto de elementos constantes
definidos pelo programador.
enum [nome] { <id1> [, <id2> [...] ] };
São mais convenientes que constantes
individuais quando o grupo de valores
enumerados constitui um conjunto (como
um tipo de dados).
A cada constante é associado um valor
inteiro a partir do zero.
Exemplos:
enum cor { Branco, Vermelho, Cinza };
enum escolaridade { Fundamental,
Medio, Superior, Especializacao,
Mestrado, Doutorado,
PosDoutorado };
enum zoom { z0=1, z1=2, z2=4 };
enum mes { janeiro=1, fevereiro,
marco, abril, maio, junho, julho,
agosto, setembro, outubro,
novembro, dezembro };
20/04/2017 (C) 2017, PJANDL. 57
EXEMPLO _ENUM
#include <iostream>
using namespace std;
enum zoom { z0=1, z1=2, z2=4 };
int main() {
enum { A, B, C }; // enum anônima
cout << A << " ... " << C << endl;
zoom zIni = z0; // uso de constante
zoom zMax = zoom(3); // coerção
cout << zIni << " ... " << zMax << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 58
Uso de
enumerações
C++::PONTEIROS
Ponteiros (pointers) são variáveis
especiais capazes de armazenar
endereços de memória, ou seja, seus
conteúdos se referem à localização de
outro objeto na memória (como uma
variável, arranjo, outro ponteiro etc.).
Ponteiros permitem o acesso e a
modificação das posições de memória
indicadas.
Proveem suporte para alocação
dinâmica de memória.
Declaração de ponteiro:
<Tipo> *<nome>;
Exemplos:
char *palavra; // ponteiro para caractere
int *p; // ponteiro para inteiro
long *cont; // ponteiro para long
void *qq; // ponteiro para void
double *total; // ponteiro para double
20/04/2017 (C) 2017, PJANDL. 59
C++::PONTEIROS
Operadores Específicos:
• Endereço de &
• Conteúdo de *
Exemplos:
int a = 33; // variável int
int *p1 = &a; // ponteiro para int
char c = 'A'; // variável char
char *p2 = &c; // ponteiro para char
int b = *p1; // var. b recebe conteúdo
// apontado por p1
// exibe o conteúdo apontado por p2
cout << *p2 << endl;
20/04/2017 (C) 2017, PJANDL. 60
C++::PONTEIROS
A obtenção do conteúdo de um
endereço de memória através do
operador '*' é conhecida como
'indireção' (indirection ou dereferencing)
e é uma operação fundamental para a
utilização efetiva dos ponteiros.
#include <iostream>
using namespace std;
int main() {
int a = 33; // variável inteira simples
char c = 'A'; // variável caractere simples
int* p1 = &a; // ponteiro para inteiro
char* p2 = &c; // ponteiro para caractere
// exibe informações sobre os ponteiros
cout << " Ponteiro p1: " << p1 << endl
<< "Conteudo do endereco p1: " << *p1 << endl
<< "Endereco do ponteiro p1: " << &p1 << endl;
cout << " Ponteiro p2: " << (int*)p2 << endl
<< "Conteudo do endereco p2: " << *p2 << endl
<< "Endereco do ponteiro p2: " << &p2 << endl;
return 0; // encerra o programa
}
20/04/2017 (C) 2017, PJANDL. 61
Uso de ponteiros e
seus operadores
Exemplo _Ponteiro
C++::PONTEIROS
Os operadores soma (‘+’), subtração (‘-’),
incremento (‘++’) e decremento (‘--’)
podem ser aplicados aos ponteiros para
modificar o local apontado.
Através do operador soma ('+') podemos
adicionar um valor inteiro a um ponteiro de modo
que ele seja “avançado” tal número de elementos
do tipo, passando a apontar uma localidade de
memória num endereço superior ao anterior.
Com o operador subtração (‘-') ocorre o inverso,
fazendo que o ponteiro seja “retrocedido” o
número indicado de elementos, apontando para
um endereço anterior.
20/04/2017 (C) 2017, PJANDL. 62
Aritmética de
ponteiros
C++::PONTEIROS
#include <iostream>
using namespace std;
int main() {
// ponteiros com endereços literais inválidos em outros sistemas!
char *pChar = (char *)0x0065FDF4;
cout << (int *)pChar << ": " << *pChar << endl;
pChar = pChar + 1;
cout << (int *)pChar << ": " << *pChar << endl;
pChar += 1;
cout << (int *)pChar << ": " << *pChar << endl;
pChar++;
cout << (int *)pChar << ": " << *pChar << endl;
long *pLong = (long *)0x0065FE00;
cout << pLong << ": " << *pLong << endl;
pLong = pLong - 1;
cout << pLong << ": " << *pLong << endl;
pLong -= 1;
cout << pLong << ": " << *pLong << endl;
pLong--;
cout << pLong << ": " << *pLong << endl;
return 0; // encerra o programa
}
Não pode ser empregado o operador '*'
em ponteiros do tipo void porque não se
sabe o tamanho dos dados apontados,
exigindo uma operação de type casting
para o tipo correto:
int k = 10; // variável inteira
void *p = &k; // ponteiro void recebe endereço
cout << *((int*)p) << endl;
// uso do ponteiro void para
// acessar conteúdo apontado
*((int*)p) = 33; // uso do ponteiro void para
// modificar conteúdo apontado
20/04/2017 (C) 2017, PJANDL. 63
Exemplo _Ponteiro2
C++::PONTEIROS
#include <iostream>
using namespace std;
const int MAX =10;
int main() {
int a[MAX];
cout << "Entrada de valoresn";
for (int i=0; i<MAX; i++) {
cout << "a[" << i << "] ?b"; cin >> a[i];
}
cout << "Exibicao do arranjon[ ";
for (int i=0; i<MAX; i++) { cout << a[i] << " "; }
cout << "]n";
cout << "Invertendo posicao do elementos...n";
for (int i=0,j=MAX-1; i<j; i++, j--) {
int tmp = *(a+i); // uso de aritmética de ponteiros
*(a+i) = *(a+j); // para acessar e modificar
*(a+j) = tmp; // elementos do arranjo
}
cout << "Exibicao do arranjo invertidon[ ";
for (int i=0; i<MAX; i++) { cout << *(a+i) << " "; }
cout << "]n";
return 0; // encerra o programa
}
20/04/2017 (C) 2017, PJANDL. 64
Equivalência do uso
de ponteiros e
arranjos
Exemplo _Ponteiro3
C++::ALOCAÇÃO DINÂMICA
Mecanismo que permite a agregação de
novas regiões de memória para uso do
programa durante sua execução.
C++ permite:
alocação dinâmica de memória por
meio do operador new.
liberação das regiões alocadas por
meio do operador delete.
Estes operadores são utilizados em
conjunto com os ponteiros.
Exemplos:
 int *pInt; // ponteiro para inteiro
 pInt = new int; // aloca memória p/ um int
 delete pInt; // libera região alocada
 double *pDouble;
// ponteiro para double
 pDouble = new double[1000];
// aloca mem p/1000 doubles
 delete[] pDouble;
// libera memória alocada
20/04/2017 (C) 2017, PJANDL. 65
EXEMPLO _ALOCDINAM
#include <iostream>
using namespace std;
int main() {
int max; // tamanho do arranjo dinamicamente alocado
cout << "Quantos elementos?n"; cin >> max;
// aloca arranjo dinamicamente
double *pDouble = new double[max];
if (pDouble==NULL) {
cout << "Nao ha memoria suficiente no sistema.n";
return 1; // encerra programa com erro
}
cout << "Entrada de valoresn";
for (int i=0; i<max; i++) {
cout << "valor[" << i << "] ?b"; cin >> pDouble[i];
}
double soma = 0; // variável para total dos valores
cout << "Exibicao do arranjon ";
for (int i=0; i<max; i++) {
cout << pDouble[i] << " ";
soma += pDouble[i]; // acumula valores dados
}
// exibe média dos valores
cout << "nMedia = " << soma/max << endl;
delete[] pDouble; // libera memória alocada
return 0; // encerra o programa
}
20/04/2017 (C) 2017, PJANDL. 66
C++::ALOCAÇÃO DINÂMICA
Ponteiros para Ponteiros
Um ponteiro pode conter o endereço de
qualquer objeto existente, até de um
outro ponteiro e este para outro, até
que dados sejam apontados, o que
constitui a indireção múltipla (multiple
indirection).
 int x = 17580; // variável int simples
 int *p1 = &x; // ponteiro de int
 int **p2 = &p1; // ponteiro de ponteiro de int
 int ***p3 = &p2; // 3ª indireção para int
Referências
Uma referência é como um ponteiro
implícito que funciona como um 'nome
alternativo' para uma entidade.
 double resultado; // variável comum
 double &ref = resultado; // referência
É obrigatória a inicialização das
referências com uma variável ou valor
constante, pois não podem ser alteradas
depois de inicializadas.
20/04/2017 (C) 2017, PJANDL. 67
C++::ESTRUTURAS
Uma estrutura (structure) é:
 um agrupamento de variáveis relacionadas,
 mas de tipos arbitrários,
 referenciadas por um mesmo nome.
Cada variável designada como
parte de uma estrutura é chamada
de campo ou membro.
Sintaxe:
struct <nomeEstrutura> {
<tipo1> <campo1>;
[<tipo2> <campo2>; [...] ]
} [var1 [, var2 [...]]];
Exemplo:
struct s_pessoa {
char nome[80]; // string com 80 caracteres
short ddd; // inteiro curto
long telefone; // inteiro longo
char email[80]; // string com 80 caracteres
};
20/04/2017 (C) 2017, PJANDL. 68
C++::ESTRUTURAS
Declaração:
 struct s_pessoa eu;
 s_pessoa você;
Inicialização na declaração:
 s_pessoa peter = { "Peter Jandl", 11,
987654321,
"prof.peter@fatec.sp.gov.br" };
Cópia:
 s_pessoa copia = peter;
Uso:
cout << "nome : " << eu.nome
<< "nfone : (" << eu.ddd << ")"
<< eu.telefone << "nemail: “
<< eu.email << endl;
strcpy(eu.nome, "Peter Jandl Jr.");
// nome é um campo string!
eu.telefone = 976543210;
// telefone é um campo inteiro
20/04/2017 (C) 2017, PJANDL. 69
EXEMPLO _STRUCT
#include <iostream>
#include <cstring>
using namespace std;
struct s_pessoa {
char nome[80]; // string com 80 caracteres
short ddd; // inteiro curto
long telefone; // inteiro longo
char email[80]; // string com 80 caracteres
};
int main() {
// declaração e inicialização de estrutura
struct s_pessoa eu = { "Peter", 11, 0, "jandl@live.com" };
// exibe campos
cout << "nome : " << eu.nome
<< "nfone : (" << eu.ddd << ")" << eu.telefone
<< "nemail: " << eu.email << endl;
// altera campos
strcpy(eu.nome, "Peter Jandl Jr."); // nome é um campo string!
eu.telefone = 38323374; // telefone é um campo inteiro
// exibe campos novamente
cout << "nome : " << eu.nome
<< "nfone : (" << eu.ddd << ")" << eu.telefone
<< "nemail: " << eu.email << endl;
// declara outra estrutura e efetua leitura de seus campos
struct s_pessoa voce;
cout << "Seu nome? "; cin.getline(voce.nome,80);
cout << " DDD? "; cin >> voce.ddd;
cout << "Telefone? "; cin >> voce.telefone;
cout << " E-mail? "; cin >> voce.email;
// exibe campos
cout << "nome : " << voce.nome
<< "nfone : (" << voce.ddd << ")" << voce.telefone
<< "nemail: " << voce.email << endl;
return 0; // encerra o programa
}
20/04/2017 (C) 2017, PJANDL. 70
Uso de struct e seus
campos
C++::ESTRUTURAS
Composição de Estruturas
struct s_data {
short ano;
short mes;
short dia;
};
struct s_compromisso {
// estrutura independente
struct s_data data;
char lembrete[80];
}
// declaração de variável
struct s_compromisso c;
// campos
c.data.ano
c.data.mes
c.data.dia
c.lembrete
Composição com Estrutura Anônima
struct s_compromisso {
// estrutura anônima
struct {
short ano;
short mes;
short dia;
};
char lembrete[80];
}
// declaração de variável
struct s_compromisso c;
// campos
c.ano
c.mes
c.dia
c.lembrete
20/04/2017 (C) 2017, PJANDL. 71
EXEMPLO
#include <iostream>
#include <cstring>
using namespace std;
// estruturas independentes aninhadas
struct s_hora {
short HH;
short MM;
};
struct s_compromisso {
struct s_hora hora;
char lembrete[80];
};
// estrutura anônima aninhada
struct s_compromisso2 {
struct {
short HH;
short MM;
};
char lembrete[80];
};
int main() {
// declara e inicializa estrutura e ponteiro para a mesma
struct s_compromisso c1 = { 10, 30, "Cliente 1" };
struct s_compromisso *p1 = &c1;
// exibe conteúdo dos campos da estrutura
cout << c1.hora.HH << ":" << c1.hora.MM << " "
<< c1.lembrete << endl;
cout << p1->hora.HH << ":" << p1->hora.MM << " "
<< p1->lembrete << endl;
// declara e inicializa estrutura e ponteiro para a mesma
struct s_compromisso2 c2;
c2.HH = c1.hora.HH;
c2.MM = p1->hora.MM;
strcpy(c2.lembrete, p1->lembrete);
struct s_compromisso2 *p2 = &c2;
// exibe conteúdo dos campos da estrutura
cout << c2.HH << ":" << c2.MM << " "
<< c2.lembrete << endl;
cout << p2->HH << ":" << p2->MM << " "
<< p2->lembrete << endl;
return 0; // encerra programa
}
20/04/2017 (C) 2017, PJANDL. 72
Uso de struct e seus campos
por meio de ponteiros
C++::UNIÕES
Uma união (union) é como uma estrutura
(struct), ou seja, organiza variáveis de
tipos diferentes sob um mesmo nome,
exceto pelo fato de que todas as
variáveis compartilham o mesmo espaço
em memória, não podendo ser utilizadas
simultaneamente
Declaração:
union <nomeUnião> {
<tipo1> <campo1>;
[<tipo2> <campo2>; [...] ]
} [var1 [, var2 [...]]];
Exemplo:
union u_variante {
short valor_s; // campo inteiro curto
long valor_l; // campo inteiro longo
double valor_d; // campo real
};
20/04/2017 (C) 2017, PJANDL. 73
C++::DEFINIÇÃO DE TIPOS
Para melhorar a legibilidade dos
programas é possível que novos tipos
sejam criados a partir de outros
existentes utilizando-se a palavra
reservada typedef com a sintaxe
abaixo:
typedef <tipoExistente> <nomeNovoTipo>;
Exemplos:
typedef int integer;
typedef int* pInt;
typedef double real;
typedef unsigned char byte;
typedef unsigned long DWORD;
20/04/2017 (C) 2017, PJANDL. 74
PARTE IV::
FUNÇÕES
C++ 200
UM MINICURSO
20/04/2017 (C) 2017, PJANDL. 75
C++::FUNÇÕES
Uma função é um segmento de
programa independente (subprograma),
ou seja, um bloco de diretivas agrupadas
ao qual se associa um nome (o
identificador de função).
Cada função tem uma finalidade
específica, realizada por meio de suas
diretivas.
Para executarmos uma função devemos
efetuar uma chamada à função (function
call) de qualquer ponto do programa.
Uma função:
 Pode ser chamada qualquer número de
vezes;
 Pode receber valores (argumentos) para
realizar suas tarefas de maneira
customizada;
 Pode retornar um valor como resultado de
sua execução;
 Pode acionar a si mesma (recursão).
Programas em C++ podem ser
organizados como um conjunto de
funções.
20/04/2017 (C) 2017, PJANDL. 76
C++::FUNÇÕES
Forma geral da definição:
tipoRetorno nome (listaParâmetros) corpoFunção
Onde:
 tipoRetorno especifica o tipo do valor
retornado pela função. O default é int;
qualquer outro pode ser escolhido; void indica
uma função sem valor de retorno.
 nome é o identificador da função, usado em
seu acionamento (chamada da função).
 listaParâmetros relaciona o tipo e nome dos
parâmetros opcionalmente recebidos pela
função.
 corpoFunção é o bloco de código associado.
Um trecho de código como segue:
int temp;
cout << "Digite um valor inteiro: ";
cin >> temp;
Pode ser convertido numa função como:
int leInteiro(char *msg) {
int temp;
cout << msg;
cin >> temp;
return temp;
}
20/04/2017 (C) 2017, PJANDL. 77
C++::FUNÇÕES
Ao invés de repetir-se código, o uso de
funções não apenas reduz a quantidade
de programa a ser escrito, mas melhora
sua abstração, facilita sua manutenção e
promove o reuso.
Observe que a definição da função
aparece no código antes de sua
utilização (no caso, antes do main).
#include <iostream>
using namespace std;
int LeInteiro(const char *msg) { // definição da função
int temp; // declaração var auxiliar
cout << msg; // exibe mensagem
cin >> temp; // lê valor
return temp; // retorna valor lido
}
int main() {
int valor1, valor2; // declaração de variáveis
// chamada da função e atribuição do valor retornado
valor1 = LeInteiro(“Valor1? ");
// chamada da função e atribuição do valor retornado
valor2 = LeInteiro(“Valor2? ");
// exibe valores lidos
cout << “Valor1:” << valor1 << endl
<< “Valor2:” << valor2 << endl;
return 0; // encerramento do programa
}
20/04/2017 (C) 2017, PJANDL. 78
Função que retorna
tipo primitivo
C++::RETORNO DE FUNÇÕES
Toda função deve retornar um único valor
como seu resultado.
Tal valor deve ser do tipo especificado
para retorno.
O valor de retorno deve ser indicado
diretamente através da diretiva return:
return expressão;
bool EPrimo(long numero) {
// laço que percorre as possibilidades de teste
for (int div=2; div<=numero/2; div++) {
if (numero%div==0) { // verifica se div é divisor
// encontrou divisor, número não é primo
return false;
}
}
// laço concluído, número dado é primo
return true; // retorno do resultado
}
20/04/2017 (C) 2017, PJANDL. 79
Função que retorna
tipo primitivo
C++::DECLARAÇÃO OU PROTOTIPAÇÃO
A declaração ou prototipação (function
prototype) é a especificação do nome
pretendido para uma função, juntamente
com seu tipo de retorno e a lista dos
tipos de seus argumentos.
A declaração não inclui o bloco de
código da função e é finalizada por um
ponto e vírgula (';').
Exemplos:
• int LeInteiro(const char*);
• bool EPrimo(long);
• double Soma(double, double);
• int Procura(const string, char);
• void Troca(double*, double*);
20/04/2017 (C) 2017, PJANDL. 80
EXEMPLO _FUNCAO2
20/04/2017 (C) 2017, PJANDL. 81
#include <iostream>
using namespace std;
// declaração das funções
bool EPrimo(long);
int LeInteiro(const char*);
// função principal
int main() {
// mensagem inicial
cout << "Verificacao de numero primon";
// declara var, chama função e atribui valor lido
int valor = LeInteiro("Valor inteiro?");
// exibe mensagem contendo resultado de 'EPrimo(long)'
cout << "Numero '" << valor << "' "
<< (EPrimo(valor) ? "e" : "nao e") << " primon";
return 0; // encerramento do programa
}
bool EPrimo(long numero) { // definição da função EPrimo
bool primo = true; // declara e inicia var auxiliar
// laço percorre as possibilidades de teste
for(int div=2; div<=numero/2; div++) {
if (numero%div==0) { // verifica se div é divisor
primo = false; // encontra divisor, número não é primo
break; // interrompe laço
}
} // não encontrou divisor, número é primo
return primo; // retorno do resultado
}
int LeInteiro(const char *msg) { // definição da função LeInteiro
int temp; // declaração var auxiliar
cout << msg; // exibe mensagem
cin >> temp; // lê valor
return temp; // retorna valor lido
}
Funções que retornam
tipos primitivos
EXEMPLO _FUNCAO3
#include <iostream>
using namespace std;
// declaração da função 'ObtemArranjo(int)'
int* ObtemArranjo(int);
// função principal
int main() {
int* arranjo; // ponteiro para arranjo de inteiros
const int TAM = 10; // constante para tamanho do arranjo
arranjo = ObtemArranjo(TAM); // lê arranjo de tamanho TAM
cout << "[ "; // exibe arranjo obtido
for (int i=0; i<TAM; i++) {
cout << arranjo[i] << " ";
}
cout << "]n";
delete[] arranjo; // memória alocada é liberada
return 0; // encerra programa
}
// definição da função 'ObtemArranjo(int)'
int* ObtemArranjo(int tamanho) {
int* tmp = new int[tamanho]; // aloca arranjo dinamicamente
for (int i=0; i<tamanho; i++) { // laço para leitura de valores
cout << "Valor[" << i << "] ?b";
cin >> tmp[i];
}
return tmp; // retorna arranjo
}
20/04/2017 (C) 2017, PJANDL. 82
Função que retorna
tipo ponteiro
C++::PASSAGEM DE PARÂMETROS
Passagem de parâmetros
por valor
Mecanismos mais simples de
transferência de argumentos.
O valor dos argumentos usados na
chamada é copiado para os parâmetros
de entrada da função.
Se tais parâmetros são alterados na
função, a modificação não afeta os
argumentos na chamada (passagem
unidirecional, sem efeito colateral).
Passagem de parâmetros
por referência
Mecanismos mais sofisticado de
transferência de argumentos.
O endereço dos argumentos usados na
chamada é copiado para os parâmetros
de entrada da função.
Se tais parâmetros são alterados na
função, a modificação afeta os
argumentos na chamada (passagem
bidirecional, com efeito colateral).
20/04/2017 (C) 2017, PJANDL. 83
Uso de const impede que
argumentos passados por referência
sejam alterados na função.
C++::ARGUMENTOS PARA MAIN()
A linguagem C++ admite duas formas
para a função principal:
// função principal sem argumentos
int main() { ... }
// função principal com argumentos
int main(int argc, char *argv[]) { ... }
Na segunda forma, os argumentos são
providos pelo sistema operacional em uso
e correspondem aos argumentos da linha
de comando (dos consoles).
20/04/2017 (C) 2017, PJANDL. 84
EXEMPLO _MAIN
#include <iostream>
using namespace std;
// função principal com recebimento de argumentos
int main (int argc, char *argv[]) {
// exibe mensagem com número de argumentos recebidos
cout << "Argumentos recebidos: " << argc << endl;
// exibe todos os argumentos recebidos
for (int i=0; i<=argc; i++) {
cout << i << ": " << argv[i] << endl;
}
return 0; // encerra o programa
}
20/04/2017 (C) 2017, PJANDL. 85
C++::ARGUMENTOS DEFAULT
Construção conveniente da linguagem
C++ que possibilita definir argumentos
default para funções, isto é, definir
funções onde um ou mais de seus
parâmetros tenham valores pré-definidos
em sua declaração.
Quando um argumento é omitido na
chamada da função, é automaticamente
usado seu valor default.
Isso exige que os argumentos default
sejam os últimos das listas de parâmetros
das funções.
#include <iostream>
using namespace std;
// declaração da função 'Inc(double&, double)'
double Inc (double&, double = 1);
int main() { // função principal
double valor = 5;
cout << "Valor Inicial: " << valor << endl;
Inc(valor, 2.4);
cout << "Valor+2.4: " << valor << endl;
cout << "Valor+1: " << Inc(valor) << endl;
return 0; // encerra programa
}
// definição da função 'Inc(double&, double)'
double Inc (double &valor, double incremento) {
valor += incremento; // adiciona incremento ao valor
return valor; // retorna valor
}
20/04/2017 (C) 2017, PJANDL. 86
Função com passagem de
parâmetro por referência e
argumento default
C++::SOBRECARGA DE FUNÇÕES
É a possibilidade de existirem várias
funções com o mesmo nome dentro de um
mesmo espaço declarativo (function
overload).
Assim, em um mesmo escopo, podem
existir funções homônimas desde que
possuam diferentes assinaturas
(signatures).
A assinatura de uma função é a lista dos
tipos de seus parâmetros formais na
ordem em que foram declarados.
Exemplo:
double Inc(double&);
double Inc(double&,double);
double Inc(double*,double);
20/04/2017 (C) 2017, PJANDL. 87
EXEMPLO _SOBRECARGA
#include <iostream>
using namespace std;
double Inc (double&);
double Inc (double&, double);
double Inc (double*, double);
int main() {
double x = 0;
double y = 3;
double *w = &y;
cout << "x inicial = " << x << endl;
Inc(x);
cout << "x + 1 = " << x << endl;
cout << "y inicial = " << y << endl;
cout << "y + 2.8 = " << Inc(y, 2.8) << endl;
cout << "y + 1.2 = " << Inc(&y, 1.2) << endl;
cout << "y = " << y << endl;
Inc(w, 0.5);
cout << "y + 0.5 (indireto) = " << y << endl;
cout << "x + Inc(y, 0.7) = " << (x + Inc(y, 0.7)) << endl;
return 0;
}
double Inc (double &valor) {
valor += 1;
return valor;
}
double Inc (double &valor, double quant) {
valor += quant;
return valor;
}
double Inc (double *valor, double quant) {
*valor = *valor + quant;
return *valor;
}
20/04/2017 (C) 2017, PJANDL. 88
Estas duas versões da função
poderiam ser substituídas por
uma única dotada de
argumento default
PARTE V::
ORIENTAÇÃO A OBJETOS BÁSICA
C++ 200
UM MINICURSO
20/04/2017 (C) 2017, PJANDL. 89
ORIENTAÇÃO A OBJETOS
Sobre a ideia de objeto:
"No sentido mais simples, um objeto é
uma coisa ou uma entidade do mundo
real." (Jamsa & Klander, 1999)
Sobre a orientação a objetos:
"...uma forma particular de organizar o
desenvolvimento de software como uma
coleção de objetos que incorporam tanto
uma estrutura de dados como
comportamentos." (Rumbaugh, 1991)
20/04/2017 (C) 2017, PJANDL. 90
ORIENTAÇÃO A OBJETOS::CARACTERÍSTICAS
 Classificação
Característica que permite a criação de categorias de objetos (as classes) para facilitar a
compreensão do mundo e dos problemas.
 Generalização
Mecanismo que possibilita o compartilhamento de características entre classes, evitando sua
repetição.
 Encapsulamento
Mecanismo que determina quais elementos de uma classe serão visíveis, permitindo proteger
ou restringir o acesso a outros elementos.
20/04/2017 (C) 2017, PJANDL. 91
C++::CLASSES
Uma classe (class) é um novo tipo de
dados que pode ser definido pelo
programador para descrever uma
entidade real ou abstrata.
As classes representam os conceitos
fundamentais da aplicação em termos
da realidade 'modelada‘ pelo
programador.
20/04/2017 (C) 2017, PJANDL. 92
Enquanto uma classe é um modelo, as
ocorrências de uma classe são suas
instâncias.
C++::CLASSES
Classes em C++ possuem a seguinte
estrutura:
class <NomeClasse> {
[membros]
[EspecificadorDeAcesso:
membros]
[...]
} [ListaDeObjetos];
Os membros de uma classe podem ser
basicamente de duas naturezas:
 variáveis-membro ou campos da classe são as
declarações de variáveis que pertencem à classe
e representam seus atributos (características); e
 funções-membro ou métodos da classe são as
declarações e definições de funções associadas à
classe e representam suas operações
(comportamentos).
Os especificadores de acesso (access
specifiers) determinam a visibilidade externa
dos membros da classe aos quais se aplicam,
indicando como podem ser utilizados.
20/04/2017 (C) 2017, PJANDL. 93
C++::CAMPOS
Uma classe pode possuir um ou mais
atributos, os quais podem ser
representados por seus campos ou
variáveis-membro.
As variáveis-membro podem ser de
qualquer tipo pré-definido pela
linguagem ou definido pelo
programador, ou seja, tipos primitivos,
arrays, estruturas, uniões ou objetos de
outras classes.
Campos que não possuem restrição
podem ser declarados com acesso
público (public).
Nas situações ondem existem restrições
aos valores possíveis de um campo,
recomenda-se sua declaração com
acesso protegido (protected) ou privado
(private).
20/04/2017 (C) 2017, PJANDL. 94
EXEMPLO _INTEIRO
// Inteiro.h
class Inteiro { // denom. classe
public: // especif. acesso
int valor; // variável-membro
};
#include <iostream>
#include "Inteiro.h"
using namespace std;
int main() {
Inteiro i1, i2; // declaração de objetos Inteiro
i1.valor = 5;
cout << "i1.valor: " << i1.valor << endl;
cout << "Digite um valor inteiro: "; cin >> i2.valor;
cout << "i2.valor: " << i2.valor << endl;
cout << "i2 " << (i2.valor>i1.valor? "maior" : "menor ou igual")
<< " que i2" << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 95
Classe simples
contendo apenas
atributos públicos
Instanciação implícita dos
objetos da classe indicada
Campo público
apropriado, pois
não há restrição de
valores
Observe o uso do seletor ‘.’
para acesso aos campos dos
objetos
EXEMPLO _CAIXA
// Caixa.cpp
class Caixa {
public:
// campos públicos
// dimensões da caixa
double altura, largura, profundidade;
// informações para empilhamento
double peso;
int empilhamento;
};
#include <iostream>
#include "Caixa.cpp"
using namespace std;
void LeCaixa(Caixa&); // declaração de função
int main() {
Caixa cx; // declaração de objeto Caixa
LeCaixa(cx);
cout << "Dim (LARG x ALT x PROF): " << cx.largura << " x "
<< cx.altura << " x " << cx.profundidade << "nPeso: "
<< cx.peso << "nEmpilhamento: " << cx.empilhamento << endl;
return 0;
}
void LeCaixa(Caixa &cx) { // definição de função
cout << "Digite as dimensoes da caixa (LARG ALT PROF): ";
cin >> cx.largura >> cx.altura >> cx.profundidade;
cout << "Digite o peso da caixa: "; cin >> cx.peso;
cout << "Digite o empilhamento maximo da caixa: ";
cin >> cx.empilhamento;
}
20/04/2017 (C) 2017, PJANDL. 96
Classe simples contendo
apenas atributos públicos
Observe o uso do seletor ‘.’
para acesso aos campos dos
objetos
C++::MÉTODOS
Uma classe também pode possuir uma
ou mais operações, as quais podem ser
definidas por seus métodos ou funções-
membro.
As funções-membro podem tomar
qualquer número e tipo de parâmetros,
retornar qualquer tipo de resultados,
afetando (situação mais usual) ou não o
estado do objeto.
Métodos que permitem a utilização do
objeto em geral são declarados com
acesso público (public).
Métodos destinados a subdivisão interna
das responsabilidades do objeto, ou
aqueles cujo uso possui restrições que o
usuário da classe não necessita conhecer,
devem ser declarados com acesso
protegido (protected) ou privado
(private).
20/04/2017 (C) 2017, PJANDL. 97
É comum que métodos públicos
provejam acesso a campos privados
(operações de acesso e mutação)
EXEMPLO _CAIXA
// Caixa-cpp
class Caixa {
public:
// campos públicos
// dimensões da caixa
double altura, largura, profundidade;
// informações para empilhamento
double peso;
int empilhamento;
// declaração de método
double volume();
};
double Caixa::volume() { // definição do método
return altura*largura*profundidade;
}
#include <iostream>
#include "Caixa.cpp"
using namespace std;
void LeCaixa(Caixa&); // declaração de função
int main() {
Caixa cx; // declaração de objeto Caixa
LeCaixa(cx);
cout << "Dim (LARG x ALT x PROF): " << cx.largura << " x "
<< cx.altura << " x " << cx.profundidade << "nPeso: "
<< cx.peso << "nEmpilhamento: " << cx.empilhamento << endl;
cout << “Volume: “ << cx.volume() << endl;
return 0;
}
void LeCaixa(Caixa &cx) { // definição de função
cout << "Digite as dimensoes da caixa (LARG ALT PROF): ";
cin >> cx.largura >> cx.altura >> cx.profundidade;
cout << "Digite o peso da caixa: "; cin >> cx.peso;
cout << "Digite o empilhamento maximo da caixa: ";
cin >> cx.empilhamento;
}
20/04/2017 (C) 2017, PJANDL. 98
Classe simples contendo atributos e
operações públicos
Observe o uso do seletor ‘.’
para acesso à operação do
objeto
C++::FUNÇÕES INLINE
// Caixa-cpp
class Caixa {
public:
// campos públicos
// dimensões da caixa
double altura, largura, profundidade;
// informações para empilhamento
double peso;
int empilhamento;
// declaração implícita de método inline
double volume() {
return altura*largura*profundidade;
}
};
Funções podem ser declaradas inline. Se uma
função é assim declarada, o compilador substitui
cada chamada existente da função por uma
cópia de seu código. Com isso o código
produzido torna-se mais rápido, apesar de maior.
inline int Max(int x, int y) {
return (x > y)? x : y;
}
Funções-membro torna-se implicitamente inline se
definidas dentro da declaração da classe.
O uso do modificador inline pode ser aplicado à
funções comuns ou funções-membro declaradas
externamente.
20/04/2017 (C) 2017, PJANDL. 99
C++::ACESSIBILIDADE
A acessibilidade dos membros de uma
classe, também conhecida como
encapsulamento ou ocultamento de
dados (data hiding), é a forma com que
tais elementos podem ser vistos e
utilizados externamente, ou seja, pelas
instâncias da classe e por outras classes.
O encapsulamento auxilia na separação
do projeto (design) da implementação
(coding), proporcionando facilidades de
modificação e padronização do código
Em C++ a acessibilidade é definida
pelos especificadores de acesso:
 public
 protected
 private
20/04/2017 (C) 2017, PJANDL. 100
EXEMPLO _CIRCUNFERENCIA
// Circunferencia.h
#include <cmath>
class Circunferencia {
private:
double raio;
public:
void setRaio(double); // mutator
double getRaio(); // accessor
double area();
double perimetro();
};
void Circunferencia::setRaio(double r) {
if (r >= 0) { raio = r; }
}
double Circunferencia::getRaio() { return raio; }
double Circunferencia::area() { return M_PI * pow(raio, 2); }
double Circunferencia::perimetro() { return 2 * M_PI * raio; }
#include <iostream>
#include "Circunferencia.h"
using namespace std;
int main() {
Circunferencia c1;
double raio;
cout << "Raio? "; cin >> raio;
c1.setRaio(raio);
cout << "Circunferencianraio: " << c1.getRaio()
<< "narea: " << c1.area() << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 101
Classe atributo privado e
operações de acesso
(accessor e mutator)
C++::CONSTRUTORES
Os objetos das classes também devem
ser inicializados de modo que se tornem
consistentes e que seja evitado o retorno
de valores não esperados.
Para a criação de objetos em estados
consistentes, podem ser declarados os
construtores (constructors), métodos
especiais acionados apenas na criação
dos objetos das próprias classes, que
preparam os objetos para uso, isto é,
inicializam apropriadamente seus
campos.
// Circunferencia.h
#include <cmath>
class Circunferencia {
private:
double raio;
public:
void setRaio(double);
double getRaio();
double area();
double perimetro();
Circunferencia(); // construtor default
};
Circunferencia::Circunferencia() { raio = 0; }
void Circunferencia::setRaio(double r) {
if (r >= 0) { raio = r; }
}
double Circunferencia::getRaio() { return raio; }
double Circunferencia::area() { return M_PI * pow(raio, 2); }
double Circunferencia::perimetro() { return 2 * M_PI * raio; }
20/04/2017 (C) 2017, PJANDL. 102
Construtores sempre têm o
nome da classe e não
possuem valor de retorno
C++::SOBRECARGA DE MÉTODOS E CONSTRUTORES
Métodos e construtores podem ser
sobrecarregados, tal como funções.
A sobrecarga é possível sempre que a
assinatura da operação é diferente.
É um mecanismo natural, pois como
veremos, os compiladores geram, como
padrão, dois construtores: o default e o
cópia.
class Caixa {
public: // campos públicos p/ info. da caixa
double altura, largura, profundidade;
double peso;
int empilhamento;
// declaração de métodos
double volume() { return altura*largura*profundidade; }
void ajustaMedidas(double, double, double, double, int);
void ajustaMedidas(double, double, double);
void ajustaMedidas(double, int);
// declaração de construtores
Caixa() { ajustaMedidas(0, 0, 0, 0, 0); }
Caixa(double, double, double, double, int);
Caixa(double, double, double);
Caixa(double, int);
Caixa(Caixa &c);
};
20/04/2017 (C) 2017, PJANDL. 103
C++::CONSTRUTORES
Construtores sem parâmetros são
denominados construtores-default, pois
são automaticamente acionados na
declaração de objetos do tipo:
 Circunferencia c1, c2;
Construtores parametrizados podem ser
acionados por meio da passagem
adequada de parâmetros na
declaração dos objetos:
 Circunferencia c3(2.5), c4(10);
// Circunferencia.h
#include <cmath>
class Circunferencia {
private:
double raio;
public:
void setRaio(double);
:
// construtores
Circunferencia(); // default
Circunferencia(double); // parametrizado
};
Circunferencia::Circunferencia() { raio = 0; }
Circunferencia::Circunferencia(double r) {
setRaio(r);
}
void Circunferencia::setRaio(double r) {
if (r >= 0) { raio = r; }
}
:
20/04/2017 (C) 2017, PJANDL. 104
Os construtores default são
supridos pelo compilador
quando outros não são
especificados
EXEMPLO _PONTO
class Ponto {
public:
float x, y; // coord. do ponto
Ponto(float=0, float=0); // val. default p/ args
void translacao(float, float);
};
// construtor parametrizado
Ponto::Ponto(float x, float y) {
translacao(x, y); // uso de método da classe
}
// ajusta nova coordenada
void Ponto::translacao(float x, float y) {
Ponto::x = x; // op. escopo diferencia parâmetro
Ponto::y = y;
}
#include <iostream>
#include "Ponto.h"
using namespace std;
int main() {
Ponto p1; // declara objeto s/ args. (default)
cout << "p1(" << p1.x << "," << p1.y << ")n";
p1.translacao(-5,10);// ajusta coordenadas
cout << "p1(" << p1.x << "," << p1.y << ")n";
Ponto p2(5); // declara objeto c/ 1 arg. (x)
cout << "p2(" << p2.x << "," << p2.y << ")n";
Ponto p3(100, 50); // declara objeto / 2 args. (x e y)
cout << "p3(" << p3.x << "," << p3.y << ")n";
return 0; // encerra programa
}
20/04/2017 (C) 2017, PJANDL. 105
Os construtores default com valores default têm
comportamento dual: default e parametrizado
C++::CONSTRUTORES CÓPIA
Classes declaradas sem construtores explícitos fazem que compiladores adicionem
dois construtores automaticamente:
 Construtor default (sem parâmetros) e
 Construtor cópia.
O construtor default representa o mecanismo natural de inicialização de objetos,
enquanto o construtor cópia é responsável por:
1. realizar a inicialização de objetos a partir de outros objetos do mesmo tipo já existentes; e
2. permitir a passagem de objetos por valor para funções (ou métodos).
Exemplo (para classe Ponto):
Ponto::Ponto(const Ponto &p) { // copia atributos do
x = p.x; y = p.y; // objeto recebido para o novo
}
20/04/2017 (C) 2017, PJANDL. 106
EXEMPLO _PONTO
#include <cmath>
class Ponto {
public:
float x, y; // coord. do ponto
Ponto(float = 0, float = 0); // constr default
Ponto(const Ponto&); // construtor cópia
void translacao(float, float);
static float distancia(const Ponto &p1, const Ponto &p2);
};
// construtor parametrizado
Ponto::Ponto(float x, float y) {
translacao(x, y); // uso de método da classe
}
// construtor cópia
Ponto::Ponto(const Ponto &p) {
x = p.x;
y = p.y;
}
// ajusta nova coordenada
void Ponto::translacao(float x, float y) {
Ponto::x = x; // op. escopo diferencia parâmetro
Ponto::y = y;
}
// calcula distância entre pontos
float Ponto::distancia(const Ponto &p1, const Ponto &p2) {
return sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
}
20/04/2017 (C) 2017, PJANDL. 107
Os construtores cópia
precisam duplicar
adequadamente o objeto
Métodos estáticos
pertencem à classe e não
devem afetar instâncias
C++::MEMBROS ESTÁTICOS
Membros estáticos, isto é, declarados
como static, são elementos especiais de
uma classe que não estão associados as
suas instâncias e sim a própria classe.
Variáveis-membro estáticas existem
apenas na classe, e não em suas
instâncias, sendo compartilhadas por
todos objetos existentes.
Funções-membro estáticas, são
compartilhados entre as instâncias como
métodos comuns, mas utilizam
exclusivamente variáveis-membro
estáticas, ou seja, se aplicam ao
contexto da classe.
ImagemExecutável
Constantes
Código
Heap
Pilha
20/04/2017 (C) 2017, PJANDL. 108
EXEMPLO _ESTATICA
#include <cstdlib>
#include <iostream>
using namespace std;
class Estatica {
static double fator; // decl. var-membro estática
public:
static double resultado; // decl. var-membro estática
static double cm2pol(double); // decl. func-membro estática
};
double Estatica::fator = 2.54; // define var-membro estática
double Estatica::resultado = 0; // define var-membro estática
double Estatica::cm2pol(double cm) { // define método estático
resultado = cm/fator;
return resultado;
}
int main(int argc, char* argv[]) {
if (argc>1) {
cout << "cm = " << argv[1] << endl;
// utiliza método e atributo estáticos
cout << "pol = " << Estatica::cm2pol(atof(argv[1])) << endl;
cout << "ultimo resultado = " << Estatica::resultado << endl;
} else {
cout << "Uso: main <valor em cm>n";
}
return 0;
}
20/04/2017 (C) 2017, PJANDL. 109
C++::CONSTRUTORES EXPLÍCITOS
Considere a classe abaixo:
class Inteiro {
public:
int valor;
// construtor default inline com valor
Inteiro(int v=0) { valor = v; }
};
Ela permite instanciar objetos com:
Inteiro i1; i2(4);
Inteiro i3 = 44; // uso implícito de construtor
// transforma literal em objeto
O uso implícito de construtor é possível
quando não existe confusão possível
entre os construtores existentes, sendo
convertido para:
Inteiro i3(44);
Se desejado, o uso implícito de
construtores pode ser suprimido com uso
da palavra reservada explicit:
explicit Inteiro(int v=0) { valor = v; }
Isso evita que atribuições sejam
confundidas com a criação de objetos.
20/04/2017 (C) 2017, PJANDL. 110
C++::DESTRUTORES
Os construtores são operações especiais
que efetuam a inicialização dos objetos.
Por outro lado, existem os destrutores
(destructors), operações especiais que
atuam na remoção dos objetos,
permitindo que recursos do sistema
tomados na criação sejam devolvidos.
Os destrutores devem ser declarados
sempre que houver manipulação direta
de recursos de memória ou outros, que o
compilador não tem condição de
detectar e desfazer.
Considerando a existência dos
construtores e destrutores, percebemos
que os objetos possuem um ciclo de vida
associado ao escopo onde são
declarados.
Os destrutores são acionados quando o
escopo onde os objetos foram
declarados é finalizado.
20/04/2017 (C) 2017, PJANDL. 111
EXEMPLO _DINAMICA
#include <iostream>
using namespace std;
class Dinamica {
int* valor; // ponteiro para inteiro
public:
Dinamica(int=0); // construtor parametrizado
~Dinamica(); // destrutor
void ajustaValor(int); // ajusta valor do atributo
int obtemValor(); // obtém valor do atributo
};
Dinamica::Dinamica(int valor) { // construtor parametrizado
cout << "Construtorn"; // exibe mensagem
Dinamica::valor = new int; // aloca memória dinamicamente
*Dinamica::valor = valor; // armazena valor na memória
}
Dinamica::~Dinamica() { // destrutor
cout << "Destrutorn"; // exibe mensagem
delete valor; // libera região de memória alocada
}
void Dinamica::ajustaValor(int v) { *valor = v; }
int Dinamica::obtemValor() { return *valor; }
int main() {
cout << "inicio main()n"; // exibe mensagem
Dinamica obj1(10); // declara objeto
cout << obj1.obtemValor() << endl; // exibe valor do objeto
obj1.ajustaValor(20); // modifica valor do objeto
cout << obj1.obtemValor() << endl; // exibe valor do objeto
cout << "fim main()n"; // exibe mensagem
return 0; // encerra programa
}
20/04/2017 (C) 2017, PJANDL. 112
A execução deste programa
ilustra o ciclo de vida dos objetos
C++::THIS
A palavra reservada this representa o
endereço do próprio objeto na memória,
ou seja, é um ponteiro cujo valor é
diferente para cada objeto criado.
O ponteiro this é uma auto-referência
(self reference).
Em toda utilização de campo ou uso de
função-membro, implicitamente ocorre o
uso de this (exceto para membros
estáticos).
O uso de this é limitado, pois em geral
não é necessário exceto quando:
 Deseja-se distinguir entre uma variável local e
um campo da classe com a mesma designação
(tal como feito pelo operador de resolução de
escopo ::); ou
 Quando se deseja acesso ao objeto que
acionou um método específico; ou
 Quando é necessário obter ou retornar um
ponteiro (this) ou referência (*this) para o
próprio objeto, útil na sobrecarga de
operadores.
20/04/2017 (C) 2017, PJANDL. 113
EXEMPLO _INTERVALO
class Intervalo {
double minimo;
double maximo;
public:
Intervalo(double min, double max) {
minimo = min;
maximo = max;
}
double valorMinimo() const {
return minimo;
}
double valorMaximo() const {
return maximo;
}
bool pertence(double v) const {
return v >= valorMinimo() && v <= valorMaximo();
}
};
this->minimo = min;
this->maximo = max;
return this->minimo;
return this->maximo;
return v >= this->valorMinimo() && v <= this->valorMaximo();
20/04/2017 (C) 2017, PJANDL. 114
Uso explícito de thisUso implícito de this
PARTE VI::
ORIENTAÇÃO A OBJETOS INTERMEDIÁRIA
C++ 200
UM MINICURSO
20/04/2017 (C) 2017, PJANDL. 115
C++::FUNÇÕES AMIGAS
Uma função não-membro de uma classe
pode receber o status de amiga (friend), o
que possibilita seu acesso aos membros
protegidos e privados, além dos públicos
cujo acesso é padrão.
Embora tal ação viole o encapsulamento
pretendido pela classe, é alternativa viável
na sobrecarga de operadores, além de
facilitar a criação de funções destinadas a
entrada/saída.
Seu uso deve ser feito com cautela!
class NomeClasse {
// membros privados e protegidos
public:
friend <tipo> funcao([paramList]);
:
};
// implementação da função-amiga
// que *não* é membro da classe!
<tipo> funcao([paramList]) {
}
20/04/2017 (C) 2017, PJANDL. 116
EXEMPLO _INTERVALO
class Intervalo {
double minimo;
double maximo;
public:
Intervalo(double min, double max) {
minimo = min; maximo = max;
}
double valorMinimo() const { return minimo; }
double valorMaximo() const { return maximo; }
bool pertence(double v) const {
return v>=minimo && v<=maximo;
}
friend bool contem(const Intervalo &, const Intervalo &);
};
bool contem(const Intervalo &a, const Intervalo &b) {
return b.minimo>=a.minimo && b.maximo<=a.maximo;
}
#include <iostream>
#include "intervalo.h"
using namespace std;
int main() {
Intervalo A(-5, 12), B(7, 10), C(5, 15);
cout << "A" << (contem(A, B) ? " " : " nao ")
<< "contem Bn";
cout << "A" << (contem(A, C) ? " " : " nao ")
<< "contem Cn";
cout << "C" << (contem(C, B) ? " " : " nao ")
<< "contem Bn";
return 0;
}
20/04/2017 (C) 2017, PJANDL. 117
Uso de função amiga
C++::CLASSES AMIGAS
Também é possível a existência de
classes amigas, que, como para as
funções amigas, também terão acesso a
membros privados e protegidos em
função da relação de amizade
estabelecida.
Novamente existe a situação de cautela
exigida pela violação conceitual do
encapsulamento.
// Colecao.h
#ifndef _COLECAO_H_
#define _COLECAO_H_
class Iterator; // definição da classe Iterator
class Colecao { // declaração da classe Colecao
int *v, tam, prox;
public:
Colecao(int=10); // construtor
~Colecao(); // destrutor
bool adiciona(int); // adiciona um elemento
int tamanho() const; // determina tamanho da coleção
int le(int) const; // obtém um elemento da coleção
void limpar(); // limpa coleção
friend class Iterator; // especifica classe amiga
};
class Iterator { // declaração da classe Iterator
int *v, tam, prox;
public:
Iterator(const Colecao&); // construtor
bool existeProximo() const; // verifica se existem mais elementos
int proximo(); // retorna próximo elemento
};
#endif
20/04/2017 (C) 2017, PJANDL. 118
Este exemplo também mostra a correta
organização do programa em múltiplos arquivos
de cabeçalho (header) e código-fonte (source).
EXEMPLO _COLECAO
// Colecao.cpp
#include "Colecao.h"
Colecao::Colecao(int t) {
tam = t; v = new int[tam]; prox = 0;
}
Colecao::~Colecao() { delete[] v; }
bool Colecao::adiciona(int valor) {
if (prox<tam) {
v[prox++] = valor; return true;
}
return false;
}
int Colecao::tamanho() const { return tam; };
int Colecao::le(int pos) const { return v[pos]; };
void Colecao::limpar() { prox=0; }
Iterator::Iterator(const Colecao &c) { v = c.v; tam = c.prox; prox = 0; }
bool Iterator::existeProximo() const { return prox<tam; }
int Iterator::proximo() {
if (prox<tam) return v[prox++]; return 0;
}
#include <iostream>
#include "Colecao.h"
using namespace std;
void listaColecao(const Colecao &c) {
Iterator it(c); // cria Iterator para Colecao
// lista elementos da Colecao através do Iterator
cout << "Colecao [ ";
while(it.existeProximo()) cout << it.proximo() << " ";
cout << "]n";
}
int main() {
Colecao c; // cria Colecao e adiciona elementos
for (int i=0; i<c.tamanho(); i++) c.adiciona(i);
listaColecao(c); // lista Colecao
c.limpar(); // limpa Colecao
listaColecao(c); // lista Colecao
return 0;
}
20/04/2017 (C) 2017, PJANDL. 119
C++::SOBRECARGA DE OPERADORES
Operadores disponíveis em C++
permitem realizar operações sobre tipos
de dados pré-definidos.
C++ permite redefinir a função de
muitos de seus operadores,
possibilitando seu uso para outros tipos
de dados, ou seja, a sobrecarga de
operadores (operator overload).
Sintaxe:
<Tipo> operator <sinal> (<parâmetros>);
Isto permite a construção de uma sintaxe
mais rica para os novos tipos definidos
para o programador.
Os operadores sobrecarregáveis são:
20/04/2017 (C) 2017, PJANDL. 120
+ - * / % ++ -- < <= >
>= == != && || ! & | ~ ^
>> << += -= *= /= %= &= |= ^=
>>= <<= , ( ) [ ] = -> ->* new delete
EXEMPLO _PONTO
#include <iostream>
using namespace std;
class Ponto {
public:
float x, y;
Ponto(float xi=0, float yi=0) {
x = xi; y = yi;
}
Ponto operator+(Ponto p) { // oper. sobrecarregado
Ponto tmp; // declara objeto aux
tmp.x = x + p.x; // soma x obj + param
tmp.y = y + p.y; // soma y obj + param
return tmp; // retorna objeto aux
}
};
int main() {
Ponto p1, p2; // declara objetos Ponto
cout << "Digite uma coordenada (x,y): ";
cin >> p1.x >> p1.y; // lê coord de ponto 1
cout << "Digite outra coordenada (x,y): ";
cin >> p2.x >> p2.y; // lê coord de ponto 2
// soma coordenadas
Ponto p3 = p1 + p2;
// exibe resultado e encerra programa
cout << "Coordenada final: (" << p3.x << ", “
<< p3.y << ")n";
return 0;
}
20/04/2017 (C) 2017, PJANDL. 121
Uso de sobrecarga de
operador
C++::SOBRECARGA DE OPERADORES
Sobrecarga de operadores possibilita
simplificação do programa:
Ponto p3 = p1 + p2;
O uso da sobrecarga é equivalente à:
Ponto p3 = p1.operator+(p2);
Uma classe pode possui várias operações
sobrecarregadas:
Ponto operator-(Ponto p) {
Ponto tmp;
tmp.x = x - p.x;
tmp.y = y - p.y;
return tmp;
}
Quando corretamente implementada, a
sobrecarga permite o encadeamento de
operações:
Ponto p = p1 + p2 + p3 + p4;
Que equivale à:
Ponto p =
p1.operator+(p2.operator+(p3.operator+(p4)));
20/04/2017 (C) 2017, PJANDL. 122
EXEMPLO _FRACAO
// Fracao.h
#ifndef _FRACAO_H_
#define _FRACAO_H_
#include <iostream>
using namespace std;
class Fracao {
int Numerador, Denominador;
void reduzir();
public:
Fracao (const int=1, const int=1);
Fracao (const Fracao &);
int numerador() const;
int denominador() const;
Fracao operator+ (const Fracao &);
Fracao operator- (const Fracao &);
Fracao operator+ (const int);
Fracao operator- (const int);
friend istream& operator>> (istream &, Fracao &);
friend ostream& operator<< (ostream &, const Fracao &);
};
#endif
// Fracao.cpp
#include "Fracao.h"
Fracao::Fracao(const int n, const int d) {
Numerador = n; Denominador = d!=0 ? d : 1;
reduzir();
}
Fracao::Fracao(const Fracao &f) {
Numerador = f.Numerador; Denominador = f.Denominador;
}
int Fracao::numerador() const { return Numerador; }
int Fracao::denominador() const { return Denominador; }
Fracao Fracao::operator+ (const Fracao &f) {
Fracao tmp;
tmp.Numerador = Numerador*f.Denominador + f.Numerador*Denominador;
tmp.Denominador = Denominador * f.Denominador; tmp.reduzir();
return tmp;
}
Fracao Fracao::operator- (const Fracao &f) {
Fracao tmp;
tmp.Numerador = Numerador*f.Denominador - f.Numerador*Denominador;
tmp.Denominador = Denominador * f.Denominador; tmp.reduzir();
return tmp;
}
20/04/2017 (C) 2017, PJANDL. 123
Uso de sobrecarga de
operadores e funções
amigas
EXEMPLO _FRACAO
Fracao Fracao::operator+ (const int i) {
Fracao tmp(i/1);
return operator+(tmp);
}
Fracao Fracao::operator- (const int i) {
Fracao tmp(i/1);
return operator-(tmp);
}
istream& operator>>(istream& stream, Fracao &f) {
stream >> f.Numerador >> f.Denominador;
f.reduzir();
return stream;
}
ostream& operator<<(ostream& stream, const Fracao &f) {
stream << f.Numerador;
if (f.Denominador!=1) stream << "/" << f.Denominador;
return stream;
}
void Fracao::reduzir() {
int a, b, sinal = 1, resto;
if (Numerador==0) Denominador = 1;
if (Numerador<0 && Denominador<0) {
Numerador = -Numerador; Denominador = - Denominador;
} else if (Numerador<0) {
Numerador = - Numerador; sinal = -1;
} else if (Denominador<0) {
Denominador = - Denominador; sinal = -1;
}
if (Numerador<Denominador) {
a = Numerador; b = Denominador;
} else {
a = Denominador; b = Numerador;
}
while (b!=0) {
resto = a % b;
a = b; b = resto;
}
Numerador /= a*sinal;
Denominador /= a;
}
20/04/2017 (C) 2017, PJANDL. 124
EXEMPLO _FRACAO
#include "Fracao.h"
#include <iostream>
using namespace std;
int main() {
Fracao f1, f2, f3;
cout << "Digite 1a. fracao (nun den): "; cin >> f1;
cout << "Digite 2a. fracao (nun den): "; cin >> f2;
cout << "Soma de Fracoesn";
f3 = f1 + f2;
cout << f1 << " + " << f2 << " = " << f3 << endl;
cout << "Subtracao de Fracoesn";
f3 = f1 - f2;
cout << f1 << " - " << f2 << " = " << f3 << endl;
cout << "Soma de Fracao e inteiron";
f3 = f1 + 1;
cout << f1 << " + 1 = " << f3 << endl;
cout << "Subtracao de Fracao e inteiron";
f3 = f1 - 1;
cout << f1 << " - 1 = " << f3 << endl;
return 0;
}
Exemplos de uso de Fracao:
Fracao f1(1/4), f2(3/6), f3(4/5);
Fracao f4 = f1 + f2 + f3;
f4 = f4 + 1;
Fracao f5 = f1 – f2 – f3;
f5 = f4 – 3;
20/04/2017 (C) 2017, PJANDL. 125
C++::HERANÇA
A herança (inheritance) é uma das formas
mais importantes do polimorfismo e pode
ser entendida como uma técnica para
que uma classe passe a utilizar atributos
e operações definidas em uma outra
classe, ou seja, compartilhe uma parcela
de sua implementação.
C++ oferece tanto a herança simples,
como a herança múltipla.
Em geral, podemos perceber que existe
uma relação de herança entre duas
classes quando a pergunta 'é um(a)?' é
respondida afirmativamente.
Sintaxe da herança simples:
class <NomeClasseDerivada> :
[especificadorAcesso] <NomeClasseBase> {
// corpo da classe derivada
};
20/04/2017 (C) 2017, PJANDL. 126
EXEMPLO
// Base.h
class Base {
private:
int a;
protected:
int b;
public:
void ajustaAB(int na, int nb) {
a = na; b = nb; }
int leA() { return a; }
int leB() { return b; }
};
#include <iostream>
#include "Base.h"
using namesapce std;
int main() {
Base obj;
cout << obj.leA() << "," << obj.leB() << endl;
obj.ajustaAB(5, -2);
cout << obj.leA() << "," << obj.leB() << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 127
EXEMPLO
// Derivada1.h
#include "Base.h"
class Derivada1: public Base {
private:
int c;
public:
void deslocar() {
int tmp = leA(); ajustaAB(b, c); c = tmp; }
void ajustaC(int nc) { c = nc; }
int leC() { return c; }
};
#include <iostream>
#include "Derivada1.h"
using namespace std;
main() {
Derivada1 obj;
cout << obj.leA() << "," << obj.leB() << ",“
<< obj.leC() << endl;
obj.ajustaAB(2, 4);
obj.ajustaC(6);
cout << obj.leA() << "," << obj.leB() << ",“
<< obj.leC() << endl;
obj.deslocar();
cout << obj.leA() << "," << obj.leB() << "," << obj.leC()
<< endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 128
C++::HERANÇA
A herança pública é uma situação comum em
projetos C++, mas também pode ser
especificada diferentemente.
Na herança pública, a implementação da
própria subclasse e de suas subclasses têm
acesso aos membros herdados públicos e
protegidos; já as instâncias destas subclasses
têm acesso somente aos membros herdados
públicos.
Na herança privada apenas a implementação
da própria subclasse tem acesso aos membros
herdados públicos e protegidos. Nem as
instâncias desta subclasse nem suas subclasses
poderão utilizar os membros herdados.
20/04/2017 (C) 2017, PJANDL. 129
C++::HERANÇA MÚLTIPLA
A herança múltipla resolve as questões
de quando uma nova classe possui
relacionamento com várias outras, pois
permite que sejam criadas novas classes
que compartilhem as características de
duas ou mais classes base
simultaneamente.
Sintaxe para herança múltipla:
class <NomeClasseDerivada> :
[especificadorAcesso1] <NomeClasseBase1>,
[especificadorAcesso2] <NomeClasseBase2>,
:
[especificadorAcessoN] <NomeClasseBaseN>
{
// corpo da classe derivada
};
20/04/2017 (C) 2017, PJANDL. 130
EXEMPLO
// Func.h
#ifndef _FUNC
#define _FUNC
#include <iostream>
using namespace std;
class Funcionario {
long id;
public:
Funcionario(long nid) { id = nid;
cout << "Construtor Funcionario: " << nid << endl;
}
~Funcionario() { cout << "Destrutor Funcionarion"; }
long getId() { return id; }
};
ostream& operator<<(ostream &out, Funcionario &f) {
return out << "Funcionario[" << f.getId() << "]";
}
class Temporario {
int periodo;
public:
Temporario(int p) {
cout << "Construtor Temporario: " << p << endl;
periodo = p;
}
~Temporario() { cout << "Destrutor Temporarion"; }
int getPeriodo() { return periodo; }
};
ostream& operator<<(ostream &out, Temporario &t) {
return out << "Temporario(" << t.getPeriodo() << "d)";
}
20/04/2017 (C) 2017, PJANDL. 131
Observe a existência apenas de
construtores parametrizados.
Observe o uso da sobrecarga
de operadores.
EXEMPLO
class Engenheiro: public Funcionario {
public:
Engenheiro(long nid): Funcionario(nid) {
cout << "Construtor Engenheiro: " << nid << endl;
}
~Engenheiro() { cout << "Destrutor Engenheiron"; }
};
ostream& operator<<(ostream &out, Engenheiro &e) {
return out << "Engenheiro[" << e.getId() << "]";
}
class Estagiario: public Funcionario, public Temporario {
public:
Estagiario(long nid, int p): Funcionario(nid), Temporario(p) {
cout << "Construtor Estagiario: " << nid << ",“
<< p << endl;
}
~Estagiario() { cout << "Destrutor Estagiarion"; }
};
ostream& operator<<(ostream &out, Estagiario &e) {
return out << "Estagiario[" << e.getId() << "]";
}
#endif
20/04/2017 (C) 2017, PJANDL. 132
Observe como os parâmetros dos
construtores das superclasses foram supridos.
EXEMPLO
#include <iostream>
#include "Func.h"
using namespace std;
int main() {
cout << "Criando objeto Engenheiron";
Engenheiro eng(12345);
cout << "Criando objeto Estagiarion";
Estagiario est(67890, 90);
return 0; // destrói objetos implicitamente
}
A execução deste programa demonstra
a passagem de parâmetros para as
superclasses envolvidas.
20/04/2017 (C) 2017, PJANDL. 133
C++::POLIMORFISMO
O polimorfismo permite:
 a sobrecarga de funções e operadores,
obtida em tempo de compilação (isto é,
implementadas diretamente) no código e
 também possibilita explorar a herança e
funções virtuais para manipulação
genérica de classes em tempo de execução
As classes Engenheiro e Estagiario
podem ter objetos declarados assim:
 Engenheiro eng(1111);
 Estagiario estag(2222, 60);
Como ambos são derivados da classe
Funcionario é possível simplesmente
atribuir seus endereços a ponteiros do
tipo da superclasse:
 Funcionario *func1 = &eng;
 Funcionario *func2 = &estag;
20/04/2017 (C) 2017, PJANDL. 134
EXEMPLO
#include <iostream>
#include "Func.h“
using namespace std;
// função genérica baseada em referência
void informacao(Funcionario &f) {
cout << f << endl;
}
// função genérica baseada em ponteiro
void mostraId(Funcionario *f) {
cout << "Id: " << f->getId() << endl;
}
int main() {
Engenheiro eng(1111);
Estagiario estag(2222, 60);
Engenheiro &e = eng;
cout << eng << endl; // exibição de dados originais
cout << estag << endl;
informacao(e); // usa função genérica c/ referências
informacao(estag);
// declaraçao de ponteiros tipo Funcionario (genericos)
Funcionario *func1 = &eng;
Funcionario *func2 = &estag;
Funcionario *func3 = &e;
mostraId(func1); // usa função genérica c/ ponteiros
mostraId(func2);
mostraId(func3);
return 0;
}
20/04/2017 (C) 2017, PJANDL. 135
PARTE VII::
ORIENTAÇÃO A OBJETOS AVANÇADA
C++ 200
UM MINICURSO
20/04/2017 (C) 2017, PJANDL. 136
C++::FUNÇÕES VIRTUAIS
Uma subclasse pode substituir uma
método existente em sua superclasse
(sobreposição ou method override).
Devido o polimorfismo, o método
chamado (da superclasse ou da
subclasse) depende do tipo de ponteiro
ou referência usada.
Mas nem sempre o efeito produzido é o
desejado. Nestes casos pode-se lançar
mão das funções virtuais.
Funções virtuais são marcadas com o
modificador virtual.
Observe nos próximo exemplos o efeito
do modificador virtual, assim como o
fato de ser hereditário.
20/04/2017 (C) 2017, PJANDL. 137
EXEMPLO
#include <iostream>
using namespace std;
class ValorSimples {
public:
int v_valor;
ValorSimples(int v=0) { v_valor = v; }
int valor() { return v_valor; }
};
class ValorDuplo: public ValorSimples {
public:
ValorDuplo(int v=0): ValorSimples(v) { };
int valor() { return 2*v_valor; }
};
int main() {
ValorSimples vs(5); // declara obj ValorSimples
ValorDuplo vd(5); // declara obj ValorDuplo
ValorSimples *pvs; // declara ponteiro ValorSimples
pvs = &vs; // obtém endereço obj ValorSimples
cout << "obj. ValorSimples via pont. ValorSimples: "
<< pvs->valor() << endl;
pvs = &vd; // obtém endereço obj ValorDuplo
cout << "obj. ValorDuplo via pont. ValorSimples: "
<< pvs->valor() << endl;
ValorDuplo *pvd = &vd; // declara pont. ValorDuplo
cout << "obj. ValorDuplo via pont. ValorDuplo : "
<< pvd->valor() << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 138
Sem o uso de funções virtuais
EXEMPLO
#include <iostream>
using namespace std;
class ValorSimples {
public:
int v_valor;
ValorSimples(int v=0) { v_valor = v; }
virtual int valor() { return v_valor; } // função virtual
};
class ValorDuplo: public ValorSimples {
public:
ValorDuplo(int v=0): ValorSimples(v) { };
int valor() { return 2*v_valor; } // func virtual herdada
};
int main() {
ValorSimples vs(5); // declara obj ValorSimples
ValorDuplo vd(5); // declara obj ValorDuplo
ValorSimples *pvs; // declara ponteiro ValorSimples
pvs = &vs; // obtém endereço obj ValorSimples
cout << "obj. ValorSimples via pont. ValorSimples: "
<< pvs->valor() << endl;
pvs = &vd; // obtém endereço obj ValorDuplo
cout << "obj. ValorDuplo via pont. ValorSimples: "
<< pvs->valor() << endl;
ValorDuplo *pvd = &vd; // declara pont. ValorDuplo
cout << "obj. ValorDuplo via pont. ValorDuplo : "
<< pvd->valor() << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 139
Com o uso de funções virtuais Classe ValorDuplo e função
main() não foram alteradas
C++::FUNÇÕES VIRTUAIS PURAS
Uma função-membro virtual pura é
aquela que não possui definição numa
classe, obrigando que suas subclasses
realizem tal definição.
Para indicar que uma função-membro é
'puramente virtual' (pure virtual) devemos
declará-la como:
virtual <tipo> nomeFunc([listaParam]) = 0;
Classes contendo métodos virtuais puros
são consideradas classes abstratas
(abstract classes), pois como sua
implementação está incompleta, não
podem ser instanciadas.
20/04/2017 (C) 2017, PJANDL. 140
EXEMPLO
// Comp.h
#ifndef _COMPONENTE
#define _COMPONENTE
#include <iostream>
#include <string>
class Componente {
string descr; // descrição do componente
int id; // id do componente
Componente *pai; // componente pai
public:
Componente(int n) {
id = n; defineDescr("Componente");
pai = NULL;
}
void defineDescr(const string d) { descr = d; }
string obtemDescr() const { return descr; }
unsigned int obtemId() const { return id; }
void definePai(Componente *c) { pai = c; }
Componente *obtemPai() const { return pai; }
virtual void draw()=0;
};
20/04/2017 (C) 2017, PJANDL. 141
EXEMPLO
class Rotulo: public Componente {
public:
Rotulo(int n): Componente(n) { defineDescr("Rotulo"); }
void draw() { cout << obtemDescr() << obtemId(); }
};
class Botao: public Componente {
public:
Botao(int n): Componente(n) { defineDescr("Botao"); }
void draw() { cout << obtemDescr() << obtemId(); }
void click() { /* processamento específico */}
};
class Container: public Componente {
Componente *comps[10];
int quant;
public:
Container(int n): Componente(n) {
defineDescr("Container"); quant = 0;
}
void adicionar(Componente *c) {
c->definePai(this); // registro de paternidade
if (quant<10) { comps[quant++] = c; }
}
int componentes() const { return quant; }
void draw() { // desenha comps contidos no container
cout << obtemDescr() << obtemId() << " [ ";
for (int i=0; i<quant; i++) {
comps[i]->draw(); cout << " ";
}
cout << "]";
}
};
#endif
20/04/2017 (C) 2017, PJANDL. 142
EXEMPLO
#include <iostream>
#include "Comp.h“
using namespace std;
int main() {
int id = 0;
cout << "Cria 1o. containern";
Container c1(id++);
c1.draw();
cout << "nAdiciona comps 1o. containern";
c1.adicionar(new Botao(id++));
c1.adicionar(new Botao(id++));
c1.adicionar(new Rotulo(id++));
c1.draw();
cout << "nCria 2o. containern";
Container c2(id++);
c2.draw();
cout << "nAdiciona comps 2o. containern";
c2.adicionar(new Rotulo(id++));
c2.adicionar(new Botao(id++));
c2.adicionar(new Rotulo(id++));
c2.adicionar(&c1);
c2.draw();
cout << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 143
C++::NAMESPACES
Um namespace é um bloco de escopo
denominado ou um espaço declarativo
identificado (ANSI, 1989), cujas definições
permitem agrupar conjuntos de classes,
objetos e funções sob um nome.
Na prática, os namespaces dividem o escopo
global em escopos menores.
Sintaxe:
namespace identificador {
// bloco do sub-escopo (ou do namespace)
}
Exemplo:
namespace IC {
long a;
double b;
int func (int) { ... }
}
20/04/2017 (C) 2017, PJANDL. 144
EXEMPLO _NAMESPACES
#include <iostream>
using namespace std;
namespace NS1 {
long a;
long dobro(long a) { return 2*a; }
}
namespace NS2 {
double a;
double dobro(double a) { return 2*a; }
}
int main() {
cout << "2 * 2 = " << NS1::dobro(2) << endl;
cout << "1.5 * 2 = " << NS2::dobro(1.5) << endl;
NS1::a = 10;
NS2::a = 4.5;
cout << NS1::a << " * 2 = "
<< NS1::dobro(NS1::a) << endl;
cout << NS2::a << " * 2 = "
<< NS2::dobro(NS2::a) << endl;
cout << NS1::a << " * 2 = "
<< NS2::dobro(NS1::a) << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 145
C++::TEMPLATES
O mecanismo de construção dos templates
(ou modelos) em C++ permite que um tipo
(primitivo ou classe) seja empregado como
parâmetro na definição de uma função, ou
classe, ou mesmo outro modelo.
Os templates possibilitam criar funções e
classes capazes de realizar suas operações
com tipos distintos de dados sem o emprego
da sobrecarga, ou seja, preservando a lógica
interna e mantendo-se genérica em relação
aos tipos de dados manipulados.
Sintaxe:
template <classId1 [, classId2 ...]>
declaraçãoDaFunção;
template <classId1 [, classid2 ...]>
declaraçãoDaClasse;
Exemplo:
template <class Tipo>
Tipo Minimo (Tipo x, Tipo y) {
Tipo resultado = x > y ? x : y;
return resultado;
}
20/04/2017 (C) 2017, PJANDL. 146
EXEMPLO _TEMPLATES
#include <iostream>
using namespace std;
template <class T>
T Minimo (T x, T y) {
T resultado = x < y ? x : y;
return resultado;
}
int main() {
int a = 1, b = 2;
long c = 1029, d = -10;
double e = 2.34e10, f = 0.23e-2;
int r1 = Minimo<int>(a, b);
long r2 = Minimo(c, d);
cout << "Minimo(" << a << ", " << b
<< ")= " << r1 << endl;
cout << "Minimo(" << c << ", " << d
<< ")= " << r2 << endl;
cout << "Minimo(" << e << ", " << f
<< ")= " << Minimo(e, f) << endl;
return 0;
}
20/04/2017 (C) 2017, PJANDL. 147
C++200
C++200
C++200

More Related Content

Similar to C++200

Introdução à Linguagem de Programação C
Introdução à Linguagem de Programação CIntrodução à Linguagem de Programação C
Introdução à Linguagem de Programação CJose Augusto Cintra
 
Introdução a linguagem de programação C
Introdução a linguagem de programação CIntrodução a linguagem de programação C
Introdução a linguagem de programação CSchoolByte
 
Introdução+à+linguagem+c
Introdução+à+linguagem+cIntrodução+à+linguagem+c
Introdução+à+linguagem+cThiago Freitas
 
5. introducao a linguagem c
5. introducao a linguagem c5. introducao a linguagem c
5. introducao a linguagem cEugenio Caetano
 
Logica5 141120062157-conversion-gate02
Logica5 141120062157-conversion-gate02Logica5 141120062157-conversion-gate02
Logica5 141120062157-conversion-gate02Lucas Antonio
 
Introdução a Linguagem de Programação C
Introdução a Linguagem de Programação CIntrodução a Linguagem de Programação C
Introdução a Linguagem de Programação CGercélia Ramos
 
Apostila de-introdução-à-linguagem-c
Apostila de-introdução-à-linguagem-cApostila de-introdução-à-linguagem-c
Apostila de-introdução-à-linguagem-cMaicon Rodrigues
 
Apostila linguagem c
Apostila linguagem cApostila linguagem c
Apostila linguagem corvel
 
Algoritomos aula 3 rafael
Algoritomos aula 3 rafaelAlgoritomos aula 3 rafael
Algoritomos aula 3 rafaelhugodrocha
 
Linguagem C e Dev-C++ Algumas Explicações
Linguagem C e Dev-C++  Algumas ExplicaçõesLinguagem C e Dev-C++  Algumas Explicações
Linguagem C e Dev-C++ Algumas Explicaçõesnataferraz
 
Apostila linguagem c
Apostila linguagem cApostila linguagem c
Apostila linguagem cvingue
 
Fundamentos do .NET Framework - Parte 2
Fundamentos do .NET Framework - Parte 2Fundamentos do .NET Framework - Parte 2
Fundamentos do .NET Framework - Parte 2Julian Correa
 

Similar to C++200 (20)

Introdução à Linguagem de Programação C
Introdução à Linguagem de Programação CIntrodução à Linguagem de Programação C
Introdução à Linguagem de Programação C
 
Introdução a linguagem de programação C
Introdução a linguagem de programação CIntrodução a linguagem de programação C
Introdução a linguagem de programação C
 
Ud2
Ud2Ud2
Ud2
 
Introdução+à+linguagem+c
Introdução+à+linguagem+cIntrodução+à+linguagem+c
Introdução+à+linguagem+c
 
5. introducao a linguagem c
5. introducao a linguagem c5. introducao a linguagem c
5. introducao a linguagem c
 
Logica5 141120062157-conversion-gate02
Logica5 141120062157-conversion-gate02Logica5 141120062157-conversion-gate02
Logica5 141120062157-conversion-gate02
 
Introdução a Linguagem de Programação C
Introdução a Linguagem de Programação CIntrodução a Linguagem de Programação C
Introdução a Linguagem de Programação C
 
Apostila de-introdução-à-linguagem-c
Apostila de-introdução-à-linguagem-cApostila de-introdução-à-linguagem-c
Apostila de-introdução-à-linguagem-c
 
Apostila linguagem c
Apostila linguagem cApostila linguagem c
Apostila linguagem c
 
Apostila c
Apostila cApostila c
Apostila c
 
Apostila linguagem c
Apostila linguagem cApostila linguagem c
Apostila linguagem c
 
02 - Introdução a linguagem C# v1.0
02 - Introdução a linguagem C# v1.002 - Introdução a linguagem C# v1.0
02 - Introdução a linguagem C# v1.0
 
Algoritomos aula 3 rafael
Algoritomos aula 3 rafaelAlgoritomos aula 3 rafael
Algoritomos aula 3 rafael
 
Linguagem C e Dev-C++ Algumas Explicações
Linguagem C e Dev-C++  Algumas ExplicaçõesLinguagem C e Dev-C++  Algumas Explicações
Linguagem C e Dev-C++ Algumas Explicações
 
Apostila linguagem c
Apostila linguagem cApostila linguagem c
Apostila linguagem c
 
Apostila linguagem c
Apostila linguagem cApostila linguagem c
Apostila linguagem c
 
Apostila linguagem c
Apostila linguagem cApostila linguagem c
Apostila linguagem c
 
Linguagem c
Linguagem cLinguagem c
Linguagem c
 
Linguagem C clecioamerico
Linguagem C clecioamericoLinguagem C clecioamerico
Linguagem C clecioamerico
 
Fundamentos do .NET Framework - Parte 2
Fundamentos do .NET Framework - Parte 2Fundamentos do .NET Framework - Parte 2
Fundamentos do .NET Framework - Parte 2
 

More from Peter Jandl Junior

More from Peter Jandl Junior (13)

2023-03-23-ArduinoDay-CompFisica-1osPassos-ESP8266-v1.pdf
2023-03-23-ArduinoDay-CompFisica-1osPassos-ESP8266-v1.pdf2023-03-23-ArduinoDay-CompFisica-1osPassos-ESP8266-v1.pdf
2023-03-23-ArduinoDay-CompFisica-1osPassos-ESP8266-v1.pdf
 
Power BI 101
Power BI 101Power BI 101
Power BI 101
 
Robocode 666
Robocode 666Robocode 666
Robocode 666
 
Robocode 101
Robocode 101Robocode 101
Robocode 101
 
O (papel do) Arquiteto de Software
O (papel do) Arquiteto de SoftwareO (papel do) Arquiteto de Software
O (papel do) Arquiteto de Software
 
Reee - Resíduos Eletro Eletrônicos
Reee - Resíduos Eletro EletrônicosReee - Resíduos Eletro Eletrônicos
Reee - Resíduos Eletro Eletrônicos
 
Revisitando o Robocode
Revisitando o RobocodeRevisitando o Robocode
Revisitando o Robocode
 
Robocode
RobocodeRobocode
Robocode
 
SO-II-2016-1-02-Virtualizacao
SO-II-2016-1-02-VirtualizacaoSO-II-2016-1-02-Virtualizacao
SO-II-2016-1-02-Virtualizacao
 
2015-TCC-como apresentar
2015-TCC-como apresentar2015-TCC-como apresentar
2015-TCC-como apresentar
 
Novidades do Java 8
Novidades do Java 8Novidades do Java 8
Novidades do Java 8
 
SO-II-2015-2-02-Virtualizacao
SO-II-2015-2-02-VirtualizacaoSO-II-2015-2-02-Virtualizacao
SO-II-2015-2-02-Virtualizacao
 
Y da Carreira
Y da CarreiraY da Carreira
Y da Carreira
 

C++200

  • 1. C++ 200 UM MINICURSO Prof. Ms. Peter Jandl Junior ADS & GTI FATEC Jundiaí
  • 2. POR QUÊ C++? 20/04/2017 (C) 2017, PJANDL. 2
  • 3. 20/04/2017 (C) 2017, PJANDL. 3 Não é razão suficiente?
  • 4. ROTEIRO Parte I::Visão Geral  Origens, Características, Abstração, Recursos Necessários. Parte II::Fundamentos  Estrutura dos Programas, Variáveis, Palavras Reservadas, Tipos de Dados, Constantes, Conversão de Tipos, Console, Escopo, Operadores, Precedência, Diretivas de Controle. Parte III::Estruturas de Dados  Arranjos, Ponteiros, Alocação Dinâmica, Enumerações, Estruturas, Uniões. Parte IV::Funções  Definição, Declaração, Prototipagem, Passagem de Parâmetros, Valores Default, Sobrecarga. Parte V::OO Básica  Classes, Membros, Acessibilidade, Construtores, Destrutores, Sobrecarga, Ponteiro this. Parte VI::OO Intermediária  Funções Amigas, Classes Amigas, Sobrecarga de Operadores, Herança Simples, Herança Múltipla, Polimorfismo. Parte VII::OO Avançada  Funções Virtuais, Classes Abstratas. 20/04/2017 (C) 2017, PJANDL. 4
  • 5. PARTE I:: VISÃO GERAL C++ 200 UM MINICURSO 20/04/2017 (C) 2017, PJANDL. 5
  • 6. C++::ORIGENS Para superar as limitações da linguagem C, Bjarne Stroustrup constrói, em 1980 nos Laboratórios Bell (Nova Jérsei, EUA), um conjunto de extensões para permitir a criação de programas melhores e mais complexos, principalmente do ponto de vista de projeto.  Estrutura sintática da linguagem C  Conceitos de classe da linguagem Simula67  Sobrecarga de operadores do Algol68 Resultou no “C with Classes”, cujo nome foi alterado para C++ (“C plus plus” cujo sentido pretendido era “C com algo mais”). A adoção surpreendentemente grande fez com que fosse padronizada pela ANSI e ISO em 1990. Atualmente seu padrão é a ISO/IEC 14882. 20/04/2017 (C) 2017, PJANDL. 6
  • 8. C++::CARACTERÍSTICAS Simplicidade  Estrutura sintática simples e concisa. Oferece sistema de divisão modular que favorece o reuso. Performance  Ausência de restrições e mecanismos embutidos de controle possibilitam a geração de código em linguagem de máquina conciso e muito eficiente. Portabilidade  A padronização efetiva faz com que, quando seguida, possibilite a recompilação do código fonte para diferentes plataformas sem necessidade de qualquer ajuste ou alteração. Versatilidade  Embora com sintaxe simples, é uma linguagem de alto nível que permite a expressão de algoritmos e estruturas de dados sofisticadas, acesso ao hardware e integração com outras linguagens de programação. 20/04/2017 (C) 2017, PJANDL. 8
  • 9. C++::ABSTRAÇÃO C++ permite que a programação seja realizada de maneira genérica. Possibilita a definição de novos tipos. Garante isolamento adequado entre as funcionalidades existentes. Permite uso amplo e eficiente dos conceitos da programação orientada a objetos. 20/04/2017 (C) 2017, PJANDL. 9
  • 10. C++::RECURSOS NECESSÁRIOS GNU C++ Compiler [“nativo” no Linux, disponível para Windows como MinGW: http://www.mingw.org/ ] Dev C++ [IDE free, open source, disponível para Windows e outras plataformas: http://www.bloodshed.net/dev/devcpp.html ] Eclipse C++ IDE [tradicional IDE Java com plugins para desenvolvimento C++: http://www.bloodshed.net/dev/devcpp.html Requer MinGW em sistemas Windows] VisualStudio C++ [IDE popular da Microsoft também permite desenvolvimento voltado para C++] 20/04/2017 (C) 2017, PJANDL. 10
  • 11. PARTE II:: FUNDAMENTOS C++ 200 UM MINICURSO 20/04/2017 (C) 2017, PJANDL. 11
  • 12. (O) EXEMPLO _HELLO (MAIS TRADICIONAL DE TODO MUNDO) /* Arquivo: main01.cpp Autor: Prof. Peter Jandl Jr */ #include <iostream> using namespace std; int main() { // impressão de mensagem no console cout << "Hello world!" << endl; // finalização do main (funcão principal) return 0; } 20/04/2017 (C) 2017, PJANDL. 12 include: efetua a inclusão de uma biblioteca no programa. using namespace: indica o uso de um espaço declarativo (no caso o padrão std). Para um programa mínimo em C++ basta remover a diretiva de impressão cout.
  • 13. C++::PROGRAMAÇÃO 20/04/2017 (C) 2017, PJANDL. 13 Editor ASCII Compilador C/C++ Arquivo Fonte Arquivo Objeto Arquivo Executável Bibliotecas Ligador
  • 14. C++::ESTRUTURA DOS PROGRAMAS Programa em linguagem C++ são compostos de um ou mais arquivos de programa fonte, cada um considerado uma unidade de compilação (ou translation unit). Cada unidade de compilação pode conter: diretivas do pré-processador (include, define, if, ifdef...) declarações de: variáveis; estruturas de dados; funções; e classes. implementação de: funções; e classes. 20/04/2017 (C) 2017, PJANDL. 14
  • 15. C++::VARIÁVEIS Variáveis são nomes definidos pelo programador para os quais podem ser associados valores. Em linguagens fortemente tipadas, como C++, tais valores devem pertencer a um tipo (que determina uma faixa de valores aceitáveis ou pertencentes a um elemento). Sintaxe: <Tipo> <nome1> [, <nome2> [...] ]; Identificadores válidos:  sequência de um ou mais caracteres alfabéticos, dígitos numéricos e `_` (sublinhado), iniciados por letra ou sublinhado.  usualmente apenas 32 primeiros caracteres são usados para distinção dos identificadores.  C++ é sensível ao caixa, ou seja, diferencia maiúsculas de minúsculas.  Palavras reservadas não podem ser usadas como identificadores. 20/04/2017 (C) 2017, PJANDL. 15
  • 16. C++::KEYWORDS* (PALAVRAS RESERVADAS*) auto bool break case catch char class const const_cast continue default delete do double dynamic_cast else enum explicit export extern false float for friend goto if inline int long mutable namespace new operator private protected public register reinterpret_cast return short signed sizeof static static_cast struct switch template this throw true try typedef typeid typename union unsigned using virtual void volatile while 20/04/2017 (C) 2017, PJANDL. 16 São destacadas as 47 que serão vistas neste tutorial. C++ possui 61 keywords. *Emitálico,keywordscompatilhadascomC.
  • 17. C++::TIPOS DE DADOS Estão disponíveis os tipos de dados pré- definidos típicos da maioria das LPs: caracteres inteiros ponto flutuante lógico Também existem tipos derivados e a possibilidade de definição de novos tipos por parte do programador. Tipos de Dados C++ Tipos de Dados C++ Pré- definidos Pré- definidos IntegraisIntegrais charchar intint Ponto flutuante Ponto flutuante floatfloat doubledouble LógicoLógico boolbool DerivadosDerivados ArranjoArranjo FunçãoFunção PonteiroPonteiro ReferênciaReferência DefiníveisDefiníveis EnumeraçãoEnumeração EstruturaEstrutura ClasseClasse UniãoUnião 20/04/2017 (C) 2017, PJANDL. 17
  • 18. C++::TIPOS DE DADOS Existem modificadores short long signed unsigned Quando aplicados aos tipos integrais permitem reduzir/ampliar a faixa de valores e também desconsiderando o sinal. Existe também o tipo void, especial, que sinaliza a ausência de resultado. 20/04/2017 (C) 2017, PJANDL. 18
  • 19. C++::TIPO DE DADOS Caracteres char letra = 'J'; char especial = 'n'; char hexa = 'x61'; caractere 'a' 20/04/2017 (C) 2017, PJANDL. 19
  • 20. C++::TIPOS DE DADOS Inteiros int a = 2; signed int x = -13; long int y = 95000L; // sufixo L unsigned int z = 765u; // sufixo u int h = 0xCAFE; // prefixo 0x : hexa int octal = 02000; // prefixo 0 : octal Dica Arquivo de cabeçalho (header file) "climits.h" da biblioteca padrão contém os tamanhos em bytes, bem como os valores mínimos e máximos dos tipos primitivos e outros eventualmente adicionados pela implementação. 20/04/2017 (C) 2017, PJANDL. 20
  • 21. C++::TIPOS DE DADOS Ponto flutuante float f = 1.46; float c = -25.34e8; double d = 534.789e-11; long double ld = 143.2314673595l; Lógico bool flag = true; bool error = false; Também existe equivalência entre tipos lógicos e numéricos, tal como na linguagem C:  valores iguais a zero equivalem a false  valores diferentes de zero equivale a true 20/04/2017 (C) 2017, PJANDL. 21 long também se aplica ao tipo double e suas constantes requerem o sufixo l ou L.
  • 22. EXEMPLO _SIZEOF /* Arquivo: main02.cpp Autor: Prof. Peter Jandl Jr */ #include <iostream> using namespace std; int main() { cout << " char:" << sizeof(char) << "n bool:" << sizeof(bool) << endl; cout << " short:" << sizeof(short) << "n int:" << sizeof(int) << endl; cout << " long:" << sizeof(long) << "n float:" << sizeof(float) << endl; cout << " double:" << sizeof(double) << "n long double:" << sizeof(long double) << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 22 sizeof retorna o tamanho em bytes do tipo indicado endl é uma constante e representa o fim de uma linha de texto.
  • 23. C++::CONSTANTES Definidas Identificador associado a um valor literal constante. #define <id> <valor> Exemplos: #define PI 3.1415926 #define MAX 1024 Durante pré-processamento do programa, identificador será substituído pelo literal previamente indicado. Declaradas Variável cujo conteúdo está associado ao tipo especificado, mas que não pode ter valor alterado durante execução do programa. const <tipo> <id> = <expr>; Exemplos: const double PI = 3.1415926; const long MAX = 1024L; 20/04/2017 (C) 2017, PJANDL. 23
  • 24. C++::MODIFICADORES DE ACESSO const Define um elemento que não pode ser modificado pelo programa. Pode ser usado para declaração de constantes, como já visto, e também para indicar parâmetros que não podem ser modificados por funções ou métodos: <tipoRet> nomeF ( const <tipo> param [, ...] ); size_t strlen(cont char *str); volatile Indica ma variável cujo conteúdo pode ser alterado de maneira indireta, não causada pelo próprio programa. volatile <tipo> id; Exemplos dessa situação são variáveis compartilhadas entre o programa e o sistema operacional, onde este último é responsável pela atualização do conteúdo da variável. volatile unsigned char *clock = 0x3F; 20/04/2017 (C) 2017, PJANDL. 24
  • 25. C++::CONVERSÃO DE TIPOS A promoção automática de tipos é a conversão implícita e automática de um tipo mais simples para outro mais complexo adequado à avaliação de uma expressão. int a = 1; long b = 99999; // conversão b = a + b; // conversão float c = b * 0.33; // conversão 20/04/2017 (C) 2017, PJANDL. 25 bool char int long float double long double
  • 26. C++::CONVERSÃO DE TIPOS 20/04/2017 (C) 2017, PJANDL. 26 long char float float char char char intint long long float char doubledouble int long float int float double double long double int double char long double long double long double long double long int char float long double long double long double Este diagrama mostra apenas os tipos de dados principais
  • 27. C++::CONVERSÃO DE TIPOS A conversão explícita de tipos (coerção ou type casting) permite que o programador especifique uma conversão desejada. (tipo) expressão forma comum tipo(expressão) forma funcional Exemplos: int a = 3, b = 2; float c1 = a / b; cout << c1; // exibe 1 float c2 = (float) a / b; cout << c2; // exibe 1.5 20/04/2017 (C) 2017, PJANDL. 27
  • 28. C++::CONSOLE Entrada A entrada direta pode utilizar outro objeto pré-definido, cin (console in) que permite o uso do dispositivo de entrada padrão (teclado). int x; cin >> x; float f; cin >> f; Saída Exibição simples de valores e mensagens pode ser feita por meio de cout (console out), um objeto pré-definido que permite a impressão no dispositivo de saída padrão (console). cout << 10; cout << "Mensagem"; cout << "Concatenação: " << x << endl; 20/04/2017 (C) 2017, PJANDL. 28 Também existe um objeto pré- definido para saída de erros, cerr, semelhante a cout.
  • 29. C++::ESCOPO Escopo são os locais do programa nos quais uma declaração específica tem validade. É o espaço declarativo de variáveis e outras construções válidas. C++ permite declarar variáveis em qualquer ponto do código, as quais serão válidas até o final do bloco onde foram declaradas. C++ oferece três níveis de escopo: global, local e imediato. Global Local Imediato • Visível em todo código. • Visibilidade limitada à função ou método. • Visibilidade restrita ao bloco. 20/04/2017 (C) 2017, PJANDL. 29
  • 30. EXEMPLO _ESCOPO #include <iostream> using namespace std; int x = 10; // variável global int main() { cout << "x: " << x << endl; int x = 20; // variável local cout << "x: " << x << endl; { int x = 30; // variável imediata cout << "x: " << x << endl; cout << "x: " << ::x << endl; // uso do operador :: } cout << "x: " << x << endl; cout << "x: " << ::x << endl; // uso do operador :: return 0; } 20/04/2017 (C) 2017, PJANDL. 30 Operador :: (resolução de escopo) provê acesso ao nível global. Variáveis redeclaradas ocultam o escopo exterior.
  • 31. C++::OPERADORES Aritméticos +, -, *, / operadores algébricos % resto da divisão inteira ++, -- incremento e decremento unitários Relacionais ==, != igualdade e diferença >, >=, <, <= comparadores 20/04/2017 (C) 2017, PJANDL. 31
  • 32. C++::OPERADORES Lógicos && e lógico || ou lógico ! não lógico (negação) Bit-a-bit & e bitwise | ou bitwise ˆ ou-exclusivo bitwise ~ complemento >>, << deslocamento (shift) à direita e à esquerda 20/04/2017 (C) 2017, PJANDL. 32
  • 33. C++::OPERADORES Atribuição = atribuição +=, -=, atribuição compacta *=, /=, %=, &=, |=, ˆ=, >>=, <<= Exemplo: x = x + 10; x += 10; Ternário ? : operador ternário Permite seleção de um resultado entre dois para uma expressão, baseado no resultado de uma expressão lógica: exprLog ? expr1 : expr2 onde: exprLog seleciona o resultado true toma expr1 false toma expr2 20/04/2017 (C) 2017, PJANDL. 33
  • 34. C++ ::PRECEDÊNCIA A precedência é a ordem padronizada com que os operadores da linguagem são executados na avaliação de uma expressão. A precedência garante consistência matemática na avaliação de expressões algébricas, lógicas e relacionais, além das operações associadas às estruturas de dados e objetos. 20/04/2017 (C) 2017, PJANDL. 34
  • 35. C++::CONTROLE As diretivas que permitem realizar o controle do fluxo de execução. C++ oferece:  diretivas de repetição  diretivas de decisão (ou desvio de fluxo)  construções para modularização  diretivas de controle de erros 20/04/2017 (C) 2017, PJANDL. 35
  • 36. C++::CONTROLE 20/04/2017 (C) 2017, PJANDL. 36 Controle de fluxo estabelece como e quais diretivas serão executadas.
  • 37. C++::SEQUENCIAÇÃO Organização da sequência de diretivas da linguagem que conduzem a execução do programa no sentido de produzir o resultado desejado. Diretivas em C++ devem ser separadas por um ; (ponto-e-vírgula), organizadas tipicamente uma em cada linha. Mas várias diretivas podem existir numa mesma linha, quando separadas adequadamente. As chaves { } permitem delimitar um bloco de diretivas, que passarão a ser tratadas como uma unidade. //Exemplo _Seq #include <iostream> #include <cmath> using namespace std; int main() { double raio; cout << "Raio? "; cin >> raio; double area = M_PI * pow(raio, 2); cout << "Area = " << area << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 37 Exemplo _Seq
  • 38. C++::WHILE Diretiva de repetição condicional. int k = 0, j = 20; while (k < j) { cout << k << " menor " << j << endl; k++; j = j - 2; } 20/04/2017 (C) 2017, PJANDL. 38 expressão diretiva falsaverdadeira Os fragmentos que seguem podem ser testados, bastando incluí-los num programa mínimo. Exemplo _Fragmentos
  • 39. C++::DO/WHILE Diretiva de repetição condicional. float valor, min=0, max=10; do { cout << "Digite valor [0..10]? "; cin >> valor; } while (valor<min || valor>max); 20/04/2017 (C) 2017, PJANDL. 39 expressão diretiva falsa verdadeira Exemplo _Fragmentos
  • 40. C++::FOR Diretiva automática de repetição condicional. const int MAX = 5; double soma = 0, numero; for (int i=0; i<MAX; i++) { cout << "#" << i << "? " << endl; cin >> numero; soma += numero; } cout << "Soma: " << soma << endl; 20/04/2017 (C) 2017, PJANDL. 40 expressãodiretiva falsa verdadeira incremento ou decremento inicialização Exemplo _Fragmentos
  • 41. C++::IF Diretiva de desvio condicional simples. int x; cout << "Digite um inteiro para x: "; cin >> x; if (x < 0) { cout << "x menor do que zero"; } 20/04/2017 (C) 2017, PJANDL. 41 expressão diretiva1 falsaverdadeira Exemplo _Fragmentos
  • 42. C++::IF/ELSE Diretiva de desvio condicional completa. int y; cout << "Digite um inteiro para y: "; cin >> y; if (y > 0 && y < 11) { cout << "y no intervalo [1..10]" << endl; } else { cout << "y fora do intervalo [1..10]" << endl; } 20/04/2017 (C) 2017, PJANDL. 42 expressão diretiva1 falsaverdadeira diretiva2 Exemplo _Fragmentos
  • 43. C++::SWITCH Diretiva de desvio condicional múltiplo, baseado em expressão ordinal. char letra; cout << "Digite uma letra maiúscula entre A e E: "; cin >> letra; switch (letra) { case "A": cout << "Conceito máximo"; break; // : case "E": cout << "Conceito mínimo"; break; default: cout << "Conceito inválido"; } 20/04/2017 (C) 2017, PJANDL. 43 expressão ordinal diretiva1 defaultcase 1 diretivaNdiretiva2 diretiva3 case 2 case 3  Exemplo _Fragmentos
  • 44. C++::GOTO Diretiva de desvio incondicional. goto <label>; Onde label é um rótulo, definido acima (antes) ou abaixo (depois) da diretiva. label: diretiva1; diretiva2; : Rótulos devem ser declarados no mesmo escopo onde diretiva goto é usada. Embora possível e disponível na linguagem C++, o uso da diretiva goto é fortemente desencorajado, pois em raríssimas situações é, de fato a melhor alternativa. Em geral seu uso esconde alguma deficiência no projeto do algoritmo. 20/04/2017 (C) 2017, PJANDL. 44
  • 45. EXEMPLO _GOTO #include <iostream> #include <iomanip> using namespace std; int main() { cout << "Caracteres ASCII [33..132]" << endl; unsigned char c = 33; int i = 0; laco: cout << c << " " << setw(3) << int(c) << "| "; i++; c++; if (i%10==0) { cout << endl; } if (c<=132) { goto laco; } return 0; } 20/04/2017 (C) 2017, PJANDL. 45 Resultados do programa
  • 46. C++::BREAK & CONTINUE break Diretiva de desvio incondicional que interrompe o comando corrente (um laço ou decisão múltipla com switch), fazendo que a execução prossiga no comando subsequente àquele em que foi usado. continue Diretiva de desvio incondicional que abrevia a iteração corrente do laço, fazendo que a expressão de controle do comando de repetição seja novamente avaliada, acelerando assim a continuação do comando de repetição. 20/04/2017 (C) 2017, PJANDL. 46
  • 47. EXEMPLO _GRAFICO #include <iostream> #include <iomanip> #include <cmath> using namespace std; int main() { cout << "Polinomio de 2o. grau" << endl; // coeficientes do polinômio deveriam ser lidos double a = -1.5, b = 3.0, c = 2.2, xi, xf; // intervalo da ordenada cout << "Valor inicial da ordenada? "; cin >> xi; // 0 cout << "Valor final da ordenada? "; cin >> xf; // 2.4 // desenha eixo da abcissa cout << “______0"; for (int i=1; i<6; i++) { cout << "---------"<< i; } cout << " (Y)" << endl; // plota polinômio for (double x=xi; x<=xf; x+=0.2) { double aux = (int(10*x))/10.0; cout << setw(6) << aux << " "; double y = a*pow(x, 2) + b*x + c; if (y<0 || y>5) { cout << endl; // abcissa fora da escala continue; // abrevia iteração } // plota abcissa em escala 10:1 for (int i=0, l=int(10*y)-1; i<l; i++) { cout << " "; } cout << "+" << endl; // ponto da função } cout << " (X)" << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 47 Uso de continue
  • 48. EXEMPLO _GRAFICO 20/04/2017 (C) 2017, PJANDL. 48 Resultados do programa
  • 49. PARTE III:: ESTRUTURAS DE DADOS C++ 200 UM MINICURSO 20/04/2017 (C) 2017, PJANDL. 49
  • 50. C++ ::ESTRUTURAS DE DADOS C++ oferece várias estruturas de dados.  Derivadas  Arranjo  Função  Ponteiro  Referência  Definíveis  Enumeração  Estrutura  União  Classe 20/04/2017 (C) 2017, PJANDL. 50
  • 51. C++::ARRANJOS Arranjos ou Arrays são: conjuntos de elementos de um mesmo tipo; organizados em posições consecutivas da memória; ocupando uma região de tamanho fixo (capacidade máxima pré-definida); seus elementos podem ser acessados individual e aleatoriamente por meio de um índice (primeira posição é zero). Arranjos podem ser unidimensionais ou multidimensionais, Declaração (unidimensional): <Tipo> <id>[<tamanho>]; Exemplos: int a[10]; double f[1024]; float k[] = { 0.1, 2.3, 4.56, -78.9 }; 20/04/2017 (C) 2017, PJANDL. 51
  • 52. C++::ARRANJOS 20/04/2017 (C) 2017, PJANDL. 52 arranjo com 12 elementos 31 102 8 0 1 2 arranjo[ 0 ][ 0 ] arranjo[ 2 ][ 0 ] arranjo[ 2 ][ 3 ] arranjo[ 0 ][ 3 ] arranjo[ 1 ][ 1 ] 713 -82 946 37 9 456 512 -28 91 0 1 2 3índices arranjo com 5 elementos 13 -28 946 50 724 0 1 2 3 4 índices conteúdos arranjo[ 0 ] arranjo[ 1 ] arranjo[ 2 ] arranjo[ 3 ] arranjo[ 4 ] elementos individuais unidimensional bidimensional
  • 53. EXEMPLO _ARRANJO #include <iostream> using namespace std; const int MAX = 5; int main() { double a[MAX]; // lê arranjo for (int i=0; i<MAX; i++) { cout << "#" << i << "? "; cin >> a[i]; } // soma elementos do arranjo double soma = 0; for (int i=0; i<MAX; i++) { soma = soma + a[i]; } cout << "Soma = " << soma << endl; return 0; } Cuidado! C++ inicializa automaticamente apenas arranjos (e variáveis) globais. C++ não mantém o tamanho dos arranjos, nem dispõe de função para tal fim. C++ não oferece qualquer mecanismo de proteção ou restrição quanto ao uso de índices inválidos para acesso aos elementos do arranjo. 20/04/2017 (C) 2017, PJANDL. 53 Uso de array unidimensional
  • 54. EXEMPLO _MATRIZ #include <iostream> #include <iomanip> using namespace std; int main() { // declara e inicializa matriz int matriz[3][4] = { { 31, 713, 37, 512 }, { 102, -82, 9, -28 }, { 8, 946, 546, 91 } }; double res[3][4]; // declara matriz cout << "Matriz dada:n"; for (int l=0; l<3; l++) {// exibe matriz organizada em linhas e colunas cout << "[ "; for (int c=0; c<4; c++) { cout << setw(6) << matriz[l][c] << " "; } cout << "]n"; } cout << "Normalizando Matriz...n"; double maior = matriz[0][0]; for (int l=0; l<3; l++) {// determina maior elemento da matriz for (int c=0; c<4; c++) { if (maior<matriz[l][c]) maior = matriz[l][c]; } } // normaliza matriz: maior=1 e outros proporcionais a maior for (int l=0; l<3; l++) { for (int c=0; c<4; c++) { res[l][c] = matriz[l][c]/maior; } } cout << "Matriz resultado:n"; // exibe matriz organizada em linhas e colunas for (int l=0; l<3; l++) { cout << "[ "; for (int c=0; c<4; c++) { cout << setw(10) << setprecision(3) << res[l][c] << " "; } cout << "]n"; } return 0; // encerra programa } 20/04/2017 (C) 2017, PJANDL. 54 Uso de arrays bidimensional
  • 55. C++::STRINGS Uma string é uma sequência de caracteres de comprimento arbitrário. C++ compartilha com sua antecessora C o uso de arrays de caracteres terminados com nulo (caractere ‘0’ ou 0). 20/04/2017 (C) 2017, PJANDL. 55 Exemplos: char nome[ ] = “Peter Jandl Jr.”; char lang [ ] = { ‘C’, ‘+’, ‘+’, 0 }; char s[ ] = { ‘0’ };
  • 56. C++::STRINGS #include <iostream> #include <cstring> using namespace std; int main() { char nome[20], linha[80]; // duas strings // entrada de string com uso direto de cin cout << "Qual o seu nome? "; cin >> nome; // lê apenas 1a palavra cin.ignore(80, 'n'); // ignora restante da entrada até 'ENTER' cout << "Alo " << nome << "!n" << "Digite uma ou mais frases, '.' finaliza programa.n"; do { // entrada de string com uso de cin.getline cin.getline(linha, 80); // lê tudo até 'ENTER' cout << linha << " : " << strlen(linha) << endl; } while (linha[0]!='.'); // encerra laço se 1o caractere='.' cout << "Tchaun"; return 0; // encerra programa } 20/04/2017 (C) 2017, PJANDL. 56 Exemplo _String
  • 57. C++::ENUMERAÇÕES Uma enumeração é uma construção da linguagem que permite agrupar um conjunto de elementos constantes definidos pelo programador. enum [nome] { <id1> [, <id2> [...] ] }; São mais convenientes que constantes individuais quando o grupo de valores enumerados constitui um conjunto (como um tipo de dados). A cada constante é associado um valor inteiro a partir do zero. Exemplos: enum cor { Branco, Vermelho, Cinza }; enum escolaridade { Fundamental, Medio, Superior, Especializacao, Mestrado, Doutorado, PosDoutorado }; enum zoom { z0=1, z1=2, z2=4 }; enum mes { janeiro=1, fevereiro, marco, abril, maio, junho, julho, agosto, setembro, outubro, novembro, dezembro }; 20/04/2017 (C) 2017, PJANDL. 57
  • 58. EXEMPLO _ENUM #include <iostream> using namespace std; enum zoom { z0=1, z1=2, z2=4 }; int main() { enum { A, B, C }; // enum anônima cout << A << " ... " << C << endl; zoom zIni = z0; // uso de constante zoom zMax = zoom(3); // coerção cout << zIni << " ... " << zMax << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 58 Uso de enumerações
  • 59. C++::PONTEIROS Ponteiros (pointers) são variáveis especiais capazes de armazenar endereços de memória, ou seja, seus conteúdos se referem à localização de outro objeto na memória (como uma variável, arranjo, outro ponteiro etc.). Ponteiros permitem o acesso e a modificação das posições de memória indicadas. Proveem suporte para alocação dinâmica de memória. Declaração de ponteiro: <Tipo> *<nome>; Exemplos: char *palavra; // ponteiro para caractere int *p; // ponteiro para inteiro long *cont; // ponteiro para long void *qq; // ponteiro para void double *total; // ponteiro para double 20/04/2017 (C) 2017, PJANDL. 59
  • 60. C++::PONTEIROS Operadores Específicos: • Endereço de & • Conteúdo de * Exemplos: int a = 33; // variável int int *p1 = &a; // ponteiro para int char c = 'A'; // variável char char *p2 = &c; // ponteiro para char int b = *p1; // var. b recebe conteúdo // apontado por p1 // exibe o conteúdo apontado por p2 cout << *p2 << endl; 20/04/2017 (C) 2017, PJANDL. 60
  • 61. C++::PONTEIROS A obtenção do conteúdo de um endereço de memória através do operador '*' é conhecida como 'indireção' (indirection ou dereferencing) e é uma operação fundamental para a utilização efetiva dos ponteiros. #include <iostream> using namespace std; int main() { int a = 33; // variável inteira simples char c = 'A'; // variável caractere simples int* p1 = &a; // ponteiro para inteiro char* p2 = &c; // ponteiro para caractere // exibe informações sobre os ponteiros cout << " Ponteiro p1: " << p1 << endl << "Conteudo do endereco p1: " << *p1 << endl << "Endereco do ponteiro p1: " << &p1 << endl; cout << " Ponteiro p2: " << (int*)p2 << endl << "Conteudo do endereco p2: " << *p2 << endl << "Endereco do ponteiro p2: " << &p2 << endl; return 0; // encerra o programa } 20/04/2017 (C) 2017, PJANDL. 61 Uso de ponteiros e seus operadores Exemplo _Ponteiro
  • 62. C++::PONTEIROS Os operadores soma (‘+’), subtração (‘-’), incremento (‘++’) e decremento (‘--’) podem ser aplicados aos ponteiros para modificar o local apontado. Através do operador soma ('+') podemos adicionar um valor inteiro a um ponteiro de modo que ele seja “avançado” tal número de elementos do tipo, passando a apontar uma localidade de memória num endereço superior ao anterior. Com o operador subtração (‘-') ocorre o inverso, fazendo que o ponteiro seja “retrocedido” o número indicado de elementos, apontando para um endereço anterior. 20/04/2017 (C) 2017, PJANDL. 62 Aritmética de ponteiros
  • 63. C++::PONTEIROS #include <iostream> using namespace std; int main() { // ponteiros com endereços literais inválidos em outros sistemas! char *pChar = (char *)0x0065FDF4; cout << (int *)pChar << ": " << *pChar << endl; pChar = pChar + 1; cout << (int *)pChar << ": " << *pChar << endl; pChar += 1; cout << (int *)pChar << ": " << *pChar << endl; pChar++; cout << (int *)pChar << ": " << *pChar << endl; long *pLong = (long *)0x0065FE00; cout << pLong << ": " << *pLong << endl; pLong = pLong - 1; cout << pLong << ": " << *pLong << endl; pLong -= 1; cout << pLong << ": " << *pLong << endl; pLong--; cout << pLong << ": " << *pLong << endl; return 0; // encerra o programa } Não pode ser empregado o operador '*' em ponteiros do tipo void porque não se sabe o tamanho dos dados apontados, exigindo uma operação de type casting para o tipo correto: int k = 10; // variável inteira void *p = &k; // ponteiro void recebe endereço cout << *((int*)p) << endl; // uso do ponteiro void para // acessar conteúdo apontado *((int*)p) = 33; // uso do ponteiro void para // modificar conteúdo apontado 20/04/2017 (C) 2017, PJANDL. 63 Exemplo _Ponteiro2
  • 64. C++::PONTEIROS #include <iostream> using namespace std; const int MAX =10; int main() { int a[MAX]; cout << "Entrada de valoresn"; for (int i=0; i<MAX; i++) { cout << "a[" << i << "] ?b"; cin >> a[i]; } cout << "Exibicao do arranjon[ "; for (int i=0; i<MAX; i++) { cout << a[i] << " "; } cout << "]n"; cout << "Invertendo posicao do elementos...n"; for (int i=0,j=MAX-1; i<j; i++, j--) { int tmp = *(a+i); // uso de aritmética de ponteiros *(a+i) = *(a+j); // para acessar e modificar *(a+j) = tmp; // elementos do arranjo } cout << "Exibicao do arranjo invertidon[ "; for (int i=0; i<MAX; i++) { cout << *(a+i) << " "; } cout << "]n"; return 0; // encerra o programa } 20/04/2017 (C) 2017, PJANDL. 64 Equivalência do uso de ponteiros e arranjos Exemplo _Ponteiro3
  • 65. C++::ALOCAÇÃO DINÂMICA Mecanismo que permite a agregação de novas regiões de memória para uso do programa durante sua execução. C++ permite: alocação dinâmica de memória por meio do operador new. liberação das regiões alocadas por meio do operador delete. Estes operadores são utilizados em conjunto com os ponteiros. Exemplos:  int *pInt; // ponteiro para inteiro  pInt = new int; // aloca memória p/ um int  delete pInt; // libera região alocada  double *pDouble; // ponteiro para double  pDouble = new double[1000]; // aloca mem p/1000 doubles  delete[] pDouble; // libera memória alocada 20/04/2017 (C) 2017, PJANDL. 65
  • 66. EXEMPLO _ALOCDINAM #include <iostream> using namespace std; int main() { int max; // tamanho do arranjo dinamicamente alocado cout << "Quantos elementos?n"; cin >> max; // aloca arranjo dinamicamente double *pDouble = new double[max]; if (pDouble==NULL) { cout << "Nao ha memoria suficiente no sistema.n"; return 1; // encerra programa com erro } cout << "Entrada de valoresn"; for (int i=0; i<max; i++) { cout << "valor[" << i << "] ?b"; cin >> pDouble[i]; } double soma = 0; // variável para total dos valores cout << "Exibicao do arranjon "; for (int i=0; i<max; i++) { cout << pDouble[i] << " "; soma += pDouble[i]; // acumula valores dados } // exibe média dos valores cout << "nMedia = " << soma/max << endl; delete[] pDouble; // libera memória alocada return 0; // encerra o programa } 20/04/2017 (C) 2017, PJANDL. 66
  • 67. C++::ALOCAÇÃO DINÂMICA Ponteiros para Ponteiros Um ponteiro pode conter o endereço de qualquer objeto existente, até de um outro ponteiro e este para outro, até que dados sejam apontados, o que constitui a indireção múltipla (multiple indirection).  int x = 17580; // variável int simples  int *p1 = &x; // ponteiro de int  int **p2 = &p1; // ponteiro de ponteiro de int  int ***p3 = &p2; // 3ª indireção para int Referências Uma referência é como um ponteiro implícito que funciona como um 'nome alternativo' para uma entidade.  double resultado; // variável comum  double &ref = resultado; // referência É obrigatória a inicialização das referências com uma variável ou valor constante, pois não podem ser alteradas depois de inicializadas. 20/04/2017 (C) 2017, PJANDL. 67
  • 68. C++::ESTRUTURAS Uma estrutura (structure) é:  um agrupamento de variáveis relacionadas,  mas de tipos arbitrários,  referenciadas por um mesmo nome. Cada variável designada como parte de uma estrutura é chamada de campo ou membro. Sintaxe: struct <nomeEstrutura> { <tipo1> <campo1>; [<tipo2> <campo2>; [...] ] } [var1 [, var2 [...]]]; Exemplo: struct s_pessoa { char nome[80]; // string com 80 caracteres short ddd; // inteiro curto long telefone; // inteiro longo char email[80]; // string com 80 caracteres }; 20/04/2017 (C) 2017, PJANDL. 68
  • 69. C++::ESTRUTURAS Declaração:  struct s_pessoa eu;  s_pessoa você; Inicialização na declaração:  s_pessoa peter = { "Peter Jandl", 11, 987654321, "prof.peter@fatec.sp.gov.br" }; Cópia:  s_pessoa copia = peter; Uso: cout << "nome : " << eu.nome << "nfone : (" << eu.ddd << ")" << eu.telefone << "nemail: “ << eu.email << endl; strcpy(eu.nome, "Peter Jandl Jr."); // nome é um campo string! eu.telefone = 976543210; // telefone é um campo inteiro 20/04/2017 (C) 2017, PJANDL. 69
  • 70. EXEMPLO _STRUCT #include <iostream> #include <cstring> using namespace std; struct s_pessoa { char nome[80]; // string com 80 caracteres short ddd; // inteiro curto long telefone; // inteiro longo char email[80]; // string com 80 caracteres }; int main() { // declaração e inicialização de estrutura struct s_pessoa eu = { "Peter", 11, 0, "jandl@live.com" }; // exibe campos cout << "nome : " << eu.nome << "nfone : (" << eu.ddd << ")" << eu.telefone << "nemail: " << eu.email << endl; // altera campos strcpy(eu.nome, "Peter Jandl Jr."); // nome é um campo string! eu.telefone = 38323374; // telefone é um campo inteiro // exibe campos novamente cout << "nome : " << eu.nome << "nfone : (" << eu.ddd << ")" << eu.telefone << "nemail: " << eu.email << endl; // declara outra estrutura e efetua leitura de seus campos struct s_pessoa voce; cout << "Seu nome? "; cin.getline(voce.nome,80); cout << " DDD? "; cin >> voce.ddd; cout << "Telefone? "; cin >> voce.telefone; cout << " E-mail? "; cin >> voce.email; // exibe campos cout << "nome : " << voce.nome << "nfone : (" << voce.ddd << ")" << voce.telefone << "nemail: " << voce.email << endl; return 0; // encerra o programa } 20/04/2017 (C) 2017, PJANDL. 70 Uso de struct e seus campos
  • 71. C++::ESTRUTURAS Composição de Estruturas struct s_data { short ano; short mes; short dia; }; struct s_compromisso { // estrutura independente struct s_data data; char lembrete[80]; } // declaração de variável struct s_compromisso c; // campos c.data.ano c.data.mes c.data.dia c.lembrete Composição com Estrutura Anônima struct s_compromisso { // estrutura anônima struct { short ano; short mes; short dia; }; char lembrete[80]; } // declaração de variável struct s_compromisso c; // campos c.ano c.mes c.dia c.lembrete 20/04/2017 (C) 2017, PJANDL. 71
  • 72. EXEMPLO #include <iostream> #include <cstring> using namespace std; // estruturas independentes aninhadas struct s_hora { short HH; short MM; }; struct s_compromisso { struct s_hora hora; char lembrete[80]; }; // estrutura anônima aninhada struct s_compromisso2 { struct { short HH; short MM; }; char lembrete[80]; }; int main() { // declara e inicializa estrutura e ponteiro para a mesma struct s_compromisso c1 = { 10, 30, "Cliente 1" }; struct s_compromisso *p1 = &c1; // exibe conteúdo dos campos da estrutura cout << c1.hora.HH << ":" << c1.hora.MM << " " << c1.lembrete << endl; cout << p1->hora.HH << ":" << p1->hora.MM << " " << p1->lembrete << endl; // declara e inicializa estrutura e ponteiro para a mesma struct s_compromisso2 c2; c2.HH = c1.hora.HH; c2.MM = p1->hora.MM; strcpy(c2.lembrete, p1->lembrete); struct s_compromisso2 *p2 = &c2; // exibe conteúdo dos campos da estrutura cout << c2.HH << ":" << c2.MM << " " << c2.lembrete << endl; cout << p2->HH << ":" << p2->MM << " " << p2->lembrete << endl; return 0; // encerra programa } 20/04/2017 (C) 2017, PJANDL. 72 Uso de struct e seus campos por meio de ponteiros
  • 73. C++::UNIÕES Uma união (union) é como uma estrutura (struct), ou seja, organiza variáveis de tipos diferentes sob um mesmo nome, exceto pelo fato de que todas as variáveis compartilham o mesmo espaço em memória, não podendo ser utilizadas simultaneamente Declaração: union <nomeUnião> { <tipo1> <campo1>; [<tipo2> <campo2>; [...] ] } [var1 [, var2 [...]]]; Exemplo: union u_variante { short valor_s; // campo inteiro curto long valor_l; // campo inteiro longo double valor_d; // campo real }; 20/04/2017 (C) 2017, PJANDL. 73
  • 74. C++::DEFINIÇÃO DE TIPOS Para melhorar a legibilidade dos programas é possível que novos tipos sejam criados a partir de outros existentes utilizando-se a palavra reservada typedef com a sintaxe abaixo: typedef <tipoExistente> <nomeNovoTipo>; Exemplos: typedef int integer; typedef int* pInt; typedef double real; typedef unsigned char byte; typedef unsigned long DWORD; 20/04/2017 (C) 2017, PJANDL. 74
  • 75. PARTE IV:: FUNÇÕES C++ 200 UM MINICURSO 20/04/2017 (C) 2017, PJANDL. 75
  • 76. C++::FUNÇÕES Uma função é um segmento de programa independente (subprograma), ou seja, um bloco de diretivas agrupadas ao qual se associa um nome (o identificador de função). Cada função tem uma finalidade específica, realizada por meio de suas diretivas. Para executarmos uma função devemos efetuar uma chamada à função (function call) de qualquer ponto do programa. Uma função:  Pode ser chamada qualquer número de vezes;  Pode receber valores (argumentos) para realizar suas tarefas de maneira customizada;  Pode retornar um valor como resultado de sua execução;  Pode acionar a si mesma (recursão). Programas em C++ podem ser organizados como um conjunto de funções. 20/04/2017 (C) 2017, PJANDL. 76
  • 77. C++::FUNÇÕES Forma geral da definição: tipoRetorno nome (listaParâmetros) corpoFunção Onde:  tipoRetorno especifica o tipo do valor retornado pela função. O default é int; qualquer outro pode ser escolhido; void indica uma função sem valor de retorno.  nome é o identificador da função, usado em seu acionamento (chamada da função).  listaParâmetros relaciona o tipo e nome dos parâmetros opcionalmente recebidos pela função.  corpoFunção é o bloco de código associado. Um trecho de código como segue: int temp; cout << "Digite um valor inteiro: "; cin >> temp; Pode ser convertido numa função como: int leInteiro(char *msg) { int temp; cout << msg; cin >> temp; return temp; } 20/04/2017 (C) 2017, PJANDL. 77
  • 78. C++::FUNÇÕES Ao invés de repetir-se código, o uso de funções não apenas reduz a quantidade de programa a ser escrito, mas melhora sua abstração, facilita sua manutenção e promove o reuso. Observe que a definição da função aparece no código antes de sua utilização (no caso, antes do main). #include <iostream> using namespace std; int LeInteiro(const char *msg) { // definição da função int temp; // declaração var auxiliar cout << msg; // exibe mensagem cin >> temp; // lê valor return temp; // retorna valor lido } int main() { int valor1, valor2; // declaração de variáveis // chamada da função e atribuição do valor retornado valor1 = LeInteiro(“Valor1? "); // chamada da função e atribuição do valor retornado valor2 = LeInteiro(“Valor2? "); // exibe valores lidos cout << “Valor1:” << valor1 << endl << “Valor2:” << valor2 << endl; return 0; // encerramento do programa } 20/04/2017 (C) 2017, PJANDL. 78 Função que retorna tipo primitivo
  • 79. C++::RETORNO DE FUNÇÕES Toda função deve retornar um único valor como seu resultado. Tal valor deve ser do tipo especificado para retorno. O valor de retorno deve ser indicado diretamente através da diretiva return: return expressão; bool EPrimo(long numero) { // laço que percorre as possibilidades de teste for (int div=2; div<=numero/2; div++) { if (numero%div==0) { // verifica se div é divisor // encontrou divisor, número não é primo return false; } } // laço concluído, número dado é primo return true; // retorno do resultado } 20/04/2017 (C) 2017, PJANDL. 79 Função que retorna tipo primitivo
  • 80. C++::DECLARAÇÃO OU PROTOTIPAÇÃO A declaração ou prototipação (function prototype) é a especificação do nome pretendido para uma função, juntamente com seu tipo de retorno e a lista dos tipos de seus argumentos. A declaração não inclui o bloco de código da função e é finalizada por um ponto e vírgula (';'). Exemplos: • int LeInteiro(const char*); • bool EPrimo(long); • double Soma(double, double); • int Procura(const string, char); • void Troca(double*, double*); 20/04/2017 (C) 2017, PJANDL. 80
  • 81. EXEMPLO _FUNCAO2 20/04/2017 (C) 2017, PJANDL. 81 #include <iostream> using namespace std; // declaração das funções bool EPrimo(long); int LeInteiro(const char*); // função principal int main() { // mensagem inicial cout << "Verificacao de numero primon"; // declara var, chama função e atribui valor lido int valor = LeInteiro("Valor inteiro?"); // exibe mensagem contendo resultado de 'EPrimo(long)' cout << "Numero '" << valor << "' " << (EPrimo(valor) ? "e" : "nao e") << " primon"; return 0; // encerramento do programa } bool EPrimo(long numero) { // definição da função EPrimo bool primo = true; // declara e inicia var auxiliar // laço percorre as possibilidades de teste for(int div=2; div<=numero/2; div++) { if (numero%div==0) { // verifica se div é divisor primo = false; // encontra divisor, número não é primo break; // interrompe laço } } // não encontrou divisor, número é primo return primo; // retorno do resultado } int LeInteiro(const char *msg) { // definição da função LeInteiro int temp; // declaração var auxiliar cout << msg; // exibe mensagem cin >> temp; // lê valor return temp; // retorna valor lido } Funções que retornam tipos primitivos
  • 82. EXEMPLO _FUNCAO3 #include <iostream> using namespace std; // declaração da função 'ObtemArranjo(int)' int* ObtemArranjo(int); // função principal int main() { int* arranjo; // ponteiro para arranjo de inteiros const int TAM = 10; // constante para tamanho do arranjo arranjo = ObtemArranjo(TAM); // lê arranjo de tamanho TAM cout << "[ "; // exibe arranjo obtido for (int i=0; i<TAM; i++) { cout << arranjo[i] << " "; } cout << "]n"; delete[] arranjo; // memória alocada é liberada return 0; // encerra programa } // definição da função 'ObtemArranjo(int)' int* ObtemArranjo(int tamanho) { int* tmp = new int[tamanho]; // aloca arranjo dinamicamente for (int i=0; i<tamanho; i++) { // laço para leitura de valores cout << "Valor[" << i << "] ?b"; cin >> tmp[i]; } return tmp; // retorna arranjo } 20/04/2017 (C) 2017, PJANDL. 82 Função que retorna tipo ponteiro
  • 83. C++::PASSAGEM DE PARÂMETROS Passagem de parâmetros por valor Mecanismos mais simples de transferência de argumentos. O valor dos argumentos usados na chamada é copiado para os parâmetros de entrada da função. Se tais parâmetros são alterados na função, a modificação não afeta os argumentos na chamada (passagem unidirecional, sem efeito colateral). Passagem de parâmetros por referência Mecanismos mais sofisticado de transferência de argumentos. O endereço dos argumentos usados na chamada é copiado para os parâmetros de entrada da função. Se tais parâmetros são alterados na função, a modificação afeta os argumentos na chamada (passagem bidirecional, com efeito colateral). 20/04/2017 (C) 2017, PJANDL. 83 Uso de const impede que argumentos passados por referência sejam alterados na função.
  • 84. C++::ARGUMENTOS PARA MAIN() A linguagem C++ admite duas formas para a função principal: // função principal sem argumentos int main() { ... } // função principal com argumentos int main(int argc, char *argv[]) { ... } Na segunda forma, os argumentos são providos pelo sistema operacional em uso e correspondem aos argumentos da linha de comando (dos consoles). 20/04/2017 (C) 2017, PJANDL. 84
  • 85. EXEMPLO _MAIN #include <iostream> using namespace std; // função principal com recebimento de argumentos int main (int argc, char *argv[]) { // exibe mensagem com número de argumentos recebidos cout << "Argumentos recebidos: " << argc << endl; // exibe todos os argumentos recebidos for (int i=0; i<=argc; i++) { cout << i << ": " << argv[i] << endl; } return 0; // encerra o programa } 20/04/2017 (C) 2017, PJANDL. 85
  • 86. C++::ARGUMENTOS DEFAULT Construção conveniente da linguagem C++ que possibilita definir argumentos default para funções, isto é, definir funções onde um ou mais de seus parâmetros tenham valores pré-definidos em sua declaração. Quando um argumento é omitido na chamada da função, é automaticamente usado seu valor default. Isso exige que os argumentos default sejam os últimos das listas de parâmetros das funções. #include <iostream> using namespace std; // declaração da função 'Inc(double&, double)' double Inc (double&, double = 1); int main() { // função principal double valor = 5; cout << "Valor Inicial: " << valor << endl; Inc(valor, 2.4); cout << "Valor+2.4: " << valor << endl; cout << "Valor+1: " << Inc(valor) << endl; return 0; // encerra programa } // definição da função 'Inc(double&, double)' double Inc (double &valor, double incremento) { valor += incremento; // adiciona incremento ao valor return valor; // retorna valor } 20/04/2017 (C) 2017, PJANDL. 86 Função com passagem de parâmetro por referência e argumento default
  • 87. C++::SOBRECARGA DE FUNÇÕES É a possibilidade de existirem várias funções com o mesmo nome dentro de um mesmo espaço declarativo (function overload). Assim, em um mesmo escopo, podem existir funções homônimas desde que possuam diferentes assinaturas (signatures). A assinatura de uma função é a lista dos tipos de seus parâmetros formais na ordem em que foram declarados. Exemplo: double Inc(double&); double Inc(double&,double); double Inc(double*,double); 20/04/2017 (C) 2017, PJANDL. 87
  • 88. EXEMPLO _SOBRECARGA #include <iostream> using namespace std; double Inc (double&); double Inc (double&, double); double Inc (double*, double); int main() { double x = 0; double y = 3; double *w = &y; cout << "x inicial = " << x << endl; Inc(x); cout << "x + 1 = " << x << endl; cout << "y inicial = " << y << endl; cout << "y + 2.8 = " << Inc(y, 2.8) << endl; cout << "y + 1.2 = " << Inc(&y, 1.2) << endl; cout << "y = " << y << endl; Inc(w, 0.5); cout << "y + 0.5 (indireto) = " << y << endl; cout << "x + Inc(y, 0.7) = " << (x + Inc(y, 0.7)) << endl; return 0; } double Inc (double &valor) { valor += 1; return valor; } double Inc (double &valor, double quant) { valor += quant; return valor; } double Inc (double *valor, double quant) { *valor = *valor + quant; return *valor; } 20/04/2017 (C) 2017, PJANDL. 88 Estas duas versões da função poderiam ser substituídas por uma única dotada de argumento default
  • 89. PARTE V:: ORIENTAÇÃO A OBJETOS BÁSICA C++ 200 UM MINICURSO 20/04/2017 (C) 2017, PJANDL. 89
  • 90. ORIENTAÇÃO A OBJETOS Sobre a ideia de objeto: "No sentido mais simples, um objeto é uma coisa ou uma entidade do mundo real." (Jamsa & Klander, 1999) Sobre a orientação a objetos: "...uma forma particular de organizar o desenvolvimento de software como uma coleção de objetos que incorporam tanto uma estrutura de dados como comportamentos." (Rumbaugh, 1991) 20/04/2017 (C) 2017, PJANDL. 90
  • 91. ORIENTAÇÃO A OBJETOS::CARACTERÍSTICAS  Classificação Característica que permite a criação de categorias de objetos (as classes) para facilitar a compreensão do mundo e dos problemas.  Generalização Mecanismo que possibilita o compartilhamento de características entre classes, evitando sua repetição.  Encapsulamento Mecanismo que determina quais elementos de uma classe serão visíveis, permitindo proteger ou restringir o acesso a outros elementos. 20/04/2017 (C) 2017, PJANDL. 91
  • 92. C++::CLASSES Uma classe (class) é um novo tipo de dados que pode ser definido pelo programador para descrever uma entidade real ou abstrata. As classes representam os conceitos fundamentais da aplicação em termos da realidade 'modelada‘ pelo programador. 20/04/2017 (C) 2017, PJANDL. 92 Enquanto uma classe é um modelo, as ocorrências de uma classe são suas instâncias.
  • 93. C++::CLASSES Classes em C++ possuem a seguinte estrutura: class <NomeClasse> { [membros] [EspecificadorDeAcesso: membros] [...] } [ListaDeObjetos]; Os membros de uma classe podem ser basicamente de duas naturezas:  variáveis-membro ou campos da classe são as declarações de variáveis que pertencem à classe e representam seus atributos (características); e  funções-membro ou métodos da classe são as declarações e definições de funções associadas à classe e representam suas operações (comportamentos). Os especificadores de acesso (access specifiers) determinam a visibilidade externa dos membros da classe aos quais se aplicam, indicando como podem ser utilizados. 20/04/2017 (C) 2017, PJANDL. 93
  • 94. C++::CAMPOS Uma classe pode possuir um ou mais atributos, os quais podem ser representados por seus campos ou variáveis-membro. As variáveis-membro podem ser de qualquer tipo pré-definido pela linguagem ou definido pelo programador, ou seja, tipos primitivos, arrays, estruturas, uniões ou objetos de outras classes. Campos que não possuem restrição podem ser declarados com acesso público (public). Nas situações ondem existem restrições aos valores possíveis de um campo, recomenda-se sua declaração com acesso protegido (protected) ou privado (private). 20/04/2017 (C) 2017, PJANDL. 94
  • 95. EXEMPLO _INTEIRO // Inteiro.h class Inteiro { // denom. classe public: // especif. acesso int valor; // variável-membro }; #include <iostream> #include "Inteiro.h" using namespace std; int main() { Inteiro i1, i2; // declaração de objetos Inteiro i1.valor = 5; cout << "i1.valor: " << i1.valor << endl; cout << "Digite um valor inteiro: "; cin >> i2.valor; cout << "i2.valor: " << i2.valor << endl; cout << "i2 " << (i2.valor>i1.valor? "maior" : "menor ou igual") << " que i2" << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 95 Classe simples contendo apenas atributos públicos Instanciação implícita dos objetos da classe indicada Campo público apropriado, pois não há restrição de valores Observe o uso do seletor ‘.’ para acesso aos campos dos objetos
  • 96. EXEMPLO _CAIXA // Caixa.cpp class Caixa { public: // campos públicos // dimensões da caixa double altura, largura, profundidade; // informações para empilhamento double peso; int empilhamento; }; #include <iostream> #include "Caixa.cpp" using namespace std; void LeCaixa(Caixa&); // declaração de função int main() { Caixa cx; // declaração de objeto Caixa LeCaixa(cx); cout << "Dim (LARG x ALT x PROF): " << cx.largura << " x " << cx.altura << " x " << cx.profundidade << "nPeso: " << cx.peso << "nEmpilhamento: " << cx.empilhamento << endl; return 0; } void LeCaixa(Caixa &cx) { // definição de função cout << "Digite as dimensoes da caixa (LARG ALT PROF): "; cin >> cx.largura >> cx.altura >> cx.profundidade; cout << "Digite o peso da caixa: "; cin >> cx.peso; cout << "Digite o empilhamento maximo da caixa: "; cin >> cx.empilhamento; } 20/04/2017 (C) 2017, PJANDL. 96 Classe simples contendo apenas atributos públicos Observe o uso do seletor ‘.’ para acesso aos campos dos objetos
  • 97. C++::MÉTODOS Uma classe também pode possuir uma ou mais operações, as quais podem ser definidas por seus métodos ou funções- membro. As funções-membro podem tomar qualquer número e tipo de parâmetros, retornar qualquer tipo de resultados, afetando (situação mais usual) ou não o estado do objeto. Métodos que permitem a utilização do objeto em geral são declarados com acesso público (public). Métodos destinados a subdivisão interna das responsabilidades do objeto, ou aqueles cujo uso possui restrições que o usuário da classe não necessita conhecer, devem ser declarados com acesso protegido (protected) ou privado (private). 20/04/2017 (C) 2017, PJANDL. 97 É comum que métodos públicos provejam acesso a campos privados (operações de acesso e mutação)
  • 98. EXEMPLO _CAIXA // Caixa-cpp class Caixa { public: // campos públicos // dimensões da caixa double altura, largura, profundidade; // informações para empilhamento double peso; int empilhamento; // declaração de método double volume(); }; double Caixa::volume() { // definição do método return altura*largura*profundidade; } #include <iostream> #include "Caixa.cpp" using namespace std; void LeCaixa(Caixa&); // declaração de função int main() { Caixa cx; // declaração de objeto Caixa LeCaixa(cx); cout << "Dim (LARG x ALT x PROF): " << cx.largura << " x " << cx.altura << " x " << cx.profundidade << "nPeso: " << cx.peso << "nEmpilhamento: " << cx.empilhamento << endl; cout << “Volume: “ << cx.volume() << endl; return 0; } void LeCaixa(Caixa &cx) { // definição de função cout << "Digite as dimensoes da caixa (LARG ALT PROF): "; cin >> cx.largura >> cx.altura >> cx.profundidade; cout << "Digite o peso da caixa: "; cin >> cx.peso; cout << "Digite o empilhamento maximo da caixa: "; cin >> cx.empilhamento; } 20/04/2017 (C) 2017, PJANDL. 98 Classe simples contendo atributos e operações públicos Observe o uso do seletor ‘.’ para acesso à operação do objeto
  • 99. C++::FUNÇÕES INLINE // Caixa-cpp class Caixa { public: // campos públicos // dimensões da caixa double altura, largura, profundidade; // informações para empilhamento double peso; int empilhamento; // declaração implícita de método inline double volume() { return altura*largura*profundidade; } }; Funções podem ser declaradas inline. Se uma função é assim declarada, o compilador substitui cada chamada existente da função por uma cópia de seu código. Com isso o código produzido torna-se mais rápido, apesar de maior. inline int Max(int x, int y) { return (x > y)? x : y; } Funções-membro torna-se implicitamente inline se definidas dentro da declaração da classe. O uso do modificador inline pode ser aplicado à funções comuns ou funções-membro declaradas externamente. 20/04/2017 (C) 2017, PJANDL. 99
  • 100. C++::ACESSIBILIDADE A acessibilidade dos membros de uma classe, também conhecida como encapsulamento ou ocultamento de dados (data hiding), é a forma com que tais elementos podem ser vistos e utilizados externamente, ou seja, pelas instâncias da classe e por outras classes. O encapsulamento auxilia na separação do projeto (design) da implementação (coding), proporcionando facilidades de modificação e padronização do código Em C++ a acessibilidade é definida pelos especificadores de acesso:  public  protected  private 20/04/2017 (C) 2017, PJANDL. 100
  • 101. EXEMPLO _CIRCUNFERENCIA // Circunferencia.h #include <cmath> class Circunferencia { private: double raio; public: void setRaio(double); // mutator double getRaio(); // accessor double area(); double perimetro(); }; void Circunferencia::setRaio(double r) { if (r >= 0) { raio = r; } } double Circunferencia::getRaio() { return raio; } double Circunferencia::area() { return M_PI * pow(raio, 2); } double Circunferencia::perimetro() { return 2 * M_PI * raio; } #include <iostream> #include "Circunferencia.h" using namespace std; int main() { Circunferencia c1; double raio; cout << "Raio? "; cin >> raio; c1.setRaio(raio); cout << "Circunferencianraio: " << c1.getRaio() << "narea: " << c1.area() << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 101 Classe atributo privado e operações de acesso (accessor e mutator)
  • 102. C++::CONSTRUTORES Os objetos das classes também devem ser inicializados de modo que se tornem consistentes e que seja evitado o retorno de valores não esperados. Para a criação de objetos em estados consistentes, podem ser declarados os construtores (constructors), métodos especiais acionados apenas na criação dos objetos das próprias classes, que preparam os objetos para uso, isto é, inicializam apropriadamente seus campos. // Circunferencia.h #include <cmath> class Circunferencia { private: double raio; public: void setRaio(double); double getRaio(); double area(); double perimetro(); Circunferencia(); // construtor default }; Circunferencia::Circunferencia() { raio = 0; } void Circunferencia::setRaio(double r) { if (r >= 0) { raio = r; } } double Circunferencia::getRaio() { return raio; } double Circunferencia::area() { return M_PI * pow(raio, 2); } double Circunferencia::perimetro() { return 2 * M_PI * raio; } 20/04/2017 (C) 2017, PJANDL. 102 Construtores sempre têm o nome da classe e não possuem valor de retorno
  • 103. C++::SOBRECARGA DE MÉTODOS E CONSTRUTORES Métodos e construtores podem ser sobrecarregados, tal como funções. A sobrecarga é possível sempre que a assinatura da operação é diferente. É um mecanismo natural, pois como veremos, os compiladores geram, como padrão, dois construtores: o default e o cópia. class Caixa { public: // campos públicos p/ info. da caixa double altura, largura, profundidade; double peso; int empilhamento; // declaração de métodos double volume() { return altura*largura*profundidade; } void ajustaMedidas(double, double, double, double, int); void ajustaMedidas(double, double, double); void ajustaMedidas(double, int); // declaração de construtores Caixa() { ajustaMedidas(0, 0, 0, 0, 0); } Caixa(double, double, double, double, int); Caixa(double, double, double); Caixa(double, int); Caixa(Caixa &c); }; 20/04/2017 (C) 2017, PJANDL. 103
  • 104. C++::CONSTRUTORES Construtores sem parâmetros são denominados construtores-default, pois são automaticamente acionados na declaração de objetos do tipo:  Circunferencia c1, c2; Construtores parametrizados podem ser acionados por meio da passagem adequada de parâmetros na declaração dos objetos:  Circunferencia c3(2.5), c4(10); // Circunferencia.h #include <cmath> class Circunferencia { private: double raio; public: void setRaio(double); : // construtores Circunferencia(); // default Circunferencia(double); // parametrizado }; Circunferencia::Circunferencia() { raio = 0; } Circunferencia::Circunferencia(double r) { setRaio(r); } void Circunferencia::setRaio(double r) { if (r >= 0) { raio = r; } } : 20/04/2017 (C) 2017, PJANDL. 104 Os construtores default são supridos pelo compilador quando outros não são especificados
  • 105. EXEMPLO _PONTO class Ponto { public: float x, y; // coord. do ponto Ponto(float=0, float=0); // val. default p/ args void translacao(float, float); }; // construtor parametrizado Ponto::Ponto(float x, float y) { translacao(x, y); // uso de método da classe } // ajusta nova coordenada void Ponto::translacao(float x, float y) { Ponto::x = x; // op. escopo diferencia parâmetro Ponto::y = y; } #include <iostream> #include "Ponto.h" using namespace std; int main() { Ponto p1; // declara objeto s/ args. (default) cout << "p1(" << p1.x << "," << p1.y << ")n"; p1.translacao(-5,10);// ajusta coordenadas cout << "p1(" << p1.x << "," << p1.y << ")n"; Ponto p2(5); // declara objeto c/ 1 arg. (x) cout << "p2(" << p2.x << "," << p2.y << ")n"; Ponto p3(100, 50); // declara objeto / 2 args. (x e y) cout << "p3(" << p3.x << "," << p3.y << ")n"; return 0; // encerra programa } 20/04/2017 (C) 2017, PJANDL. 105 Os construtores default com valores default têm comportamento dual: default e parametrizado
  • 106. C++::CONSTRUTORES CÓPIA Classes declaradas sem construtores explícitos fazem que compiladores adicionem dois construtores automaticamente:  Construtor default (sem parâmetros) e  Construtor cópia. O construtor default representa o mecanismo natural de inicialização de objetos, enquanto o construtor cópia é responsável por: 1. realizar a inicialização de objetos a partir de outros objetos do mesmo tipo já existentes; e 2. permitir a passagem de objetos por valor para funções (ou métodos). Exemplo (para classe Ponto): Ponto::Ponto(const Ponto &p) { // copia atributos do x = p.x; y = p.y; // objeto recebido para o novo } 20/04/2017 (C) 2017, PJANDL. 106
  • 107. EXEMPLO _PONTO #include <cmath> class Ponto { public: float x, y; // coord. do ponto Ponto(float = 0, float = 0); // constr default Ponto(const Ponto&); // construtor cópia void translacao(float, float); static float distancia(const Ponto &p1, const Ponto &p2); }; // construtor parametrizado Ponto::Ponto(float x, float y) { translacao(x, y); // uso de método da classe } // construtor cópia Ponto::Ponto(const Ponto &p) { x = p.x; y = p.y; } // ajusta nova coordenada void Ponto::translacao(float x, float y) { Ponto::x = x; // op. escopo diferencia parâmetro Ponto::y = y; } // calcula distância entre pontos float Ponto::distancia(const Ponto &p1, const Ponto &p2) { return sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2)); } 20/04/2017 (C) 2017, PJANDL. 107 Os construtores cópia precisam duplicar adequadamente o objeto Métodos estáticos pertencem à classe e não devem afetar instâncias
  • 108. C++::MEMBROS ESTÁTICOS Membros estáticos, isto é, declarados como static, são elementos especiais de uma classe que não estão associados as suas instâncias e sim a própria classe. Variáveis-membro estáticas existem apenas na classe, e não em suas instâncias, sendo compartilhadas por todos objetos existentes. Funções-membro estáticas, são compartilhados entre as instâncias como métodos comuns, mas utilizam exclusivamente variáveis-membro estáticas, ou seja, se aplicam ao contexto da classe. ImagemExecutável Constantes Código Heap Pilha 20/04/2017 (C) 2017, PJANDL. 108
  • 109. EXEMPLO _ESTATICA #include <cstdlib> #include <iostream> using namespace std; class Estatica { static double fator; // decl. var-membro estática public: static double resultado; // decl. var-membro estática static double cm2pol(double); // decl. func-membro estática }; double Estatica::fator = 2.54; // define var-membro estática double Estatica::resultado = 0; // define var-membro estática double Estatica::cm2pol(double cm) { // define método estático resultado = cm/fator; return resultado; } int main(int argc, char* argv[]) { if (argc>1) { cout << "cm = " << argv[1] << endl; // utiliza método e atributo estáticos cout << "pol = " << Estatica::cm2pol(atof(argv[1])) << endl; cout << "ultimo resultado = " << Estatica::resultado << endl; } else { cout << "Uso: main <valor em cm>n"; } return 0; } 20/04/2017 (C) 2017, PJANDL. 109
  • 110. C++::CONSTRUTORES EXPLÍCITOS Considere a classe abaixo: class Inteiro { public: int valor; // construtor default inline com valor Inteiro(int v=0) { valor = v; } }; Ela permite instanciar objetos com: Inteiro i1; i2(4); Inteiro i3 = 44; // uso implícito de construtor // transforma literal em objeto O uso implícito de construtor é possível quando não existe confusão possível entre os construtores existentes, sendo convertido para: Inteiro i3(44); Se desejado, o uso implícito de construtores pode ser suprimido com uso da palavra reservada explicit: explicit Inteiro(int v=0) { valor = v; } Isso evita que atribuições sejam confundidas com a criação de objetos. 20/04/2017 (C) 2017, PJANDL. 110
  • 111. C++::DESTRUTORES Os construtores são operações especiais que efetuam a inicialização dos objetos. Por outro lado, existem os destrutores (destructors), operações especiais que atuam na remoção dos objetos, permitindo que recursos do sistema tomados na criação sejam devolvidos. Os destrutores devem ser declarados sempre que houver manipulação direta de recursos de memória ou outros, que o compilador não tem condição de detectar e desfazer. Considerando a existência dos construtores e destrutores, percebemos que os objetos possuem um ciclo de vida associado ao escopo onde são declarados. Os destrutores são acionados quando o escopo onde os objetos foram declarados é finalizado. 20/04/2017 (C) 2017, PJANDL. 111
  • 112. EXEMPLO _DINAMICA #include <iostream> using namespace std; class Dinamica { int* valor; // ponteiro para inteiro public: Dinamica(int=0); // construtor parametrizado ~Dinamica(); // destrutor void ajustaValor(int); // ajusta valor do atributo int obtemValor(); // obtém valor do atributo }; Dinamica::Dinamica(int valor) { // construtor parametrizado cout << "Construtorn"; // exibe mensagem Dinamica::valor = new int; // aloca memória dinamicamente *Dinamica::valor = valor; // armazena valor na memória } Dinamica::~Dinamica() { // destrutor cout << "Destrutorn"; // exibe mensagem delete valor; // libera região de memória alocada } void Dinamica::ajustaValor(int v) { *valor = v; } int Dinamica::obtemValor() { return *valor; } int main() { cout << "inicio main()n"; // exibe mensagem Dinamica obj1(10); // declara objeto cout << obj1.obtemValor() << endl; // exibe valor do objeto obj1.ajustaValor(20); // modifica valor do objeto cout << obj1.obtemValor() << endl; // exibe valor do objeto cout << "fim main()n"; // exibe mensagem return 0; // encerra programa } 20/04/2017 (C) 2017, PJANDL. 112 A execução deste programa ilustra o ciclo de vida dos objetos
  • 113. C++::THIS A palavra reservada this representa o endereço do próprio objeto na memória, ou seja, é um ponteiro cujo valor é diferente para cada objeto criado. O ponteiro this é uma auto-referência (self reference). Em toda utilização de campo ou uso de função-membro, implicitamente ocorre o uso de this (exceto para membros estáticos). O uso de this é limitado, pois em geral não é necessário exceto quando:  Deseja-se distinguir entre uma variável local e um campo da classe com a mesma designação (tal como feito pelo operador de resolução de escopo ::); ou  Quando se deseja acesso ao objeto que acionou um método específico; ou  Quando é necessário obter ou retornar um ponteiro (this) ou referência (*this) para o próprio objeto, útil na sobrecarga de operadores. 20/04/2017 (C) 2017, PJANDL. 113
  • 114. EXEMPLO _INTERVALO class Intervalo { double minimo; double maximo; public: Intervalo(double min, double max) { minimo = min; maximo = max; } double valorMinimo() const { return minimo; } double valorMaximo() const { return maximo; } bool pertence(double v) const { return v >= valorMinimo() && v <= valorMaximo(); } }; this->minimo = min; this->maximo = max; return this->minimo; return this->maximo; return v >= this->valorMinimo() && v <= this->valorMaximo(); 20/04/2017 (C) 2017, PJANDL. 114 Uso explícito de thisUso implícito de this
  • 115. PARTE VI:: ORIENTAÇÃO A OBJETOS INTERMEDIÁRIA C++ 200 UM MINICURSO 20/04/2017 (C) 2017, PJANDL. 115
  • 116. C++::FUNÇÕES AMIGAS Uma função não-membro de uma classe pode receber o status de amiga (friend), o que possibilita seu acesso aos membros protegidos e privados, além dos públicos cujo acesso é padrão. Embora tal ação viole o encapsulamento pretendido pela classe, é alternativa viável na sobrecarga de operadores, além de facilitar a criação de funções destinadas a entrada/saída. Seu uso deve ser feito com cautela! class NomeClasse { // membros privados e protegidos public: friend <tipo> funcao([paramList]); : }; // implementação da função-amiga // que *não* é membro da classe! <tipo> funcao([paramList]) { } 20/04/2017 (C) 2017, PJANDL. 116
  • 117. EXEMPLO _INTERVALO class Intervalo { double minimo; double maximo; public: Intervalo(double min, double max) { minimo = min; maximo = max; } double valorMinimo() const { return minimo; } double valorMaximo() const { return maximo; } bool pertence(double v) const { return v>=minimo && v<=maximo; } friend bool contem(const Intervalo &, const Intervalo &); }; bool contem(const Intervalo &a, const Intervalo &b) { return b.minimo>=a.minimo && b.maximo<=a.maximo; } #include <iostream> #include "intervalo.h" using namespace std; int main() { Intervalo A(-5, 12), B(7, 10), C(5, 15); cout << "A" << (contem(A, B) ? " " : " nao ") << "contem Bn"; cout << "A" << (contem(A, C) ? " " : " nao ") << "contem Cn"; cout << "C" << (contem(C, B) ? " " : " nao ") << "contem Bn"; return 0; } 20/04/2017 (C) 2017, PJANDL. 117 Uso de função amiga
  • 118. C++::CLASSES AMIGAS Também é possível a existência de classes amigas, que, como para as funções amigas, também terão acesso a membros privados e protegidos em função da relação de amizade estabelecida. Novamente existe a situação de cautela exigida pela violação conceitual do encapsulamento. // Colecao.h #ifndef _COLECAO_H_ #define _COLECAO_H_ class Iterator; // definição da classe Iterator class Colecao { // declaração da classe Colecao int *v, tam, prox; public: Colecao(int=10); // construtor ~Colecao(); // destrutor bool adiciona(int); // adiciona um elemento int tamanho() const; // determina tamanho da coleção int le(int) const; // obtém um elemento da coleção void limpar(); // limpa coleção friend class Iterator; // especifica classe amiga }; class Iterator { // declaração da classe Iterator int *v, tam, prox; public: Iterator(const Colecao&); // construtor bool existeProximo() const; // verifica se existem mais elementos int proximo(); // retorna próximo elemento }; #endif 20/04/2017 (C) 2017, PJANDL. 118 Este exemplo também mostra a correta organização do programa em múltiplos arquivos de cabeçalho (header) e código-fonte (source).
  • 119. EXEMPLO _COLECAO // Colecao.cpp #include "Colecao.h" Colecao::Colecao(int t) { tam = t; v = new int[tam]; prox = 0; } Colecao::~Colecao() { delete[] v; } bool Colecao::adiciona(int valor) { if (prox<tam) { v[prox++] = valor; return true; } return false; } int Colecao::tamanho() const { return tam; }; int Colecao::le(int pos) const { return v[pos]; }; void Colecao::limpar() { prox=0; } Iterator::Iterator(const Colecao &c) { v = c.v; tam = c.prox; prox = 0; } bool Iterator::existeProximo() const { return prox<tam; } int Iterator::proximo() { if (prox<tam) return v[prox++]; return 0; } #include <iostream> #include "Colecao.h" using namespace std; void listaColecao(const Colecao &c) { Iterator it(c); // cria Iterator para Colecao // lista elementos da Colecao através do Iterator cout << "Colecao [ "; while(it.existeProximo()) cout << it.proximo() << " "; cout << "]n"; } int main() { Colecao c; // cria Colecao e adiciona elementos for (int i=0; i<c.tamanho(); i++) c.adiciona(i); listaColecao(c); // lista Colecao c.limpar(); // limpa Colecao listaColecao(c); // lista Colecao return 0; } 20/04/2017 (C) 2017, PJANDL. 119
  • 120. C++::SOBRECARGA DE OPERADORES Operadores disponíveis em C++ permitem realizar operações sobre tipos de dados pré-definidos. C++ permite redefinir a função de muitos de seus operadores, possibilitando seu uso para outros tipos de dados, ou seja, a sobrecarga de operadores (operator overload). Sintaxe: <Tipo> operator <sinal> (<parâmetros>); Isto permite a construção de uma sintaxe mais rica para os novos tipos definidos para o programador. Os operadores sobrecarregáveis são: 20/04/2017 (C) 2017, PJANDL. 120 + - * / % ++ -- < <= > >= == != && || ! & | ~ ^ >> << += -= *= /= %= &= |= ^= >>= <<= , ( ) [ ] = -> ->* new delete
  • 121. EXEMPLO _PONTO #include <iostream> using namespace std; class Ponto { public: float x, y; Ponto(float xi=0, float yi=0) { x = xi; y = yi; } Ponto operator+(Ponto p) { // oper. sobrecarregado Ponto tmp; // declara objeto aux tmp.x = x + p.x; // soma x obj + param tmp.y = y + p.y; // soma y obj + param return tmp; // retorna objeto aux } }; int main() { Ponto p1, p2; // declara objetos Ponto cout << "Digite uma coordenada (x,y): "; cin >> p1.x >> p1.y; // lê coord de ponto 1 cout << "Digite outra coordenada (x,y): "; cin >> p2.x >> p2.y; // lê coord de ponto 2 // soma coordenadas Ponto p3 = p1 + p2; // exibe resultado e encerra programa cout << "Coordenada final: (" << p3.x << ", “ << p3.y << ")n"; return 0; } 20/04/2017 (C) 2017, PJANDL. 121 Uso de sobrecarga de operador
  • 122. C++::SOBRECARGA DE OPERADORES Sobrecarga de operadores possibilita simplificação do programa: Ponto p3 = p1 + p2; O uso da sobrecarga é equivalente à: Ponto p3 = p1.operator+(p2); Uma classe pode possui várias operações sobrecarregadas: Ponto operator-(Ponto p) { Ponto tmp; tmp.x = x - p.x; tmp.y = y - p.y; return tmp; } Quando corretamente implementada, a sobrecarga permite o encadeamento de operações: Ponto p = p1 + p2 + p3 + p4; Que equivale à: Ponto p = p1.operator+(p2.operator+(p3.operator+(p4))); 20/04/2017 (C) 2017, PJANDL. 122
  • 123. EXEMPLO _FRACAO // Fracao.h #ifndef _FRACAO_H_ #define _FRACAO_H_ #include <iostream> using namespace std; class Fracao { int Numerador, Denominador; void reduzir(); public: Fracao (const int=1, const int=1); Fracao (const Fracao &); int numerador() const; int denominador() const; Fracao operator+ (const Fracao &); Fracao operator- (const Fracao &); Fracao operator+ (const int); Fracao operator- (const int); friend istream& operator>> (istream &, Fracao &); friend ostream& operator<< (ostream &, const Fracao &); }; #endif // Fracao.cpp #include "Fracao.h" Fracao::Fracao(const int n, const int d) { Numerador = n; Denominador = d!=0 ? d : 1; reduzir(); } Fracao::Fracao(const Fracao &f) { Numerador = f.Numerador; Denominador = f.Denominador; } int Fracao::numerador() const { return Numerador; } int Fracao::denominador() const { return Denominador; } Fracao Fracao::operator+ (const Fracao &f) { Fracao tmp; tmp.Numerador = Numerador*f.Denominador + f.Numerador*Denominador; tmp.Denominador = Denominador * f.Denominador; tmp.reduzir(); return tmp; } Fracao Fracao::operator- (const Fracao &f) { Fracao tmp; tmp.Numerador = Numerador*f.Denominador - f.Numerador*Denominador; tmp.Denominador = Denominador * f.Denominador; tmp.reduzir(); return tmp; } 20/04/2017 (C) 2017, PJANDL. 123 Uso de sobrecarga de operadores e funções amigas
  • 124. EXEMPLO _FRACAO Fracao Fracao::operator+ (const int i) { Fracao tmp(i/1); return operator+(tmp); } Fracao Fracao::operator- (const int i) { Fracao tmp(i/1); return operator-(tmp); } istream& operator>>(istream& stream, Fracao &f) { stream >> f.Numerador >> f.Denominador; f.reduzir(); return stream; } ostream& operator<<(ostream& stream, const Fracao &f) { stream << f.Numerador; if (f.Denominador!=1) stream << "/" << f.Denominador; return stream; } void Fracao::reduzir() { int a, b, sinal = 1, resto; if (Numerador==0) Denominador = 1; if (Numerador<0 && Denominador<0) { Numerador = -Numerador; Denominador = - Denominador; } else if (Numerador<0) { Numerador = - Numerador; sinal = -1; } else if (Denominador<0) { Denominador = - Denominador; sinal = -1; } if (Numerador<Denominador) { a = Numerador; b = Denominador; } else { a = Denominador; b = Numerador; } while (b!=0) { resto = a % b; a = b; b = resto; } Numerador /= a*sinal; Denominador /= a; } 20/04/2017 (C) 2017, PJANDL. 124
  • 125. EXEMPLO _FRACAO #include "Fracao.h" #include <iostream> using namespace std; int main() { Fracao f1, f2, f3; cout << "Digite 1a. fracao (nun den): "; cin >> f1; cout << "Digite 2a. fracao (nun den): "; cin >> f2; cout << "Soma de Fracoesn"; f3 = f1 + f2; cout << f1 << " + " << f2 << " = " << f3 << endl; cout << "Subtracao de Fracoesn"; f3 = f1 - f2; cout << f1 << " - " << f2 << " = " << f3 << endl; cout << "Soma de Fracao e inteiron"; f3 = f1 + 1; cout << f1 << " + 1 = " << f3 << endl; cout << "Subtracao de Fracao e inteiron"; f3 = f1 - 1; cout << f1 << " - 1 = " << f3 << endl; return 0; } Exemplos de uso de Fracao: Fracao f1(1/4), f2(3/6), f3(4/5); Fracao f4 = f1 + f2 + f3; f4 = f4 + 1; Fracao f5 = f1 – f2 – f3; f5 = f4 – 3; 20/04/2017 (C) 2017, PJANDL. 125
  • 126. C++::HERANÇA A herança (inheritance) é uma das formas mais importantes do polimorfismo e pode ser entendida como uma técnica para que uma classe passe a utilizar atributos e operações definidas em uma outra classe, ou seja, compartilhe uma parcela de sua implementação. C++ oferece tanto a herança simples, como a herança múltipla. Em geral, podemos perceber que existe uma relação de herança entre duas classes quando a pergunta 'é um(a)?' é respondida afirmativamente. Sintaxe da herança simples: class <NomeClasseDerivada> : [especificadorAcesso] <NomeClasseBase> { // corpo da classe derivada }; 20/04/2017 (C) 2017, PJANDL. 126
  • 127. EXEMPLO // Base.h class Base { private: int a; protected: int b; public: void ajustaAB(int na, int nb) { a = na; b = nb; } int leA() { return a; } int leB() { return b; } }; #include <iostream> #include "Base.h" using namesapce std; int main() { Base obj; cout << obj.leA() << "," << obj.leB() << endl; obj.ajustaAB(5, -2); cout << obj.leA() << "," << obj.leB() << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 127
  • 128. EXEMPLO // Derivada1.h #include "Base.h" class Derivada1: public Base { private: int c; public: void deslocar() { int tmp = leA(); ajustaAB(b, c); c = tmp; } void ajustaC(int nc) { c = nc; } int leC() { return c; } }; #include <iostream> #include "Derivada1.h" using namespace std; main() { Derivada1 obj; cout << obj.leA() << "," << obj.leB() << ",“ << obj.leC() << endl; obj.ajustaAB(2, 4); obj.ajustaC(6); cout << obj.leA() << "," << obj.leB() << ",“ << obj.leC() << endl; obj.deslocar(); cout << obj.leA() << "," << obj.leB() << "," << obj.leC() << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 128
  • 129. C++::HERANÇA A herança pública é uma situação comum em projetos C++, mas também pode ser especificada diferentemente. Na herança pública, a implementação da própria subclasse e de suas subclasses têm acesso aos membros herdados públicos e protegidos; já as instâncias destas subclasses têm acesso somente aos membros herdados públicos. Na herança privada apenas a implementação da própria subclasse tem acesso aos membros herdados públicos e protegidos. Nem as instâncias desta subclasse nem suas subclasses poderão utilizar os membros herdados. 20/04/2017 (C) 2017, PJANDL. 129
  • 130. C++::HERANÇA MÚLTIPLA A herança múltipla resolve as questões de quando uma nova classe possui relacionamento com várias outras, pois permite que sejam criadas novas classes que compartilhem as características de duas ou mais classes base simultaneamente. Sintaxe para herança múltipla: class <NomeClasseDerivada> : [especificadorAcesso1] <NomeClasseBase1>, [especificadorAcesso2] <NomeClasseBase2>, : [especificadorAcessoN] <NomeClasseBaseN> { // corpo da classe derivada }; 20/04/2017 (C) 2017, PJANDL. 130
  • 131. EXEMPLO // Func.h #ifndef _FUNC #define _FUNC #include <iostream> using namespace std; class Funcionario { long id; public: Funcionario(long nid) { id = nid; cout << "Construtor Funcionario: " << nid << endl; } ~Funcionario() { cout << "Destrutor Funcionarion"; } long getId() { return id; } }; ostream& operator<<(ostream &out, Funcionario &f) { return out << "Funcionario[" << f.getId() << "]"; } class Temporario { int periodo; public: Temporario(int p) { cout << "Construtor Temporario: " << p << endl; periodo = p; } ~Temporario() { cout << "Destrutor Temporarion"; } int getPeriodo() { return periodo; } }; ostream& operator<<(ostream &out, Temporario &t) { return out << "Temporario(" << t.getPeriodo() << "d)"; } 20/04/2017 (C) 2017, PJANDL. 131 Observe a existência apenas de construtores parametrizados. Observe o uso da sobrecarga de operadores.
  • 132. EXEMPLO class Engenheiro: public Funcionario { public: Engenheiro(long nid): Funcionario(nid) { cout << "Construtor Engenheiro: " << nid << endl; } ~Engenheiro() { cout << "Destrutor Engenheiron"; } }; ostream& operator<<(ostream &out, Engenheiro &e) { return out << "Engenheiro[" << e.getId() << "]"; } class Estagiario: public Funcionario, public Temporario { public: Estagiario(long nid, int p): Funcionario(nid), Temporario(p) { cout << "Construtor Estagiario: " << nid << ",“ << p << endl; } ~Estagiario() { cout << "Destrutor Estagiarion"; } }; ostream& operator<<(ostream &out, Estagiario &e) { return out << "Estagiario[" << e.getId() << "]"; } #endif 20/04/2017 (C) 2017, PJANDL. 132 Observe como os parâmetros dos construtores das superclasses foram supridos.
  • 133. EXEMPLO #include <iostream> #include "Func.h" using namespace std; int main() { cout << "Criando objeto Engenheiron"; Engenheiro eng(12345); cout << "Criando objeto Estagiarion"; Estagiario est(67890, 90); return 0; // destrói objetos implicitamente } A execução deste programa demonstra a passagem de parâmetros para as superclasses envolvidas. 20/04/2017 (C) 2017, PJANDL. 133
  • 134. C++::POLIMORFISMO O polimorfismo permite:  a sobrecarga de funções e operadores, obtida em tempo de compilação (isto é, implementadas diretamente) no código e  também possibilita explorar a herança e funções virtuais para manipulação genérica de classes em tempo de execução As classes Engenheiro e Estagiario podem ter objetos declarados assim:  Engenheiro eng(1111);  Estagiario estag(2222, 60); Como ambos são derivados da classe Funcionario é possível simplesmente atribuir seus endereços a ponteiros do tipo da superclasse:  Funcionario *func1 = &eng;  Funcionario *func2 = &estag; 20/04/2017 (C) 2017, PJANDL. 134
  • 135. EXEMPLO #include <iostream> #include "Func.h“ using namespace std; // função genérica baseada em referência void informacao(Funcionario &f) { cout << f << endl; } // função genérica baseada em ponteiro void mostraId(Funcionario *f) { cout << "Id: " << f->getId() << endl; } int main() { Engenheiro eng(1111); Estagiario estag(2222, 60); Engenheiro &e = eng; cout << eng << endl; // exibição de dados originais cout << estag << endl; informacao(e); // usa função genérica c/ referências informacao(estag); // declaraçao de ponteiros tipo Funcionario (genericos) Funcionario *func1 = &eng; Funcionario *func2 = &estag; Funcionario *func3 = &e; mostraId(func1); // usa função genérica c/ ponteiros mostraId(func2); mostraId(func3); return 0; } 20/04/2017 (C) 2017, PJANDL. 135
  • 136. PARTE VII:: ORIENTAÇÃO A OBJETOS AVANÇADA C++ 200 UM MINICURSO 20/04/2017 (C) 2017, PJANDL. 136
  • 137. C++::FUNÇÕES VIRTUAIS Uma subclasse pode substituir uma método existente em sua superclasse (sobreposição ou method override). Devido o polimorfismo, o método chamado (da superclasse ou da subclasse) depende do tipo de ponteiro ou referência usada. Mas nem sempre o efeito produzido é o desejado. Nestes casos pode-se lançar mão das funções virtuais. Funções virtuais são marcadas com o modificador virtual. Observe nos próximo exemplos o efeito do modificador virtual, assim como o fato de ser hereditário. 20/04/2017 (C) 2017, PJANDL. 137
  • 138. EXEMPLO #include <iostream> using namespace std; class ValorSimples { public: int v_valor; ValorSimples(int v=0) { v_valor = v; } int valor() { return v_valor; } }; class ValorDuplo: public ValorSimples { public: ValorDuplo(int v=0): ValorSimples(v) { }; int valor() { return 2*v_valor; } }; int main() { ValorSimples vs(5); // declara obj ValorSimples ValorDuplo vd(5); // declara obj ValorDuplo ValorSimples *pvs; // declara ponteiro ValorSimples pvs = &vs; // obtém endereço obj ValorSimples cout << "obj. ValorSimples via pont. ValorSimples: " << pvs->valor() << endl; pvs = &vd; // obtém endereço obj ValorDuplo cout << "obj. ValorDuplo via pont. ValorSimples: " << pvs->valor() << endl; ValorDuplo *pvd = &vd; // declara pont. ValorDuplo cout << "obj. ValorDuplo via pont. ValorDuplo : " << pvd->valor() << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 138 Sem o uso de funções virtuais
  • 139. EXEMPLO #include <iostream> using namespace std; class ValorSimples { public: int v_valor; ValorSimples(int v=0) { v_valor = v; } virtual int valor() { return v_valor; } // função virtual }; class ValorDuplo: public ValorSimples { public: ValorDuplo(int v=0): ValorSimples(v) { }; int valor() { return 2*v_valor; } // func virtual herdada }; int main() { ValorSimples vs(5); // declara obj ValorSimples ValorDuplo vd(5); // declara obj ValorDuplo ValorSimples *pvs; // declara ponteiro ValorSimples pvs = &vs; // obtém endereço obj ValorSimples cout << "obj. ValorSimples via pont. ValorSimples: " << pvs->valor() << endl; pvs = &vd; // obtém endereço obj ValorDuplo cout << "obj. ValorDuplo via pont. ValorSimples: " << pvs->valor() << endl; ValorDuplo *pvd = &vd; // declara pont. ValorDuplo cout << "obj. ValorDuplo via pont. ValorDuplo : " << pvd->valor() << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 139 Com o uso de funções virtuais Classe ValorDuplo e função main() não foram alteradas
  • 140. C++::FUNÇÕES VIRTUAIS PURAS Uma função-membro virtual pura é aquela que não possui definição numa classe, obrigando que suas subclasses realizem tal definição. Para indicar que uma função-membro é 'puramente virtual' (pure virtual) devemos declará-la como: virtual <tipo> nomeFunc([listaParam]) = 0; Classes contendo métodos virtuais puros são consideradas classes abstratas (abstract classes), pois como sua implementação está incompleta, não podem ser instanciadas. 20/04/2017 (C) 2017, PJANDL. 140
  • 141. EXEMPLO // Comp.h #ifndef _COMPONENTE #define _COMPONENTE #include <iostream> #include <string> class Componente { string descr; // descrição do componente int id; // id do componente Componente *pai; // componente pai public: Componente(int n) { id = n; defineDescr("Componente"); pai = NULL; } void defineDescr(const string d) { descr = d; } string obtemDescr() const { return descr; } unsigned int obtemId() const { return id; } void definePai(Componente *c) { pai = c; } Componente *obtemPai() const { return pai; } virtual void draw()=0; }; 20/04/2017 (C) 2017, PJANDL. 141
  • 142. EXEMPLO class Rotulo: public Componente { public: Rotulo(int n): Componente(n) { defineDescr("Rotulo"); } void draw() { cout << obtemDescr() << obtemId(); } }; class Botao: public Componente { public: Botao(int n): Componente(n) { defineDescr("Botao"); } void draw() { cout << obtemDescr() << obtemId(); } void click() { /* processamento específico */} }; class Container: public Componente { Componente *comps[10]; int quant; public: Container(int n): Componente(n) { defineDescr("Container"); quant = 0; } void adicionar(Componente *c) { c->definePai(this); // registro de paternidade if (quant<10) { comps[quant++] = c; } } int componentes() const { return quant; } void draw() { // desenha comps contidos no container cout << obtemDescr() << obtemId() << " [ "; for (int i=0; i<quant; i++) { comps[i]->draw(); cout << " "; } cout << "]"; } }; #endif 20/04/2017 (C) 2017, PJANDL. 142
  • 143. EXEMPLO #include <iostream> #include "Comp.h“ using namespace std; int main() { int id = 0; cout << "Cria 1o. containern"; Container c1(id++); c1.draw(); cout << "nAdiciona comps 1o. containern"; c1.adicionar(new Botao(id++)); c1.adicionar(new Botao(id++)); c1.adicionar(new Rotulo(id++)); c1.draw(); cout << "nCria 2o. containern"; Container c2(id++); c2.draw(); cout << "nAdiciona comps 2o. containern"; c2.adicionar(new Rotulo(id++)); c2.adicionar(new Botao(id++)); c2.adicionar(new Rotulo(id++)); c2.adicionar(&c1); c2.draw(); cout << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 143
  • 144. C++::NAMESPACES Um namespace é um bloco de escopo denominado ou um espaço declarativo identificado (ANSI, 1989), cujas definições permitem agrupar conjuntos de classes, objetos e funções sob um nome. Na prática, os namespaces dividem o escopo global em escopos menores. Sintaxe: namespace identificador { // bloco do sub-escopo (ou do namespace) } Exemplo: namespace IC { long a; double b; int func (int) { ... } } 20/04/2017 (C) 2017, PJANDL. 144
  • 145. EXEMPLO _NAMESPACES #include <iostream> using namespace std; namespace NS1 { long a; long dobro(long a) { return 2*a; } } namespace NS2 { double a; double dobro(double a) { return 2*a; } } int main() { cout << "2 * 2 = " << NS1::dobro(2) << endl; cout << "1.5 * 2 = " << NS2::dobro(1.5) << endl; NS1::a = 10; NS2::a = 4.5; cout << NS1::a << " * 2 = " << NS1::dobro(NS1::a) << endl; cout << NS2::a << " * 2 = " << NS2::dobro(NS2::a) << endl; cout << NS1::a << " * 2 = " << NS2::dobro(NS1::a) << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 145
  • 146. C++::TEMPLATES O mecanismo de construção dos templates (ou modelos) em C++ permite que um tipo (primitivo ou classe) seja empregado como parâmetro na definição de uma função, ou classe, ou mesmo outro modelo. Os templates possibilitam criar funções e classes capazes de realizar suas operações com tipos distintos de dados sem o emprego da sobrecarga, ou seja, preservando a lógica interna e mantendo-se genérica em relação aos tipos de dados manipulados. Sintaxe: template <classId1 [, classId2 ...]> declaraçãoDaFunção; template <classId1 [, classid2 ...]> declaraçãoDaClasse; Exemplo: template <class Tipo> Tipo Minimo (Tipo x, Tipo y) { Tipo resultado = x > y ? x : y; return resultado; } 20/04/2017 (C) 2017, PJANDL. 146
  • 147. EXEMPLO _TEMPLATES #include <iostream> using namespace std; template <class T> T Minimo (T x, T y) { T resultado = x < y ? x : y; return resultado; } int main() { int a = 1, b = 2; long c = 1029, d = -10; double e = 2.34e10, f = 0.23e-2; int r1 = Minimo<int>(a, b); long r2 = Minimo(c, d); cout << "Minimo(" << a << ", " << b << ")= " << r1 << endl; cout << "Minimo(" << c << ", " << d << ")= " << r2 << endl; cout << "Minimo(" << e << ", " << f << ")= " << Minimo(e, f) << endl; return 0; } 20/04/2017 (C) 2017, PJANDL. 147