Você está na página 1de 23

Programação Orientada a Objetos

Programação Orientada a Objetos


Macros e Templates

Prof. Bruno Azevedo

Instituto Federal de São Paulo

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Macros

Antes de seu código ser compilado, ele é pré-processado pelo compilador.


A unidade que efetua essa operação é chamada de pré-processador.
O C++ contém elementos sintáticos pelo qual o programador pode
controlar diversos comportamentos da aplicação usando instruções de
pré-processamento.
Para definir estas instruções utilizamos o símbolo ’#’.
Estas instruções modificam o texto do código-fonte antes da compilação.

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Macros

Macros podem ajudar a deixar código mais legível e facilitam a sua


manutenção.
Podemos usar macros para substituir constantes ou pequenos blocos de
código que serão identificados por nome específico.
Macros também podem ser usadas para definir condições de compilação.
Isso permite que você inclua ou exclua partes do código com base em
certas condições.
Podem controlar a inclusão de cabeçalhos condicionalmente.
Podem ser usadas para gerar código repetido.

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Macros

Você pode criar substituições usando a diretiva #define.


#define GRANDE 1024

Portanto, no código acima, o pré-processador irá buscar todas as ocorrências da


string GRANDE e substituir por 1024.
Isso ocorre pré-compilação, ou seja, o texto de seu código-fonte é modificado
antes de ser compilado.
#define GRANDE 1024
int vetor[GRANDE];

Portanto, este código acima será enviado da seguinte forma para ser compilado:
int vetor[1024];

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Macros

Outro exemplo:
#define PI 3.141592653589793238461024
circunferenciaCirc = 2*PI*raio
areaCirc = PI*(r*r)

Temos algo mais gerenciável em nosso código usando a macro.

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Macros
A diretiva #define também pode ser usada para criar funções macro.
#define QUADRADO(x) ((x)*(x))

Acima, x é o argumento passado como parâmetro.


Suponha que tenhamos no código:
var = QUADRADO(7);

Toda ocorrência de QUADRADO(7) será substituída por (7)*(7) e em seguida


resolvida para 49.
Não é necessário utilizar parênteses para destacar os parâmetros da macro.
Entretanto, caso estes sejam expressões mais complexas, vocês poderão
encontrar problemas sem os parênteses. Por exemplo, considere o código:
#define QUADRADO(x) (x*x)
var = QUADRADO(3+4);

Isso se torna (3+4*3+4), o que resultará em 19, em vez de 49.


Os parênteses ajudam a evitar problemas potenciais relativos a precedência de
operadores.

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Macros
Macros podem ter mais de um parâmetro.
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))

Usamos o operador ternário condicional para descobrir o maior, e o menor, entre


dois números.
Temos dois parâmetros, x e y sendo utilizados na função macro.
#define MAX(x,y) ((x) > (y) ? (x) : (y))
var = MAX(73/4*1.13,18.9);

O código acima irá substituir todas as ocorrências de MAX(73/4*1.13,18.9) por


20.34.
Mas tenham cuidado com espaços em branco. O pré-processador não é tão
tolerante com espaços vazios.
Por exemplo:
#define MAX (x,y) ((x) > (y) ? (x) : (y))
#define QUADRADO (x) ((x)*(x))

Ambos os casos gerarão erros de compilação.

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Macros
Poddemos usar macros para definir condições de compilação.
#include <iostream>
using namespace std;

#define PI 3.14159265359

int main() {
#ifdef DEBUG
cout << "Estamos no modo DEBUG" << endl;
#endif

#ifdef VERBOSE_LEVEL
#if VERBOSE_LEVEL == 1
cout << "Currently running with verbose level: " << VERBOSE_LEVEL << endl;
cout << PI << endl;
#endif

#if VERBOSE_LEVEL == 2
cout << "Currently running with verbose level: " << VERBOSE_LEVEL << endl;
cout << PI << endl;
cout << "Mais informações." << endl;
#endif
#else
cout << "Tchau." << endl;
#endif

return 0;
}

gcc -DDEBUG -DVERBOSE_LEVEL=2 codigoExemplo.cpp -o codigoExemplo


