Template de classe Array. Use um parâmetro não

tipo de template int númeroDeElementos e um parâmetro

de tipo tipoElemento para ajudar a criar um

template para a classe Array (figuras 19.6 e 19.7) que

desenvolvemos no Capítulo 19. Esse template permitirá

que objetos Array sejam instanciados com um número

especificado de elementos de um tipo de elemento especificado

no tempo de compilação.

Escreva um programa com template de classe Array.

O template pode instanciar um Array de qualquer tipo

de elemento. Sobreponha o template com uma definição

específica para um Array de elementos float (class

Array). O driver deverá demonstrar a instanciação

de um Array de int pelo template, e deverá mostrar

que uma tentativa de instanciar um Array de float usa

a definição fornecida na class Array.

Passo 1

Vamos criar uma classe de modelo Array com a especialização explícita para o tipo de dados float.

A classe será declarada e implementada dentro do arquivo de cabeçalho, mas a especialização explícita terá suas definições de função de membro (implementação) no arquivo de origem.

Array.h

Cabeçalho do arquivo (usaremos a constante definida na especialização explícita):

#ifndef H_ARRAY_H

#define H_ARRAY_H

#include

#include

#include

using namespace std;

const int SIZE = 5;

...

Passo 2

O template que vamos usar consiste em um parâmetro non-type e um parâmetro type:

template

As funções de amigo devem ser declaradas fora da classe para não ofuscar a declaração do modelo de classe. Teremos que declarar a classe para usar o tipo nos cabeçalhos das funções:

template

class Array;

template

ostream &operator

const Array &);

template

istream &operator>>(istream &,

Array &);

Agora, a declaração de classe com os protótipos da função amigo (certifique-se de adicionar os parâmetros do modelo padrão):

template

class Array {

friend ostream &operator(ostream &, const Array &);

friend istream &operator>>(istream &, Array &);

...

};

O resto da declaração da classe:

template

class Array {

...

public:

Array();

Array(const Array &);

~Array();

int getSize() const;

const Array &operator=( const Array & );

bool operator==( const Array & ) const;

bool operator!=( const Array &right ) const

{

return ! ( *this == right );

}

elementType &operator[]( int );

elementType operator[]( int ) const;

private:

int size;

elementType* ptr;

};

Passo 3

Agora, vamos implementar as funções de membro (certifique-se de adicionar a declaração do modelo e usar corretamente o tipo Array nos cabeçalhos - adicionando os parâmetros do modelo).

Os construtores:

template

Array::Array() {

size = (numberOfElements > 0 ? numberOfElements : 10);

ptr = new elementType[size];

for (int i = 0; i

ptr[i] = 0;

}

template

Array::Array(

const Array &arrayToCopy)

: size(arrayToCopy.size) {

ptr = new elementType[size];

for (int i = 0; i

ptr[i] = arrayToCopy.ptr[i];

}

O destruidor:

template

Array::~Array() {

delete[] ptr;

}

A função de membro getter:

template

int Array::getSize()

const {

return size;

}

A função operador= sobrecarga:

template

const Array

&Array::operator=(

const Array &right) {

if (&right != this)

{

if (size != right.size)

{

delete[] ptr;

size = right.size;

ptr = new elementType[size];

}

for (int i = 0; i

ptr[i] = right.ptr[i];

}

return *this;

}

O operador == função de sobrecarga:

template

bool Array::operator==(

const Array &right) const {

if (size != right.size)

return false;

for (int i = 0; i

if (ptr[i] != right.ptr[i])

return false;

return true;

}

Passo 4

As funções de sobrecarga do operador[]:

template

elementType &Array

::operator[](

int subscript) {

if (subscript = size)

{

cerr

exit(1);

}

return ptr[subscript];

}

template

elementType Array

::operator[](

int subscript) const {

if (subscript = size)

{

cerr

exit(1);

}

return ptr[subscript];

}

A função de sobrecarga operador

template

ostream &operator

const Array &a) {

int i;

for (i = 0; i

{

output

if ((i + 1) % 4 == 0)

output

}

if (i % 4 != 0)

output

return output;

}

O operador >> função de sobrecarga:

template

istream &operator>>(istream &input,

Array &a) {

for (int i = 0; i

input >> a.ptr[i];

return input;

}

Agora, a especialização explícita do modelo de classe.

A especialização segue o modelo de classe genérico (primário). É uma declaração de classe independente que tem sua implementação armazenada no arquivo fonte.

Defina a especialização nos argumentos do modelo que seguem a declaração da classe:

template

class Array;

O restante da declaração de especialização explícita:

template

ostream &operator

const Array &);

template

istream &operator>>(istream &,

Array &);

template

class Array {

friend ostream &operator

friend istream &operator>>(istream &, Array &);

public:

Array();

Array(const Array &);

~Array();

int getSize() const;

const Array &operator=( const Array & );

bool operator==( const Array & ) const;

bool operator!=( const Array &right ) const

{

return ! ( *this == right );

}

float &operator[]( int );

float operator[]( int ) const;

private:

int size;

float* ptr;

};

Array.cpp

Para implementar a classe de especialização explícita, basta consultar o modelo de classe especializada (por exemplo, Array).

Substitua cada elementType por float e certifique-se de retornar o tipo float com as funções de membro de sobrecarga do operador[].

Também adicionaremos uma instrução de saída indicando que a classe float é usada, que será usada para fins de demonstração.

Passo 5

Os construtores junto com o cabeçalho do arquivo:

#include "Array.h"

Array::Array() {

cout

size = SIZE;

ptr = new float[size];

for (int i = 0; i

ptr[i] = 0;

}

Array::Array(const Array &arrayToCopy)

: size(arrayToCopy.size) {

cout

ptr = new float[size];

for (int i = 0; i

ptr[i] = arrayToCopy.ptr[i];

}

O destruidor:

Array::~Array() {

cout

delete[] ptr;

}

A função de membro getter:

int Array::getSize() const {

cout

return size;

}

A função operador= sobrecarga:

const Array &Array::operator=(

const Array &right) {

cout

if (&right != this)

{

if (size != right.size)

{

delete[] ptr;

size = right.size;

ptr = new float[size];

}

for (int i = 0; i

ptr[i] = right.ptr[i];

}

return *this;

}

O operador == função de sobrecarga:

bool Array::operator==(const Array &right)

const {

cout

if (size != right.size)

return false;

for (int i = 0; i

if (ptr[i] != right.ptr[i])

return false;

return true;

}

As funções de sobrecarga do operador[]:

float &Array::operator[](int subscript) {

cout

if (subscript = size)

{

cerr

exit(1);

}

return ptr[subscript];

}

float Array::operator[](int subscript)

const {

cout

if (subscript = size)

{

cerr

exit(1);

}

return ptr[subscript];

}

O operator

ostream &operator

const Array &a) {

cout

int i;

for (i = 0; i

{

output

if ((i + 1) % 4 == 0)

output

}

if (i % 4 != 0)

output

return output;

}

O operador >> função de sobrecarga:

istream &operator>>(istream &input,

Array &a) {

cout >."

for (int i = 0; i

input >> a.ptr[i];

return input;

}

main.cpp

Breve demonstração:

#include

#include "Array.h"

using namespace std;

int main()

{

Array intArray;

cout size: "

Array floatArray;

floatArray.getSize();

cout

}

Resposta

Ver o desenvolvimento.