15.12
2020
No post anterior abordamos como fazer uma função template, neste post vamos verificar como implementar uma classe template.
Para o exemplo de classe template vamos utilizar um código muito parecido com um que já usamos anteriormente, uma pilha Last In First Out (LIFO), ou seja o último elemento que entrar é o primeiro elemento a sair.
Vamos ao código. Primeiro a declaração da classe:
template <class T>
class CStack {
protected:
class CNode {
public:
T data;
CNode *prev;
CNode(T adata, CNode *aprev) : data(adata), prev(aprev) { };
};
unsigned size;
CNode *topnode;
public:
CStack() : size(0), topnode(nullptr) { };
~CStack();
void push(T adata);
T pop();
T top();
unsigned getSize();
};
Note a forma de fazer a declaração (template <class T>), muito parecida com a forma de declarar uma função template. Podemos, inclusive, utilizar diversas classes, tal qual no caso das funções templates.
E agora a implementação:
#include "CStack.h"
template<class T> CStack<T>::~CStack() {
while (topnode) {
CNode *delnode = topnode;
topnode = topnode->prev;
delete delnode;
}
}
template<class T> void CStack<T>::push(T adata) {
CNode *newnode = new CNode(adata, topnode);
topnode = newnode;
size++;
}
template<class T> T CStack<T>::pop() {
if (!topnode)
return T();
T data = topnode->data;
CNode *delnode = topnode;
topnode = topnode->prev;
delete delnode;
size--;
return data;
}
template<class T> T CStack<T>::top() {
if (!topnode)
return T();
return topnode->data;
}
template<class T> unsigned CStack<T>::getSize() {
return size;
}
Note a necessidade de declarar o template cada vez que se faz uma referência de escopo (template <class T>).
Por último, o código de teste:
#include <iostream>
#include "CStack.h"
int main() {
CStack<int> stack;
std::cout << "Pushing..." << std::endl;
for (int ct = 10; ct--; ) {
stack.push(ct);
std::cout << ct << " ";
}
std::cout << std::endl << "Stack size: " << stack.getSize() << std::endl;
std::cout << "Stack top: " << stack.top() << std::endl;
std::cout << "Popping..." << std::endl;
while (stack.getSize())
std::cout << stack.pop() << " ";
std::cout << std::endl << "Stack size: " << stack.getSize() << std::endl;
}
Aqui a diferença para a função template: é necessário definir o tipo do template na declaração do objeto, ou do ponteiro para o objeto.
Containers STL
STL é a abreviação de Standard Template Library, ou seja a biblioteca padrão de templates, e utiliza extensivamente templates. As regras de utilização são exatamente as mesmas, sendo necessário definir os tipos em tempo de compilação durante a declaração do objeto ou do ponteiro.