Prof. Bruno Azevedo Programação Orientada a Objetos
Programação Orientada a Objetos Macros Templates

Macros
Macros podem ser usadas para gerar código repetitivo ou para criar construções
específicas.
#include <iostream>
using namespace std;
#define DECLARACAO_GETTER_SETTER(type, var) \
type get_##var() const { return var; } \
void set_##var(type valor) { var = valor; }

class ClasseExemplo {
private:
int minhaVariavel;
public:
DECLARACAO_GETTER_SETTER(int, minhaVariavel)
};

int main() {
ClasseExemplo m;
m.set_minhaVariavel(12);
cout << m.get_minhaVariavel();
}

No entanto, é importante usar macros com cautela, pois elas podem levar a
problemas de legibilidade e manutenção se usadas em excesso.
Em muitos casos, as funções inline, constantes const, e outros recursos da
linguagem C++ moderna podem ser preferíveis às macros.
Prof. Bruno Azevedo Programação Orientada a Objetos
Programação Orientada a Objetos Macros Templates

Templates

Em C++, Templates são uma ferramenta que permite criação de código


genérico para trabalhar com diferentes tipos de dados.
Facilitam a implementação de algoritmos e estruturas de dados para
diferentes tipos de dados.
Sucintamente, um template é um modelo que serve como base para a
criação de classes ou funções.

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Templates

Sintaxe de Templates para Funções:


template <typename Tipo>
Tipo minhaFuncao(Tipo parametro) {
// Código da função
}

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Templates

Exemplo:
#include <iostream>
using namespace std;
template <typename T>
T quadrado(T a) {
return a ∗ a;
}
int main() {
int resultadoInteiro = quadrado(12);
double resultadoDouble = quadrado(5.9);
cout << resultadoInteiro << ", " << resultadoDouble; // 144, 34.81
return 0;
}

A função funciona para diferentes tipos de dados.

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Templates

Sintaxe de Templates para Classes:


template <typename Tipo>
class MinhaClasse {
// Código da Classe
};

Para instanciar um objeto da classe usando o Template:


MinhaClasse <TIPO> obj;

Aqui estamos instanciando o Template de classe para o tipo int.

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Templates
Exemplo:
#include <iostream>
using namespace std;
template <typename Tipo>
class MinhaClasse {
private:
Tipo varInt;
public:
MinhaClasse(Tipo varInt):varInt(varInt) {}
Tipo getvarInt() {
return this->varInt;
}
void setvarInt(Tipo var) {
this->varInt = varInt;
}
};
int main() {
MinhaClasse <int> obj(37);
cout << obj.getvarInt();
return 0;
}

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Templates

Um Template pode possuir mútiplos parâmetros.


template <typename R, typename S, typename T, typename U>
class MinhaClasse {
// Código da Classe
};

Para instanciar um objeto da classe:


MinhaClasse <TIPO_R,TIPO_S,TIPO_T,TIPO_U> obj;

É possível ter tipos diferentes para cada parâmetro usado.

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Templates
#include <iostream>
using namespace std;
template <typename TipoElemento, int tamanhoPilha>
class Pilha {
private:
TipoElemento elementos[tamanhoPilha];
int topo;
public:
Pilha() : topo(−1) {}
bool push(TipoElemento valor) {
if(topo < tamanhoPilha − 1) {
elementos[++topo] = valor;
return true; }
else {
cerr << "Erro: Stack Overflow, não é possível adicionar mais elementos.\n";
return false; }
}
TipoElemento pop() {
if (topo >= 0)
return elementos[topo−−];
else {
cerr << "Erro: Stack Underflow, não é possível remover elementos.\n";
return 0; }
}
};
int main() {
Pilha<int, 200> stack;
stack.push(50);
cout << stack.pop();
return 0;
}

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Templates
Templates podem possuir valores padrão para os parâmetros.
#include <iostream>
using namespace std;
template <typename Tipo = int, int ValorPadrao = 26>
class MinhaClasse {
private:
Tipo var;
public:
MinhaClasse(Tipo valor = ValorPadrao):var(valor) {}
void imprimirVar() {
cout << "Var: " << var << endl;
}
};
int main() {
MinhaClasse<int,36> obj1;
MinhaClasse<> obj2;
obj1.imprimirVar(); // 36
obj2.imprimirVar(); // 26
return 0;
}

