linguagem de programação iwiki.cbatista.net/lib/exe/fetch.php/lpi-cppemodelagemoo_pt2.pdf ·...
TRANSCRIPT
C++ePOO
• AmbientesdedesenvolvimentoC++• FundamentaçãodeOrientaçãoaObjetos(OO).
• ModelagemdesistemasorientadaaobjetosusandoC++
• Modelagemdesistemasorientadaaobjetos.
2
OrientaçãoaObjetos
• Análiseeprojetoorientadosaobjetos=decomposiçãoorientadaaobjetosdeumsistemadesoLware
• Coisas/en)dadesquecompõemosistema=objetos
• Objetossãoinstânciasdeclasses• Análiseestruturada=foconosprocedimentos
OrientaçãoaObjetos
• OqueéumObjeto(emlinguagenscomoC++)– Éumavariávelque• Armazenadadosestruturados(comoTADs)• Possuioperações(funções)associadas
• Objetos– Atributos• Dados
– Métodos• Funções
OrientaçãoaObjetos
• ProgramaescritoemlinguagemOO– Conjuntodeobjetosquesecomunicamatravésdemensagensparaaresoluçãodoproblemaabordado(requisitosfuncionais)
• Mensagens– Chamadasafunçõesquepertencemaumobjetoespecífico
• Classessãoos6posdosobjetos
5
OrientaçãoaObjetos
• Classes– Definemcaracterís6cascomunsdosobjetos
• Estadosdosobjetos– Valoresdosatributosindividuais
• Cadaobjetopertenceaumaclasse,quedefineseucomportamentoesuascaracterís6cas
• Conjuntodemétodosdeumobjeto=interface– Encapsulamentodefineavisibilidade
6
Herança
• Hierarquiadeclasses• Classesmaisespecializadasherdamdasmaisgenéricas
• Atributosemétodossãoherdados• Classefilhaéum“6pode”ClassePai
7
Herança
8
class Animal {int idade;
public:Animal(int id) :idade(id) {}void come();void dorme();
};class Ave: public Animal {
string nome;public:
Ave(int, const string&);void voa();void botaOvo();
};
Herança
9
int main() { Ave A(2, “Patativa”); Animal B(3); A.come(); A.dorme(); B.come(); B.dorme(); A.voa(); A.botaOvo();
}
Herança
10
class Animal { int idade;
public: Animal(int id) :idade(id) {} void come(); void dorme();
}; class Ave: public Animal {
string nome; public:
Ave(int, const string&); void dorme();
};
Herança
11
int main() { Ave A(2, “Patativa”); Animal B(3); A.come(); // chama Animal::come() A.dorme(); // chama Ave::dorme() B.come(); // Animal::come() B.dorme(); // Animal::dorme()
}
Aninhamentodeclasses
12
#ifndef CWINDOW_H #define CWINDOW_H class CWindow { class Canvas {
COLORREF textColor; COLORREF lineColor; // etc ... public: void setTextColor (COLORREF newColor);
}; int x, y; // Posição na tela int cx, cy ; // Largura e altura Canvas* my_canvas; public: ... int setTextColor(COLORREF cor); int textOut(int x, int y, char* text); // Texto em x,y }; #endif // CWINDOW_H
Aninhamentodeclasses
13
#include ”CWindow.h” void CWindow::setTextColor (COLORREF cor) {
my_canvas->setTextColor(cor); } void CWindow::Canvas::setTextColor (COLORREF newColor) {
textColor = newColor; }
Ciclodevidadeobjetos
• C++oferecemecanismosparaautoma6zarainicializaçãoeafinalizaçãodeobjetos– Alocaçãoeliberaçãodosrecursos– Métodosconstrutoresedestrutores
14
Ciclodevidadeobjetos
• Métodosconstrutores– Mesmonomedaclasse– Chamadaautomá6canadeclaração– Podereceberparâmetros• Polimorfismoseaplica
15
Ciclodevidadeobjetos
16
class CoisaX { int i; public: CoisaX();
}; void f() {
CoisaX a; }
Ciclodevidadeobjetos
17
class Pessoa { int idade; public: Pessoa(int i);
}; Pessoa::Pessoa(int i) {
idade = i; } void f() {
Pessoa a(18); // ... }
Ciclodevidadeobjetos
• Métododestrutor– Funçãochamadasemprequeoescopodeumobjetoseencerra
– Cadaclassesópodeterummétododestrutor– Métododestrutornãorecebeparâmetros• Nemretornanada
18
class Coisa { public: ~Coisa();
};
Ciclodevidadeobjetos
19
class Pessoa { int idade;
public: Pessoa(int i); // Constructor ~Pessoa();// Destructor void setIdade(int i); int getIdade();
}; Pessoa::Pessoa(int i) {
idade = i; } Pessoa::~Pessoa() {
cout << "Destrutor" << endl; } void Pessoa::setIdade(int i) {
idade = i; } int Pessoa::getIdade() {
return idade; }
Ciclodevidadeobjetos
20
int main() { cout << "Escopo externo" << endl; { Pessoa p(35); cout << "Criou um objeto" << endl; cout << "Idade: "<< p.getIdade() << endl; } cout << "Escopo externo 2" << endl;
} // O que é exibido na tela?
Ciclodevidadeobjetos
21
class Y { int i;
}; class X {
int i; X(int k);
}; Y a, b, c[4]; // OK, existe construtor default na classe Y X d(3); // OK X e, f[3]; // Erro! não existe construtor default para X
Sobrecargadefunções
• EmC– Funçõesdiferentespara6posdiferentes
• EmC++– Sobrecarga(polimorfismoad-hoc)– Atravésdadefiniçãodaassinatura(parâmetros)
22
int escalar_int(int[],int[],int); float escalar_float(float[],float[],int);
int escalar(int[],int[],int); float escalar(float[],float[],int);
Sobrecargadefunções
23
class Ponto { private:
int x, y; public:
Ponto(); Ponto(int, int);
}; Ponto::Ponto(int xx, int yy) {
x = xx; y = yy;
} Ponto::Ponto() {
x = 0; y = 0;
}
Sobrecargadefunções
24
int main() {
Ponto A, B(3, 4); Ponto *p = new Ponto(3, 4); Ponto *p1 = new Ponto; Ponto Vpoints[10];
...}
Sobrecargadefunções
25
class Ponto { private:
int x, y; public:
Ponto(int = 0, int = 0); //Valores default }; Ponto::Ponto(int xx, int yy) {
x = xx; y = yy;
}
Constantes
• const• constversus#define– consttem6po(podesertestadopelocompilador)
• Iniciadanadeclaração
26
class X { const int i = 10; const int j = i + 10;
public:
X(int ii); void f() const;
}; //... const X a;
Constantes
27
class X { const int i; // atributo constante
public: X(int ii);
// etc ... }; X::X(int ii) {
i = ii; } // Não pode, pois i é constante X::X(int ii) : i(ii) {} // OK!
Inicialização
28
class B { int t;
public: B (int tt);
}; B::B(int tt) : t(tt) {} class C {
const int size; B b;
public: C( int sz, int bt );
}; C::C(int sz, int bt) :
size(sz), b(bt) { }
Ciclodevidadeobjetos
• C++oferecemecanismosparaautoma6zarainicializaçãoeafinalizaçãodeobjetos– Alocaçãoeliberaçãodosrecursos– Métodosconstrutoresedestrutores
29
Ciclodevidadeobjetos
• Métodosconstrutores– Mesmonomedaclasse– Chamadaautomá6canadeclaração– Podereceberparâmetros• Polimorfismoseaplica
30
Ciclodevidadeobjetos
31
class CoisaX { int i; public: CoisaX();
}; void f() {
CoisaX a; }
Ciclodevidadeobjetos
32
class Pessoa { int idade; public: Pessoa(int i);
}; Pessoa::Pessoa(int i) {
idade = i; } void f() {
Pessoa a(18); // ... }
Ciclodevidadeobjetos
• Métododestrutor– Funçãochamadasemprequeoescopodeumobjetoseencerra
– Cadaclassesópodeterummétododestrutor– Métododestrutornãorecebeparâmetros• Nemretornanada
33
class Coisa { public: ~Coisa();
};
Ciclodevidadeobjetos
34
class Pessoa { int idade;
public: Pessoa(int i); // Constructor ~Pessoa();// Destructor void setIdade(int i); int getIdade();
}; Pessoa::Pessoa(int i) {
idade = i; } Pessoa::~Pessoa() {
cout << "Destrutor" << endl; } void Pessoa::setIdade(int i) {
idade = i; } int Pessoa::getIdade() {
return idade; }
Sobrecargadefunções
35
class Ponto { private:
int x, y; public:
Ponto(); Ponto(int, int);
}; Ponto::Ponto(int xx, int yy) {
x = xx; y = yy;
} Ponto::Ponto() {
x = 0; y = 0;
}
Sobrecargadefunções
36
int main() {
Ponto A, B(3, 4); Ponto *p = new Ponto(3, 4); Ponto *p1 = new Ponto; Ponto Vpoints[10];
...}
Sobrecargadefunções
37
class Ponto { private:
int x, y; public:
Ponto(int = 0, int = 0); //Valores default }; Ponto::Ponto(int xx, int yy) {
x = xx; y = yy;
}
Variáveissta)c• Inicializadasnaprimeiravezemqueoprogramarealizaadeclaraçãodavariável
• Valoréman6dodeumachamadaparaoutra– Áreadevariáveisestá6casdoprograma(nãosãocriadasnapilha)
38
int count() { static int num = 0; int x = 0; num++; return num;
}
Objetossta)c
• Construtorchamadoapenasumavez– Nomomentoemqueathreaddeexecuçãodoprogramaexecutapelaprimeiravezocódigodafunçãoqueinstanciaoobjeto
• Odestrutordeumobjetosta6csomenteéexecutadoaotérminodoprograma
• Objetoglobal– Construtorchamadoantesdomain()– Destrutorchamadoaotérminodoprograma
39
Objetossta)c
40
#include <iostream> using namespace std; class Obj {
char c; // Identifier public:
Obj(char cc) : c(cc) { cout << "Obj::Obj() for " << c << endl; } ~Obj() { cout << "Obj::~Obj() for " << c << endl; }
}; Obj a('a'); // Global void f() {
static Obj b('b'); } void g() {
static Obj c('c'); }
Objetossta)c
41
int main() { cout << "inside main()" << endl; f(); // Calls static constructor for b // g() not called, c not constructed cout << "leaving main()" << endl;
} ///:~
Atributossta)c
• Implementamconceitodeatributosdeclasse– Todososobjetosdeumaclassecompar6lhamosatributosestá6cos
42
class Ponto{ int x, y; static int cont; // ... }; Ponto Ponto_1, Ponto_2;
Atributossta)c• Acessodefinidoporencapsulamento– Funçõesmembropodemacessar,outraspartessepúblico
• Atributosestá6cospodemseracessadosantesdainstanciaçãodequalquerobjetodaclasse– Espaçodememóriareservadoantesdainstanciaçãodequalquerobjeto
• Somenteconstantesestá6caspodemserdefinidasnadeclaraçãodeumaclasse– Atributosestá6cosdevemserredeclaradasnoescopodaclasse
43
Atributossta)c
44
class Ponto{
int x, y; static int cont;
// .... }; int Ponto :: cont = 7;
class Buffer { static const int buffsize = 256; char buff[buffsize];
// ... };
Métodossta)c
• Funçõesmembroque– Podemserchamadasatravésdaclasse,enãodeumainstânciapar6cular
– Nãopodemmanipularmembrosnãoestá6cosdaclasse• Sómanipulamatributoestá6cos!
45
class Ponto{ int x, y; static int cont; static int getCont() { return cont; } }; int Ponto::cont = 0; int main() {
cout << “Cont: “<<Ponto::getCont()<<endl; return 0;
}
Padrãodeprojeto:Singleton
• Classequepossuiapenasumainstância• Instânciadisponívelglobalmentenocódigo• Háváriassituaçõesqueumaclassepodeterapenasumainstância– Recursosescassos(interfacederede,spooldeimpressão),Gerenciadordepropriedadesdeumsistemaetc.
• Construtorprivado– Usa-semétodosta)cInstance()
46
Padrãodeprojeto-Singleton
47
class KbdBuffer { public:
char getch(); // reads from the buffer static KbdBuffer *Instance();
private: KbdBuffer(); // the constructor static KbdBuffer *instancePtr; // pointer to instance
}; KbdBuffer *KBdBuffer::instancePtr = 0; // reset pointer KbdBuffer *KbdBuffer::Instance() {
if (instancePtr == 0) // if pointer is null... instancePtr = new KbdBuffer;
return(instancePtr) } Utilização: char foo = KbdBuffer::Instance() -> getch();
Ponteiros,referênciasememória
• Comou6lizarponteirosereferências– C/C++
• PassagemdeparâmetrosemC++– Passagempor“referência”
• Alocaçãodinâmicadememória
48
double *ptd, *pte, *ptf; ptd = new double; pte = new double(7); ptf = new double[5]; ptf[0] = 1.; ptf[3] = 4; ptf[4] = 9.; delete ptd; delete pte; delete[] ptf;
Ponteiros,referênciasememória
49
class Carro { double velocidade; public: Carro (double vel = 0) : velocidade(vel) {} ~Carro(); { } }; Carro *pt1 = new Carro(5.0); Carro *pt2 = new Carro[7]; delete pt1; // Destrutor de carro chamado (1 vez) delete[] pt2; // Destrutor de carro chamado (7 vezes)
Ponteiros,referênciasememória
50
Carro f ( double velocidade) { Carro c(velocidade); // .... return c; // cópia do carro c } Carro& g ( Carro& car) { // .... return car; // retorna uma referência para car! } Carro c1; Carro &c2 = g(c1); // c2 referencia c1 Carro c3 = g(c1); // c3 é uma cópia de c1
Ponteiros,referênciasememória
51
Carro* g ( Carro& car) { // .... return &car; // retorna o endereço de car } Carro c1; Carro * ptc = g(c1); ptc->acelera(); // altera c1, utilizando ptc
Ponteiros,referênciasememória
52
int* f(int* x) { (*x)++; return x; // OK, x esta fora deste escopo } int& g(int& x) { x++; // Mesmo efeito que f() return x; // OK, fora deste escopo } int& h() { int q; //return q; // Erro static int x; return x; // OK, x vive fora do escopo } int main() { int a = 0; f(&a); g(a); int &j = h(); }
Ponteiros,referênciasememória
• Referênciasconstantes– Usocomobjetostemporários(sãosempreconstantes)
53
void f(int&) {} void g(const int&) {} int main() { //! f(1); // Error g(1); }
Construtordecópia
• Executadoquandohápassagemdeparâmetrosouretornoporcópia
• Objetoédeclaradoeinicializadoporintermédiodeumoutroobjetodamesmaclasse– Cópiadoestado(valordetodosatributos)deumobjeto
54
Construtordecópia
55
class Big { private:
// Um monte de atributos }; Big bigfun(Big b) { // Passagem por cópia (chama const. de cópia)
// ... return b; // Retorno por cópia (chama const. de cópia)
} int main() {
Big B, B2; // Construtor sem parâmetros (default) Big B3(B); // Construtor de cópia Big B4 = B3; // Construtor de cópia B = B3; // NÃO há chamada ao construtor de cópia (atrib.) B2 = bigfun(B); // Construtor de cópia 2 vezes //(passagem e retorno) Big B5 = bigfun(B2); // Seriam 3 vezes, mas o compilador // pode ser “esperto” ==> 2
}
Construtordecópia
• Construtordecópiarecebeumareferênciaconstanteparaobjetoasercopiado– Evitarecursãoinfinita(casorecebesseporcópia)
• Paraimpedirqueobjetosdeumaclassesejampassadosporvalor,cria-seumconstrutordecópiaprivado
56
Construtordecópia
57
class NoCC { int i; NoCC(const NoCC&); // Privado, não precisa
definição public:
NoCC(int ii = 0) : i(ii) {} }; void f(NoCC); int main() {
NoCC n; // f(n); // Error: copy-constructor called // NoCC n2 = n; // Error: c-c called // NoCC n3(n); // Error: c-c called
}
Ponteirothis• Objetosacessamatributosdeumaclassedeformatransparente
• Objetoscompar6lhamasinstruções(código)dosmétodosdaclassedosquaissãoinstâncias
• Iden6ficaçãodainstânciaéfeitaatravésdoponteirothis– Éimplicitamentecriadoparacadafunção– Apontaparaoobjetoquechamouafunção
58
Ponteirothis
59
class Date { int d, m, y;
public: Date( int dd=0, int mm=0, int yy=0); Date& add_year(int n); // Adiciona n anos Date& add_month(int n); // Adiciona n meses Date& add_day(int n); // Adiciona n dias
}; Date& Date::add_year(int n) {
if (d==29 && m==2 && !leapyear (y+n)) { // Cuida do 29/02 d = 1; m = 3; } y +=n; return *this;
} // Semelhante para add_month e add_day Date dt; dt.add_day(4).add_month(2).add_year(1);
Atributosdinâmicos• Atributosdinâmicos– Membroéponteiroememóriaéalocadadinamicamente• Geralmentenosconstrutoresououtrosmétodosdeinicialização
– Aotérminodoescopodosobjetosmemóriadeveserdesalocadaparaosatributosdinâmicos• Métododestrutor
– Construtordecópiasobrecarregado• Evitarproblemasnapassagemdeparâmetrosporcópia
60
Atributosdinâmicos
61
class MeuVetor { double* valores; int dim;
public: MeuVetor(int n = 1, double val = 0); ~MeuVetor(); MeuVetor(const MeuVetor&); void mostra ();
}; MeuVetor::MeuVetor(int n, double val) :
dim(n) { valores = new double[dim]; for (int i = 0; i < dim; i++) valores[i] = val;
} MeuVetor::~MeuVetor() {
delete[] valores; }
Atributosdinâmicos
62
void MeuVetor::mostra () { for(int i=0; i<dim; i++) std::cout << valores[i] << std::endl; }
MeuVetor::MeuVetor(const MeuVetor& vc) : dim(vc.dim) { valores = new double[dim]; for (int i = 0; i < dim; i++) valores[i] = vc.valores[i];
} void f(MeuVetor vet) {} void main() {
MeuVetor vet(30, 7.) f(vet); vet.mostra();
}
Polimorfismo
• Quandosetrabalhacomherançapública,pode-serealizarupcas)ng
• Aclassederivadaéum6podaclassebaseeumobjetoinstânciadaclassederivadapodeseru6lizadocomoumdaclassebasequandonecessário
63
void f(Animal &an) { an.come() ; an.dorme();
}; void g(Ave &av) { f(av); }
Polimorfismo
• Upcasttambémpodeserrealizadoemponteirosereferências,semanecessidadedecastexplícito
64
Ave av; Animal * an1 = & av; Animal & an2 = av; an1-> come(); an1->dorme(); // an1->botaOvo(); // ERRO!!!
Polimorfismo
• EquandoummétododeAnimal,porexemplo,Animal::come,ésobrescritonaclasseAve?
65
class Ave: public Animal { public:
void come( ); void voa( ); void botaOvo( );
} ... Ave av; Animal * an = &av; an-> dorme (); // Animal::dorme() an-> come (); // Animal::come()!
Polimorfismoefunçõesvirtuais
• OPolimorfismoprovêoutradimensãodeseparaçãoentreinterfaceeimplementação,desacoplando“oquê”de“como”,melhorandoaorganizaçãodocódigogeradoeoseuentendimento.
66
Polimorfismoefunçõesvirtuais
• Herança-classesesubclasses(sub6pagem)• Classesdiferentes,derivadasdeummesmo6pobase,podemsertratadascomosefossemdeumúnico6po
• Pode-setrabalharcomessasdiferentesclassesdemaneiraúnica
• Cadaclassepoderápossuirumamaneiraprópriadetratarsituaçõesespecíficas
67
Polimorfismoefunçõesvirtuais
• Binding– Ligaçãoentreobjetosefunções
• Quandoaligaçãoéefetuadaantesdaexecuçãodoprogramaelaédenominadadeligaçãoestá6ca(earlybinding)– Efetuadapelocompiladorepelolinker
68
Polimorfismoefunçõesvirtuais
• Noexemplo,ocompiladornãoconseguedeterminarafunçãoaserchamada– aúnicacoisaqueeleconheceéo6podoponteiro(Animal*)queestásendou6lizado
69
class Ave: public Animal { public:
void come( ); void voa( ); void botaOvo( );
} ... Ave av; Animal * an = &av; an-> dorme (); // Animal::dorme() an-> come (); // Animal::come()!
Polimorfismoefunçõesvirtuais
• Solução:ligaçãodinâmica(latebinding)– Ligaçãofeitaemtempodeexecução– Baseadano6podoobjetoapontadoenãono6podoponteiro
• EmC++funçõesligadasdinamicamentedevemserdeclaradascomovirtuaisnaclassebase
• Objetosdevemsermanipuladospormeiodereferênciasparaaclassebase
70
Polimorfismoefunçõesvirtuais
• Somenteadeclaraçãodafunçãonecessitadapalavrachavevirtual
• Ousodapalavrachavenasclassesderivadaséredundante
71
Polimorfismoefunçõesvirtuais
72
class Animal { public: virtual void come( ); virtual void dorme( ); }; class Ave: public Animal { public: void come( ); void voa( ); void botaOvo( ); } void g(Animal &an) { an.come(); }
int main() { Ave av; Animal an1; g(av); // OK: upcasting! g(an1); // OK! Animal * ptan = &av; //up ptan-> dorme (); // Animal::dorme() ptan-> come (); // Ave::come() return 0; }
Polimorfismoefunçõesvirtuais• Polimorfismo– Funçõeshomônimasparalógicassemelhantesaolongodeumahierarquia
– Ligaçãodinâmicanecessáriaparaquehajapolimorfismo
– EmC++,funçõesvirtuais
• Classebasetemfunçõesquedevemtercomportamentosdiferentesemsuasderivadas– Funçõesvirtuaisnaclassebase– Redefinidasnasclassesderivadas
73
Polimorfismoefunçõesvirtuais
74
class Point { /* ... */}; class Color{ /* ... */}; enum Kind { circle, triangle, square }; class Shape { Kind k; Point center; Color col; public: void draw( ); void rotate(float ang); // ... };
void Shape :: draw( ) { switch (k) { case circle: // desenha o circulo break; case triangle: // desenha o triangulo break; case square: // desenha o quadrado break; } // end switch }
Ruim
Jásabertodos?
Polimorfismoefunçõesvirtuais
• Solução– Agruparoqueécomumatodasassubclassesemumaclassebase• Ex.Shapespossuemumaforma,umacor,podemserdesenhados,girados,etc.
– Propriedadesemétodosespecíficosemclassesderivadas• Ex.detriângulos,círculosedemaisshapes
– Herança
75
Polimorfismoefunçõesvirtuais
76
class Shape { // ... public: void draw( ) { cout << “Shape::draw”; } }; class Triangle : public Shape { // ... public: void draw( ) { cout << “Triangle::draw”;} }; void teste(Shape & a) { a.draw(); } int main() { Triangle t; teste(t); // Chamar de Shape, não de Triangle }
Polimorfismoefunçõesvirtuais
77
Polimorfismoefunçõesvirtuais
78
class Shape{ // ... virtual void draw( ); }; class Triangle : public Shape { // ... virtual void draw( ); // virtual é opcional }; void teste(Shape & a) { a.draw(); } int main() { Triangle t; teste(t); // Agora, chama draw de Triangle! }
Referências
• NotasdeauladoProf.RenatoMaia(Unimontes)
• NotasdeauladoProf.RenatoMesquita(UFMG)
79