Programação Orientada a Objetos OUTROS MECANISMOS Renato Dourado Maia Universidade Estadual de Montes Claros Engenharia de Sistemas
Unidade V Unidade IV Outros Mecanismos: Classes parametrizadas. A biblioteca padrão. Exceções. Identificação de tipo em tempo de execução. Hoje trabalharemos o tópico Classes Parametrizadas. Os demais tópicos serão estudados por vocês durante o desenvolvimento do Trabalho Prático IV. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 2/36
Templates Stroustrup inicialmente chamou os templates de tipos parametrizados: Uma classe ou uma função template serve como uma receita para a geração automática de classes e funções, com base na escolha de um tipo pelo usuário. As classes e algoritmos presentes na biblioteca padrão (vector<t>, list<t>, sort, find, etc ) são exemplos de classes e funções template. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 3/36
Exemplo Uma Pilha (Simples) de Inteiros class IntStack{ int* stack ; int top, ssize; public: IntStack(int size):top(0),ssize(size){stack = new int[size];; ~IntStack() { delete[] stack; void push(int i) { if(top >= ssize) { cout << Too many push()es ; exit(1); stack[top++] = i; int pop() { if (top <= 0) { cout << Too many pop()s ; exit(1); return stack[--top]; ; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 4/36
Pergunta Interessante E se o desejo for trabalhar com uma pilha de objetos de qualquer tipo? 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 5/36
Solução 1 (Horrorosa!) Copiar o código da pilha de inteiros e realizar os a- justes necessários para o novo tipo: uma pilha de a- viões. Desvantagens: Cansativo. Confuso. Propenso a erros. Deselegante. ECA! 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 6/36
Solução 2 (Não Muito Bonita...) Uma classe da biblioteca padrão é a base para as demais classes, não existindo mais do que uma árvore hierárquica. Utiliza-se a herança da classe base genérica: Classe base genérica: Object. As demais classes devem ser criadas a partir da classe base Object. Assim, seus objetos são armazenados no container de ponteiros para Object. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 7/36
Solução 3 Templates Em C++, tentou-se inicialmente implementar a solução apresentada no slide anterior: A utilização do mecanismo era complicada e confusa, especialmente porque todas as classes deveriam ser derivadas de uma única classe: Object! Em muitas situações era necessário introduzir herança múltipla... 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 8/36
Solução 3 Templates Inicialmente, Stroustrup propôs criar as classes containers como sendo grandes macros com argumento. Assim, ao se criar um container para um objeto, fazia-se uma dupla chamada da macro. Infelizmente, essa solução era mais confusa do que as soluções existentes até então... Finalmente, Stroustrup modificou essa macro original, simplificando-a e movendo-a do domínio do préprocessador para dentro do compilador. Esse novo dispositivo ele denominou de Templates. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 9/36
Solução 3 Templates Os Templates C++ permitem a execução de um molde genérico Stack<T> com parâmetro T de qualquer tipo, podendo esse tipo ser primitivo da linguagem ou definido pelo próprio usuário. Os Templates C++ fornecem uma maneira reuso do código fonte, ao contrário da herança e da composição, que fornecem uma maneira de reuso do código objeto. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 10/36
Solução 3 Templates Template é a palavra chave para o compilador identificar que a classe ou função manipulará um tipo não especificado: O mecanismo pode ser implementado na forma de classes template ou de funções template. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 11/36
Sintaxe para a definição: Funções Template template <class Tipo1 [,..., class Tipo2]> protótipo_função_template() { //código da função template Exemplo: template <class T> T soma(const T& p1, const T& p2) { return(p1+p2); 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 12/36
Funções Template Utilização: int i = 1, j = 2; double f = 3., g = 4.; Matriz A(20,20), B(20,20); // gera int soma(const int&, const int&) int k = soma(i,j); // gera double soma(const double&, const double&) double h = soma(f,g); // gera Matriz soma(const Matriz&, const Matriz&) // (se existir Matriz::operator+) Matriz C = soma(a,b); 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 13/36
Funções Template O código do slide anterior mostra claramente uma característica das funções template: elas só podem ser instanciadas (ter seu tipo genérico T substituído por um tipo de verdade ) caso o tipo de verdade satisfaça alguns pré-requisitos... No caso específico da função soma, quais seriam os prérequisitos? template <class T> T soma(const T& p1, const T& p2) { return(p1+p2); 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 14/36
Funções Template No caso específico da função soma, quais seriam os pré-requisitos? template <class T> T soma(const T& p1, const T& p2) { return(p1+p2); O tipo T: Tem que ter implementado o operator+! Deve possuir também um construtor de cópia (criado pelo programador ou sintetizado pelo compilador) para permitir o retorno por cópia. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 15/36
Funções Template Quando uma função template é chamada, os tipos dos argumentos da função determinam qual versão do template será utilizada, isto é, os parâmetros do template são deduzidos a partir dos argumentos da função. Cada vez que o compilador encontrar uma chamada de função template ainda não realizada para aqueles tipos, ele definirá um novo código (as várias funções terão endereços e códigos diferentes): esse processo é chamado de instanciação da função template. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 16/36
Funções Template Exemplo template< class T > void printarray( const T *array, const int count ){ for ( int i = 0; i < count; i++ ) cout << array[ i ] << " "; cout << endl; int main() { const int acount = 5, bcount = 7, ccount = 6; int a[ acount ] = { 1, 2, 3, 4, 5 ; double b[ bcount ] = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 ; char c[ ccount ] = "HELLO"; // 6th position for null printarray( a, acount ); // integer template function printarray( b, bcount ); // double template function printarray( c, ccount ); // character template function return 0; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 17/36
Templates Argumentos Explícitos Em algumas situações, não é possível para o compilador deduzir qual é o tipo de argumentos do template. template <class T> T max (T t1, T t2) { return (t1 > t2? t1 : t2); unsigned int ui = 10; int ia = 1; // Erro! Deve instanciar max<unsigned int> ou max<int>? max(ui, ia); Solução: indicar explicitamente a instância desejada: max< unsigned int > (ui, ia); 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 18/36
Templates Especialização Explícita Nem sempre é possível escrever uma única função template que funcione bem para todos os tipos para os quais ela pode ser instanciada. Em alguns casos, pode-se tirar vantagem do conhecimento específico que se tem sobre algum tipo para escrever uma função mais eficiente do que a instanciada pelo template. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 19/36
Templates Especialização Explícita Em outros casos, a função é simplesmente uma função errada para o tipo: template <class T> T max (T t1, T t2) { return (t1 > t2? t1 : t2); Essa função não funciona corretamente para o tipo const char * (string do C) Para resolver esse problema, pode-se criar uma especialização explícita para a função para o tipo const char*! 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 20/36
Templates Especialização Explícita Especialização explícita para const char*: #include <cstring> typedef const char *PCC; template<> PCC max< PCC > (PCC s1, PCC s2) { return ( strcmp( s1, s2) > 0? s1 : s2 ) ; int main () { int i = max (10, 5); // chama int max<int> (int, int); // Chama a especialização max<pcc> (PCC, PCC); const char *p = max ( hello, world ) ; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 21/36
Classes Template Pilha template <class T> class Stack{ T* stack ; int top, ssize; public: Stack(int size):top(0),ssize(size){stack = new T[size];; ~Stack() { delete[] stack; void push(t i) { if(top >= ssize) { cout << Too many push()es ; exit(1); stack[top++] = i; T pop() { if (top <= 0) { cout << Too many pop()s ; exit(1); return stack[--top]; ; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 22/36
Classes Template Array template<class T> class Array{ private: T* A; int size; public: Array(int tam):size(tam) {A = new T[tam]; T& operator[](int index) { return A[index]; ; int main(){ Array<int> ia(20); Array<float> fa(20); for(int i=0; i<20; i++){ ia[i]=i*i; fa[i]=i*1.414; for(int j=0; j<20; j++) cout << j << : << ia[j] <<, << fa[j] << endl; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 23/36
Classes Template Funções não inline template<class T> class Array{ private: T* A; int size; public: Array(int tam); T &operator[](int index); ; // Funções não inline template<class T> Array<T>:: Array(int tam):size(tam){ A = new T[tam]; template<class T> T & Array<T>:: operator[](int index) {return A[index]; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 24/36
Classes Template Pilha com Constante template<class T,int sz=100> class Stack { private: T stack[sz]; int top; public: Stack() : top(0){; void push (const T &i); T pop(); int size() { return top ; T peek() const; ; template<class T, int sz> void Stack<T,sz> :: push(const T&i) { if(top >= sz){ cout<< Too many push()es ; exit(1); stack[top++] = i; template<class T, int sz> T Stack<T,sz> :: pop(){ if (top <= 0) {cout<< Too many pop()s ; exit(1); return stack[--top]; template<class T, int sz> T Stack<T,sz> :: peek() const { return stack[top-1]; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 25/36
Instanciação das Funções Template Uma função membro de uma classe template também é uma função template; A norma C++ exige que essa função membro somente seja instanciada quando chamada explicitamente ou quando o seu endereço é utilizado (por meio de um ponteiro para a função): Uma função membro de uma classe template não é instanciada automaticamente quando a classe template é instanciada! 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 26/36
Classes Template e Membros Static Uma classe template pode declarar membros de dados static. Cada instanciação da classe template vai possuir seu próprio conjunto de membros de dados static. Como todo membro static de dados, ele deve ser inicializado fora da classe: template <class T> class Ponto { T x; T y static int npontos; // etc... ; template <class T> int Ponto<T>::npontos = 0; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 27/36
Classes Template e Herança Os conceitos básicos associados à herança também podem ser utilizados em conjunto com classes templates: Além de gerar classes, podem ser geradas hierarquias de classes com templates, sendo que cada hierarquia é parametrizada. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 28/36
Classes Template e Herança Podem-se criar: Classes template derivadas de classes template. Classes comuns derivadas de instâncias de classes template. Classes template derivadas de classes comuns. Classes template derivadas de instâncias de classes template. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 29/36
Classes Template e Herança Funções virtuais são permitidas na hierarquia, o que permite a utilização de polimorfismo. Pode-se ter também classes template abstratas, etc... 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 30/36
Classes Template e Herança template <class T> class Base { // Classe template T b; ; template<class T> class D1 : public Base<T> { // template derivada de template T c; ; template <class T> class D2 : public Base <int> { // template derivada de instância T d; ; class D3 : public Base<float> { // classe comum derivada de instância int f; ; template <class T> class D4 : public D3 { // template derivada de classe comum T g; ; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 31/36
Templates e Header Files Existem duas maneiras de organizar o código fonte quando funções e classes templates são utilizadas: Colocar as declarações e definições das classes em um.h. Isso pode parecer que viola a regra normal dos arquivos de cabeçalho, mas definições de templates são especiais, pois o compilador necessita efetuar a substituição de código fonte. Compiladores teoricamente permitem a separação dos arquivos.h e.cpp, mas a palavra chave export deve ser utilizada. A palavra export significa: é acessível a partir de outra unidade de compilação. 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 32/36
Classes Template e Funções Membro Template Uma função membro de uma classe template pode ser uma função template parametrizada por um outro tipo: template<class T, int size > class Array{ private: T A[size]; public: T &operator[](int index) { return A[index]; template <class Iter> void copy(iter first, Iter last) { for(int i=0; first!= last; ++first, ++i) A[i] = *first; ; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 33/36
Classes Template e Funções Membro Template A função membro template também pode ser definida fora da definição da classe: template<class T, int size > class Array{ private: T A[size]; public: T &operator[](int index) { return A[index]; template <class Iter> void copy(iter first, Iter last); ; template <class T, int size> template <class Iter> void Array< T, int size > :: copy(iter first, Iter last){ for(int i=0; first!= last; ++first, ++i) A[i] = *first; 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 34/36
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 35/36
That's All Folks! 24/08/15 Programação Orientada a Objetos Renato Dourado Maia 36/36