C++ INF1761 - Computação Gráfica Orientação por Objetos • Dados são modelados não apenas pela sua representação, mas principalmente pelo seu comportamento • Objetos são um TAD: representação interna + conjunto de operações • Variáveis da aplicação são objetos • Classes são os tipos dos objetos • Funções dos objetos são chamadas métodos Classes em C++ typedef struct { double xc, yc; double raio; } Circulo; C double area( Circulo e ) { return 3.14159 * e.raio * e.raio; } int interior( Circulo e, double x, double y) { … } X C++ struct Circulo{ double xc, yc; double raio; double area() { return 3.14159 * raio * raio; } int interior(double x, double y) { … } }; Objetos em C++ Circulo c; c.x = 3.2; c.y = 4.5; c.raio = 6.5; printf(“%d”, area( c )); if (interior( c, 9.5, 2 )) … C++ C Circulo c; c.x = 3.2; c.y = 4.5; c.raio = 6.5; printf(“%d”, c.area()); if (c.interior( 9.5, 2 )) … Encapsulamento Declarações equivalentes class: default é private struct: default é public class Classe { int c, b; public: int a, d; void set_c( int val ) { c = val; } }; struct Classe { private: int c, b; public: int a, d; void set_c( int val ) { c = val; } }; Classe obj; obj.a = 1; obj.c = 0; obj.set_c( 0 ); // ok // erro - campo c é privado // agora sim Construtores e Destrutores Métodos chamados implicitamente quando o objeto é criado e quando é destruído. class Classe{ public: Classe() { printf(“construtor\n”); } ~Classe() { printf(“destrutor\n”); } }; void f() Execução de f { Classe p1, p2; // p1 e p2 criados printf( “funcao f\n” ); // p1 e p2 destruídos } construtor construtor funcao f destrutor destrutor Construtores com parâmetros Construtores podem ter parâmetros (destrutores não!). Além disso, uma classe pode ter mais de um construtor, desde que eles recebam parâmetros diferentes. class Circulo{ double xc, yc; double raio; public: Circulo( double x, double y, double r) { xc=x; yc=y; raio=r;} … }; Circulo c1( 3.2, 4.5, 9.0 ); // obriga a inicialização Circulo c2; // erro, não tem construtor sem parâmetros c1.xc = 4; // erro, campo xc é privado Alocação dinâmica class Circulo{ … public: Circulo(); Circulo( double x, double y, double r); ~Circulo(); }; Circulo *c1, *c2; c1 = new Circulo; // cria um objeto da classe Circulo, // alocando memória e chamando o // construtor Circulo() c2 = new Circulo( 3.2, 4.5, 9.0 ); // cria outro, // agora com o outro construtor … delete c2; // destroi o objeto apontado por c2: // chama o destrutor e desaloca memória delete c1; // idem Herança Herda da classe Circulo (classe base) class CirculoColorido : public Circulo { int cor; public: CirculoColorido( double x, double y, double r, int c) : Circulo( x, y, r ) { cor = c; } void troca_cor( int c ) { cor = c; } }; Inicializa a classe base antes de entrar no construtor CirculoColorido c( 1.0, 3.4, 3.2, VERDE ); c.troca_cor( AZUL ); double a = c.area(); // ok, CirculoColorido tem tudo de Circulo Representação dos objetos Circulo Circulo* double xc double yc double raio Representação da classe Circulo CirculoColorido CirculoColorido* double xc double yc double raio Representação da classe Circulo int cor Declarado em CirculoColorido Conversão de objetos int intersecta( Circulo *c1, Circulo *c2 ); Circulo *c1, *c2; c1 = new Circulo(3, 4, 2); c2 = new Circulo(3.5, 3.3, 1 ); if (intersecta(c1, c2)) … CirculoColorido *c3; c3 = new CirculoColorido( 2.5, 1, 3 ); if (intersecta(c1, c3)) … Polimorfismo class A { virtual void nome() { printf(“classe A\n”); } }; class B : public A { virtual void nome() { printf(“classe B\n”); } }; A *pa; // ponteiros para objetos da classe A A* obj_a = new A; // cria objeto da classe A B* obj_b = new B; // cria objeto da classe B pa = obj_a; pa->nome(); // pa aponta para um objeto da classe A // chama o metodo <nome> de A pa = obj_b; pa->nome(); // pa aponta para um objeto da classe B // chama o metodo <nome> de B!!! Abstraindo as implementações dos objetos Que métodos um objeto da cena precisa ter para permitir a implementação desta função? rtColor trace ( rtRay ray, int depth) { determine a interseção mais próxima com um objeto if (intercepta objeto) { calcule a normal no ponto de interseção return ( shade ( object, ray, intersection, normal, depth); } return BACKGROUND; } class Objeto3D { public: virtual double intersecta( Raio r ) = 0; virtual Vetor3D normal( Vetor3D ponto ) = 0; }; Implementando a função trace Objeto3D* objetos[MAX_OBJETOS]; int n_objetos; rtColor trace ( rtRay ray, int depth) { determine a interseção mais próxima com um objeto ... Cor trace( Raio ray, int depth ) { int mais_proximo; double dist = -1; for (int i=0; i<n_objetos; i++) { double d = objetos[i]->intersecta(ray); if (d > 0 && (dist==-1 || d < dist)) { dist = d; mais_proximo = i; } } ... Implementando a função trace ... if (dist > 0) { Vetor3D ponto_de_inter = ray.ponto( dist ); Vetor3D normal = objetos[mais_proximo]->normal( ponto_de_inter); return shade(objetos[mais_proximo], ray, ponto, normal, depth ); } else { return BACKGROUND; } } ... if (intercepta objeto) { calcule a normal no ponto de interseção return ( shade ( object, ray, intersection, normal, depth); } return BACKGROUND; } Referência de C++ The C++ Programming Language 3a Edição B. Stroustrup Addison-Wesley, 1997