Aqui temos um valor padrão para o tipo do primeiro parâmetro e para o


valor do segundo parâmetro.
Prof. Bruno Azevedo Programação Orientada a Objetos
Programação Orientada a Objetos Macros Templates

Templates – Especialização

Templates podem ser instanciados ou especializados.


A instanciação de templates ocorre quando você cria uma instância
específica de uma classe ou função template para um tipo de dados
específico.
template <typename T>
class MinhaClasse {
// Código da classe
};
...
MinhaClasse <int> objInt; // Instanciando para o tipo int

Vocês aprenderam a fazer isso nos slides anteriores.

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Templates – Especialização

Mas também podemos especializar Templates.


A especialização de templates ocorre quando você fornece uma
implementação específica para um caso particular do template.
template <typename T>
class MinhaClasse {
// Código genérico da classe
};
template <>
class MinhaClasse<int> {
// Código específico para int
};

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Templates – Especialização

Vamos criar uma Classe Template para calcular o quadrado de um


número.
Mas se alimentarmos uma string, ela concatenará a string com ela mesma.
Ou seja, especializaremos a classe Template para o caso particular de
strings.

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Templates – Especialização
#include <iostream>
#include <string>
using namespace std;
// Classe geral
template <typename Tipo>
class Quadrado {
public:
Tipo calculaQuadrado(Tipo valor) {
return valor ∗ valor;
}
};
// Especialização para strings
template <>
class Quadrado<string> {
public:
string calculaQuadrado(string valor) {
return valor + valor; // Concatenação das strings
}
};
int main() {
Quadrado <int> quadradoInt; // Com inteiros
cout << quadradoInt.calculaQuadrado(12) << endl;
Quadrado <string> quadradoString; // Com strings
cout << quadradoString.calculaQuadrado("OrientaçãoObjeto") << endl;
return 0;
}
Prof. Bruno Azevedo Programação Orientada a Objetos
Programação Orientada a Objetos Macros Templates

Templates – Exercícios (27)

Implemente uma função de template que recebe dois parâmetros por referência
e troca seus valores. Teste a função com inteiros, doubles e chars.
Implemente uma função de template que aceita um vetor e seu tamanho como
argumentos e retorna o maior elemento do vetor. Teste a função com diferentes
tipos de dados.
Implemente uma classe de fila genérica usando templates. Teste a classe com
diferentes tipos de dados.
Implemente uma classe de lista duplamente encadeada usando templates. Inclua
operações comuns para essa estrutura de dados. Teste a classe com diferentes
tipos de dados.
Implemente uma classe de template que realiza a conversão entre dois tipos de
dados distintos. A classe deve ter um método que aceita um valor do tipo
original e o converte para o tipo alvo. A versão genérica do método deve apenas
exibir “Conversão não implementada”, já que cada conversão deve ser
implementada separadamente. Forneça uma especialização para a conversão de
string para int e teste no main().

Prof. Bruno Azevedo Programação Orientada a Objetos


Programação Orientada a Objetos Macros Templates

Templates – Exercícios (28)

Exercício: Matriz Genérica


Crie uma classe de template que represente uma matriz de elementos.
O tipo dos elementos e o número de linhas e colunas da matriz devem ser
parâmetros do template.
A classe deve ter os seguintes recursos:
Um método que realiza a adição de duas matrizes do mesmo tamanho.
Um método que multiplica a matriz por um escalar.
Um método que realiza a multiplicação de duas matrizes.
Um método que imprime a matriz.
Um método que preenche a matriz.
No main(), crie instâncias da classe Matriz com diferentes tipos de dados e
tamanhos. Realize operações de adição, multiplicação por escalar e
multiplicação de matrizes para testar a funcionalidade da classe.
As matrizes devem ser alocadas dinamicamente usando ponteiros para ponteiros.
Preencha as matrizes com números aleatórios ou efetuando alguma operação
dados os índices dos elementos.

Prof. Bruno Azevedo Programação Orientada a Objetos

Você também pode gostar