terça-feira, setembro 12, 2006

Aula 11

C++ implementa templates os quais podem ser usados em classes e
funções. Para exemplificar seu uso em classes, sejam as classes
abaixo, as quais representam um elemento de uma lista linearmente
encadeada e a lista propriamente dita:

Ex.
struct Banana
{
float L;
float D;
Banana *Next;

}

class ListBanana
{
public:
ListBanana();
~ListBanana();
void Add(Banana*);
void Remove(Banana*);
int GetNumberOfElements() const;
bool IsEmpty() const;
void Clear();
Banana *PeekHead() const;

private:

Banana *Head;
Banana *Tail;
int NumberOfElements;
ListBanana(const ListBanana&); // Não pode acessar
//os métodos private, logo não há construtor de cópia
ListBanana& operator=(const ListBanana&);

};

void ListBanana :: Clear()
{

while(Head)
{

Banana *temp = Head;
Head = Head -> next;
delete temp;

}
Tail = NumberOfElements = 0;

}


OBS:
Banana b; // Cria objeto


List lb // Cria classe
// classe (instância do template); objeto (instância da classe);

typedef List ListBanana;
ListBanana lb;

Vamos supor agora que se queira implementar uma lista de um
outro tipo qualquer, por exemplo: "Laranja". Sem templates há
duas alternativas:
  1. 1. Replicar a implementação da lista trocando "Banana" por "Laranja". Isto é incoveniente por razões óbvias, dentre as quais, há necessidade de alterações manuais no código replicado, sempre que um novo método seja adicionado a classe ou que algum método já existente seja alterado.
  2. 2. Para evitar a replicação, os elementos de uma lista seriam de classes todas elas derivadas de uma classe chamada:
class ListElement
{
private:
ListElement *Next;
friend class List;

};


Assim, "Banana" e "Laranja" derivariam de "ListElement" e haveria
apenas uma implementeção da classe "List", cujos elementos seria
do tipo "ListElement". O incoveniente é que um objeto do tipo
"List" seria um contêiner de quaisquer objeto do tipo "ListElement",
ou seja, poderíamos ter na mesma lista "Bananas" e "Laranjas".
As vezes é justamente isso que se quer, mas nem sempre.
Quando for este o caso, podemos usar templates.

Uma lista genérica pode ser definida em C++ através do seguinte template:

template
class ListImp
{
public:

ListImp();
~ListImp();
void Add(T*);
void Remove(T*);
int GetNumberOfElements() const;
bool IsEmpty() const;
void Clear();
T *PeekHead() const;
void AddAtHead(T*);

private:
T *Head;
T *Tail;
int NumberOfElements;
ListImp(const ListImp&);
ListImp& operator=(const ListImp&);

}


template
void ListImp :: Clear()
{
while(Head)
{
T *temp = Head;
Head = Head -> next;
delete temp;

}
Tail = NumberOfElements = 0;

}


No exemplo acima, "" é o parâmetro do template, o qual representa
um tipo qualquer chamado "T". Note que no corpo da classe, "T"
é usado para representar o tipo de atributos, valores de retorno de
método e parâmetros de método. Um template pode ter qualquer
número positivo de parâmetros.
Um template de uma classe não é uma classe, mas um molde a
partir do qual o compilador gera uma classe. Gerar uma classe a
partir de um template, significa instanciar o template. Para tal,
basta escrever o nome da classe e fornecer um argumento:

... ListImp ...
Supoe-se que o template seja instanciado somente uma vez pelo compilador. Quando um template é instanciado todo o código definido no molde é gerado trocando-se o parâmetro pelo argumento(no exemplo todo T é trocado por Banana). Veja a analogia:

ListImp <> | B;


Na declaração acima ocorre a criação da classe que representa uma lista de Bananas, se esta ainda não tiver sido criada pelo compilador(instanciação do template) e em seguida a criação de um objeto chamado LB do tipo List da Banana(instanciação da classe).

Instanciação de template é igual a classe e instanciação de classe é igual a objeto

Cada instanciação de um template com diferentes argumentos replica todo o código definido no molde. Isto é oque faríamos manualmente no item 1 listado anteriormente; A vantagem é que a tarefa é executada automaticamente pelo compilador. Mas tenha em mente que a replicação ocorre. Portanto embora seja uma solução interessante em muitos casos templates devem ser usados criteriosamente. No caso de lista os métodos são simples e sua replicação não aumentaria demais o tamanho do programa objeto. Isto não ocorre com tudo, em estruturas que requerem um código mais complexo, como por exemplo AVLs. Nesse caso poderíamos criar uma classe base e implementaria os métodos mais complicados e que operariam sobre um tipo genérico como feito a seguir:

class AVLNode
{
public:
AVLNode* Righ;
AVLNode* Left;
int Balance;

};


class AVLBase
{
private:
AVLNode* Root;
int NumberOfElements;

protected:
void Add(AVLNode* );
...

};



A classe AVLBase implementa as operações de inserção, remoção, e atravessamento de uma AVL considerando que os elementos são do tipo AVLNode. Esses métodos são declarados protegidos em AVLBase.

template <>
class AVLElement: public AVLNode
{
public:
T Value;
...

};


template <>
class AVL: public AVLBase
{
public:
void Add(const TB Value)
{
AVLBase::Add(new AVLElement <> (Value));

}

...

};



O template AVLElement gera classes cujos objetos são nós tipo AVL com valor do tipo T. O template AVL gera classes cujos objetos são AVLs de elementos do tipo T. Note que agora a instanciação desse template não replica o código complicado da estrutura de dados AVL o qual foi implementado em AVLBase.

No template ListImp o tipo T deve ser uma classe que declara como atributo público Next. Esta exigência impede que usemos o ListImp para gerar uma lista de Inteiros por exemplo. Isto pode ser contornado com os seguintes templates:

Template
class List
{
public:

List();
~List();
void Add(T*);
void AddAtHead(T*);
void Remove(T*);
int GetNumerOfElements() const;
bool IsEmpty() const;
void Clear();
T* PeekHead() const;

private:

T* Tail;
T* Head;
int NumberOfElements;
List(const List<>&);
List operator=(const List<>&);
}

O template List gera classes cujos objetos são listas de elementos cujo valor são do tipo T. Supoe-se agora que sobre o tipo T sejam definidas as operações de cópia e comparação(verifique).

0 comentários:

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Justin Bieber, Gold Price in India