13

Click here to load reader

Templates em C++

Embed Size (px)

DESCRIPTION

Templates em C++

Citation preview

  • Templates em C++Templates permitem a criao de cdigo-fonte mais limpo e com menos esforo por parte do programador. Isso se d atravs de funes e classes genricas, que sero discutidas nesta breve introduo sobre templates em C++.

    ndice

    1. Template de funes

    2. Template de classes 2.1 Exemplo de template de classe: Stack2.2 Exemplo de template de classe: Pair

    3. Especializao de templates de funes e de templates de classes

    4. Templates e herana 4.1 Template que herda de outro template4.2 Template que herda de uma classe "normal" (no-template)4.3 Classe "normal" (no template) que herda de um template

    5. Bibliografia

    1. Templates de funes

    Iremos motivar a discusso sobre templates de funes a partir de um exemplo. Suponha que temos um programa que imprime um array de inteiros qualquer, ordena esse array e o imprime novamente. Esse programa possue duas funes: print_array() e insertion_sort().

    #include

    void print_array(int arr[], int length){ for (int i = 0; i < length; i++) { std::cout

  • void insertion_sort(int arr[], int length){ int i, j, key; for(i = 1; i < length; i++) { key = arr[i]; j = i - 1; while(j >= 0 && arr[j] > key) { arr[j+1] = arr[j]; j -= 1; } arr[j+1] = key; }}

    void insertion_sort(double arr[], int length){ int i, j; double key; for(i = 1; i < length; i++) { key = arr[i]; j = i - 1; while(j >= 0 && arr[j] > key) { arr[j+1] = arr[j]; j -= 1; } arr[j+1] = key; }}

    int main(){ int a[10] = {3, 20, -1 , 4, 2, 50, 10, 9, 8, 13}; std::cout

  • Suponha que precisamos de uma funo minimum() que recebe dois argumentos do mesmo tipo e retorna o menor deles. Se queremos usar minimum() com variveis int, double, char, e at mesmo objetos std::string, podemos escrever um template funo para um tipo genrico T.

    Cdigo-fonte Sada do programa

    #include #include

    template inline const T& minimum(const T& arg1, const T& arg2){ return (arg1 < arg2) ? arg1 : arg2;}

    // Fazemos a funo inline e passamos os argumentos// por referncia por questo de desempenho.

    int main(){ std::cout

  • Como esperado, temos a sada:

    Array original: 3 20 -1 4 2 50 10 9 8 13 Array ordenado: -1 2 3 4 8 9 10 13 20 50 Array original: 1.01 -0.3 3.14 1.2 20.5 1.3 7.7 0.1 9.2 -3 Array ordenado: -3 -0.3 0.1 1.01 1.2 1.3 3.14 7.7 9.2 20.5 Array original: Ocelot Tiger Cat Lion Leopard Array ordenado: Cat Leopard Lion Ocelot Tiger

    Para finalizar a apresentao de templates de funes, algumas observaes gerais importantes.

    provvel que voc encontre em outros lugares uma sintaxe diferente da apresentada aqui. Ao invs de

    template // ...

    vrios programadores utilizam

    template // ...

    Para o C++ no existe nenhuma diferena semanticamente, isto , os dois significam a mesma coisa. Sendo assim a questo se reduz a gosto pessoal. O importante tentar manter uma padro consistente.

    Ainda sobre sintaxe, observe que nos exemplos utilizamos a letra T como "type parameter". Isso um costume entre a maioria dos programadores, e no uma imposio da linguagem! Voc pode usar o identificador que quiser, como tipo, type, a, b, X, Y, desde que ele obedea as regras de nomeao de varives do C++.

    Por fim, ateno! Anteriormente dissemos que templates de funes podem ser utilizados para qualquer tipo. Na verdade, existem restries. Com tipos bsicos do C++ no preciso preocupar-se, mas para tipos definidos pelo usurio necessrio que todas as operaes utilizadas no template faam sentido. Por exemplo, imagine que criamos uma classe chamada Triangle que guarda os comprimentos dos lados de um tringulo e possue mtodos para o clculo do permetro e da rea. Se quisermos usar um array de objetos Triangle com o template de funo print_array(), definido nos exemplos anteriores, devemos fazer a sobrecarga do operador

  • 2. Templates de classes

    Com templates de classes podemos criar classes genricas que funcionam para qualquer tipo de dado. Assim como para templates de funes, temos as vantagens do reaproveitamento do cdigo de maneira inteligente e da manuteno facilitada.

    A definio de um template de classe praticamente idntica a definio de um template de funo.

    template class MyClass{ // Cdigo relevante aqui, como de praxe. // A nica diferena que voc pode tratar T como se fosse um tipo qualquer.}

    Nas subsees seguintes damos alguns exemplos prticos de templates de classes.

    2.1 Exemplo de template de classe: Stack

    A stack, conhecida tambm como "pilha", uma estrutura de dados simples e muito comum tanto na computao como na vida cotidiana. Stacks so caracterizadas pelo acrnimo LIFO (Last In, First Out), que em portugus significa "ltimo a entrar, primeiro a sair". Em uma stack, os elementos so sempre inseridos no topo, atravs da operao push. Considere, por exemplo, a criao de uma stack de livros. Uma sequncia de operaes push pode ser algo como:

    Por sua vez, a remoo de elementos tambm acontece somente no topo, atravs da operao pop. Uma sequncia de operaes pop pode ser algo como:

    Um template de classe lhe permite escrever um cdigo genrico que serve para criar pilhas de int, double, char, string, roupas, pratos, livros,

    #ifndef STACKTEMPLATE_H#define STACKTEMPLATE_H

    #include #include

    // Nesse exemplo utilizamos o container vector da STL (Standard Template Library) para facilitar a implementao.

    template class Stack{ public: void push(T new_element) { elements.push_back(new_element); } T peek() const { if(!elements.empty()) { T last = elements.back(); return last; } else { exit(1); } }

    void pop() { if(!elements.empty()) { elements.pop_back(); } }

    bool is_empty() const {return elements.empty();} int get_size() const {return elements.size();} private: std::vector elements;};

  • Simples, no mesmo? Como nos templates de funes, basta escrever T onde voc quiser generalizar o tipo de dado. Depois de terminado o template, voc pode criar objetos como a seguir:

    Stack istack; // Cria uma pilha de int chamada istackStack dstack; // Cria uma pilha de double chamada dstackStack cstack; // Cria uma pilha de char chamada cstackStack sstack; // Cria uma pilha de string chamada sstack// E assim por diante...

    Observe que necessrio especificar claramente o tipo de dado na declarao do objeto.

    Stack pilha_de_float; // ERRADO!

    Stack pilha_de_float; // CORRETO!

    Abaixo temos um exemplo de utilizao da classe Stack para uma pilha de inteiros:

    Cdigo-fonte Sada do programa

    #include "stacktemplate.h"#include

    int main(){ Stack istack; std::cout

  • Voc tambm pode utilizar o template de classe Stack para criar uma pilha de objetos da classe Book.

    Cdigo-fonte Sada do programa

    #include "stacktemplate.h"#include "books.h"#include

    int main(){ Book b1("1-59059-472-X", "Grant Palmer", "Physics for Game Programmers", 1, 2005); Book b2("0-201-63182-X", "Guido Buzzi-Ferraris", "Scientific C++", 1, 1993); Book b3("0-17-771074-8", "Anthony Philip French", "Newtonian Mechanics", 1, 1971); Book b4("0-13-979809-9", "Bruce Eckel", "Thinking In C++: Volume One", 2, 2000); Book b5("2-8315-1367-7", "Eric Bailey, Ruth Balley", "Discover Canada", 1, 1995);

    Stack books_stack;

    books_stack.push(b1); books_stack.push(b2); books_stack.push(b3); books_stack.push(b4); books_stack.push(b5);

    while(!(books_stack.is_empty())) { std::cout

  • 3. Especializao de templates

    Templates permitem uma definio genrica de uma funo ou classe que serve para qualquer tipo de dado. No entanto, pode ser que voc deseje um comportamento diferente para um tipo de dado especfico. Por exemplo, suponha que voc possue um template de funo como este:

    template void print_variable(const T &variable){ std::cout

  • Agora temos o resultado desejado.

    10Atrue2.718281828

    Existe ainda uma outra modalidade de especializao, chamada de especializao parcial. Retomando o template de classe Pair da seo 2.2 percebemos que apesar depodermos criar pares de ponteiros eles no iro se comportar de forma adequada.

    #include

    template class Pair{ public: Pair(T1 first_value, T2 second_value) : first(first_value), second(second_value) {} void set_first(T1 new_value) {first = new_value;} void set_second(T2 new_value) {second = new_value;} T1 get_first() const {return first;} T2 get_second() const {return second;} private: T1 first; T2 second;};

    int main(){ int *iptr = new int(42); double *dptr = new double(3.14); std::cout

  • Podemos criar uma especializao do template de classe Pair que funciona corretamente com ponteiros. A especializao dita parcial pois funciona para todos tipos de ponteiros (e.g., int*, double*, char*, ...), ou seja, ainda preserva alguma generalidade, ao contrrio de uma especializao completa que restringe explicitamente o tipo de dado.

    #include

    template class Pair{ public: Pair(T1 first_value, T2 second_value) : first(first_value), second(second_value) {} void set_first(T1 new_value) {first = new_value;} void set_second(T2 new_value) {second = new_value;} T1 get_first() const {return first;} T2 get_second() const {return second;} private: T1 first; T2 second;};

    // ----------------------------------// | especializao parcial abaixo! |// ----------------------------------

    template class Pair{ public: Pair (T1 *first_value, T2 *second_value) : first(new T1(*first_value)), second(new T2(*second_value)) { }

    ~Pair() { delete first; delete second; } void set_first(T1 *new_value) {first = new T1(*new_value);} void set_second(T2 *new_value) {second = new T2(*new_value);} T1* get_first() const {return (new T1(*first));} T2* get_second() const {return (new T2(*second));} private: T1 *first; T2 *second;};

    int main(){ int *iptr = new int(42); double *dptr = new double(3.14); std::cout

  • Exemplo 2

    // Template primriotemplate class bar_class{ // Cdigo para tipos genricos T1, T2, T3...};

    // Especializao completatemplate class bar_class{ // Implementao especfica quando os trs parmetros so char, double, int...};

    Uma especializao parcial fixa somente alguns dos parmetros, preservando ainda algum grau de generalidade.

    Exemplo 1

    // Template primriotemplate class bar_class{ // Cdigo para tipos genricos T1, T2, T3...};

    // Especializao parcialtemplate class bar_class{ // Implementao especfica quando o ltimo parmetro float...};

    O exemplo abaixo tambm uma especializao parcial. Observe que a especializao fixa todos os parmetros do template como ponteiros, mas ainda existe uma generalidade pois so permitidos ponteiros para qualquer tipo. Se todos os parmetros fossem fixados como ponteiros para int, por exemplo, a sim teramos uma especializao completa.

    Exemplo 2

    // Template primriotemplate class bar_class{ // Cdigo para tipos genricos T1, T2, T3...};

    // Especializao parcialtemplate class bar_class{ // Implementao especfica quando todos parmetros so ponteiros para tipos genricos...};

  • 4. Templates e herana

    Muitos livros e artigos ignoram ou falam muito brevemente sobre herana e templates de classes. No h nada de muito novo ou terrivelmente complicado se comparadocom uso de herana que voc j conhece, sem templates. Iremos expor apenas alguns exemplos ilustrativos para voc se acostumar com a sintaxe dos templates.

    4.1 Template que herda de outro template

    Definimos nas sees anteriores o template de classe Pair que nos permite criar pares de variveis de qualquer tipo. Se alm de pares quisermos trios de variveis, podemos criar um template de classe chamado Triplet que herda de Pair.

    Cdigo-fonte Sada do programa

    #include

    template class Pair{ public: Pair(T1 first_value, T2 second_value) : first(first_value), second(second_value) {} void set_first(T1 new_value) {first = new_value;} void set_second(T2 new_value) {second = new_value;} T1 get_first() const {return first;} T2 get_second() const {return second;} private: T1 first; T2 second;};

    template class Triplet : public Pair{ public: Triplet(T1 first_value, T2 second_value, T3 third_value) : Pair(first_value, second_value), third(third_value) {} void set_third(T3 new_value) {third = new_value;} T3 get_third() const {return third;} private: T3 third;};

    int main(){ Pair duo(7, 4.815); std::cout

  • 5. Bibliografia

    STROUSTRUP, Bjarne. The C++ Programming Language. 3 ed. Westford, Massachusetts: Addison Wesley, 2007.

    SAVITCH, Walter. Absolute C++. 5 ed. Upper Saddle River, New Jersey: Addison-Wesley, 2012.

    SHTERN, Victor. Core C++: A Software Engineering Approach. 1 ed. Upper Saddle River, New Jersey: Prentice-Hall, 2000.

    Templates and Template Classes in C++. In: Cprogramming.com. Disponvel em < http://www.cprogramming.com/tutorial/templates.html > Acesso em: 12 jun 2013.

    An Idiot's Guide to C++ Templates - Part 1. In: CodeProject. Disponvel em < http://www.codeproject.com/Articles/257589/An-Idiots-Guide-to-Cplusplus-Templates-Part-1 > Acesso em: 12 jun 2013.

    Class templates (C++ only). In: IBM AIX Compiler Information Center. Disponvel em < https://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp > Acesso em: 12 jun 2013.

    Autor: Dr. Hank Frum Hardware.com.brData: 18 de junho de 2013

    Templates em C++1. Templates de funes2. Templates de classes2.1 Exemplo de template de classe: Stack2.2 Exemplo de template de classe: Pair3. Especializao de templates