Programação Orientada a Objetos CLASSES E OBJETOS Renato Dourado Maia Universidade Estadual de Montes Claros Engenharia de Sistemas
Em que Parte do Conteúdo Estamos? Da Unidade III Classes e Objetos, já foram trabalhados os seguintes tópicos: Implementando classes e objetos em C++. Atributos e métodos: controle de acesso e encapsulamento. Inicialização e destruição. Sobrecarga de funções e argumentos default. Constantes, funções inline e controle de visibilidade. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 2/26
Em que Parte do Conteúdo Estamos? Veremos na aula de hoje e na(s) próxima(s): Ponteiros, referências, atributos dinâmicos, gerenciamento de memória e o construtor de cópia. Sobrecarga de operadores e conversão de tipos. ISSO ENCERRA A UNIDADE III E O CONTEÚDO DA PRIMEIRA PROVA! 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 3/26
Lembrando... O que já foi estudado sobre o assunto: Como criar a utilizar ponteiros e referências. Como utilizar ponteiros e referências para passar parâmetros por referência para funções. Como utilizar referências constantes para passar parâmetros por referência para funções (esses parâmetros não poderão ser modificados dentro da função). Referências têm que ser inicializadas quando são criadas: Uma vez inicializada, não se pode fazer uma referência referenciar outro objeto. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 4/26
Lembrando... Utilizando-se ponteiros, pode-se realizar alocação dinâmica de memória: double *ptd, *pte, *ptf; ptd = new double; // aloca um único double apontado por ptd pte = new double(7); // um único double, apontado por pte, inicializado // com o valor 7 ptf = new double[5]; // um array de 5 doubles, alocado dinamicamente. // Posição 0 do array apontada por ptf ptf[0] = 1.; ptf[3] = 4; ptf[4] = 9.; // Desaloca com delete ou delete[] delete ptd; delete pte; delete[] ptf; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 5/26
Lembrando... Destrutor e alocação dinâmica: class Carro { double velocidade; public: Carro (double vel = 0) : velocidade(vel) { ~Carro(); { // Faz algo ; Carro *pt1 = new Carro(5.0); // array de 7 carros (construtor chamado 7 vezes, vel = 0) Carro *pt2 = new Carro[7]; delete pt1; // Destrutor de carro chamado (1 vez) delete[] pt2; // Destrutor de carro chamado (7 vezes) 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 6/26
Retorno por Referência Uma função pode retornar uma referência, evitando a cópia: Carro f ( double velocidade) { Carro c(velocidade); //... return c; // retorna uma 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); // já c3 é uma cópia de c1! 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 7/26
Retorno por Referência O retorno por referência também pode ser realizado utilizando-se ponteiros: Carro* g ( Carro& car) { //... return &car; // retorna o endereço de car Carro c1; Carro * ptc = g(c1); ptc->acelera(); // altera c1, utilizando ptc 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 8/26
Retorno por Referência 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 9/26
Retorno por Referência int* f(int* x) { (*x)++; return x; // OK, x is outside this scope int& g(int& x) { x++; // Same effect as in f() return x; // OK, outside this scope int& h() { int q; //return q; // Error static int x; return x; // OK, x lives outside this scope int main() { int a = 0; f(&a); g(a); int &j = h(); 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 10/26
Referências Constantes A utilização de referências constantes em argumentos de funções é especialmente importante, pois u- ma função pode receber um objeto temporário, que pode ter sido criado, por exemplo, como o retorno de outra função. Objetos temporários são sempre constantes e, portanto, se não forem utilizadas referências constantes, eles não serão aceitos como argumento pelo compilador. void f(int&) { void g(const int&) { int main() { //! f(1); // Error g(1); 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 11/26
O Construtor de Cópia É executado sempre que: Ocorre passagem de parâmetros ou retorno por cópia. Um objeto é declarado e inicializado por intermédio de outro objeto da mesma classe. O comportamento default é copiar os atributos do objeto, um a um. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 12/26
O Construtor de Cópia 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 13/26
O Construtor de Cópia class Big { private: // Um monte de atributos ; Big bigfun(big b) { // Passagem por cópia (construtor de cópia é chamado //... return b; // Retorno por cópia (construtor de cópia é chamado) 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 (atribuição) 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 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 14/26
O Construtor de Cópia #include <iostream> #include <string> using namespace std; class HowMany2 { string name; // Object identifier static int objectcount; public: HowMany2(const string& id = "") : name(id) { ++objectcount; print(); ~HowMany2() { --objectcount; cout << "\t Destrutor"; print(); HowMany2(const HowMany2& h) : name(h.name) { name += " copy"; ++objectcount; print(); void print() const { cout << '\t' << name << ": " << "objectcount = " << objectcount << endl; ; int HowMany2::objectCount = 0; HowMany2 f(howmany2 x) { return x; int main() { HowMany2 h("h"); HowMany2 h2 = f(h); f(h); h: objectcount = 1 h copy: objectcount = 2 h copy copy: objectcount = 3 Destrutor h copy: objectcount = 2 h copy: objectcount = 3 h copy copy: objectcount = 4 Destrutor h copy: objectcount = 3 Destrutor h copy copy: objectcount = 2 Destrutor h copy copy: objectcount = 1 Destrutor h: objectcount = 0 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 15/26
O Construtor de Cópia O construtor de cópia tem que receber uma referência constante para o objeto que será sendo copiado. Por quê? Caso o construtor de cópia receba por cópia o objeto que será copiado, o que acontecerá? Recursão infinita! Como impedir que objetos de uma classe sejam passados por valor para funções? Criando um construtor de cópia privado! 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 16/26
O Construtor de Cópia class NoCC { int i; NoCC(const NoCC&); // Privado, não precisa de 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 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 17/26
O Ponteiro this Cada um dos objetos de uma determinada classe a- cessa os seus atributos de maneira transparente. Todos os objetos da classe compartilham os códigos dos métodos. Como o programa sabe, dentro do código da função, qual é o objeto que está sendo acessado? 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 18/26
O Ponteiro this Para efetivar a ligação entre função membro e objeto o C++ possui um ponteiro implicitamente criado para cada função da classe, denominado this, cuja finalidade é apontar para o objeto que chamou a função. Pode-se utilizar esse ponteiro quando for necessário referenciar o objeto como um todo e não os seus a- tributos individualmente (embora isso possa ser feito também). 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 19/26
O Ponteiro this 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); ; 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... // Adiciona n dias Date dt; dt.add_day(4).add_month(2).add_year(1); 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 20/26
Atributos Dinâmicos A alocação de atributos dinâmicos ocorre quando algum membro da classe é um ponteiro e aloca-se espaço para o mesmo quando um objeto é criado. Isso é normalmente feito pelos construtores da classe. Quando termina o escopo dos objetos, deve-se desalocar a memória alocada para os atributos dinâmicos, utilizando-se para isso o destrutor da classe. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 21/26
Atributos Dinâmicos Deve-se também sobrecarregar o construtor de cópia para classes com atributos dinâmicos, pois, caso contrário, problemas graves na passagem de parâmetros por cópia para funções ocorrerão. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 22/26
Atributos Dinâmicos class MeuVetor { double* valores; int dim; public: MeuVetor(int n = 1, double val =0); ~MeuVetor(); void mostra const(); ; 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; void MeuVetor::mostra const() { for(int i=0; i<dim; i++) std::cout << valores[i] << std::endl; void f( MeuVetor vet) { void main( ) { MeuVetor vet(30, 7.) f (vet); // OOOPS vet.mostra(); // Mostra quem?? Soluções: passar por referência ou criar o construtor de cópia! 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 23/26
Atributos Dinâmicos Construtor de Cópia class MeuVetor { double* valores; int dim; public: MeuVetor(int n = 1, double val =0); ~MeuVetor(); MeuVetor(const MeuVetor&); void mostra const(); ; 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; void MeuVetor::mostra const() { 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(); // OK! 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 24/26
That's All Folks! 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 25/26
Importante Esta apresentação é uma adaptação do material originalmente desenvolvido pelo professor Renato Cardoso Mesquita, do Departamento de Engenharia Elétrica da Universidade Federal de Minas Gerais. http://www.cpdee.ufmg.br/~renato 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 26/26