Estruturas de Dados - T.332

Introdução: C++


[Word] [RTF] [PostScript] [PowerPoint]

Classes em C++

Cada tipo class representa um conjunto único de objetos em uma estrutura, de operações (métodos) e conversões para manipular, criar e destruir estes objetos.

Sintaxe de declaração de uma Classe em C++:

chave-de-classe <informação-de-tipo> nome-de-classe <:lista-base>
{ <lista-de-membros> };

A { <lista-de-membros> } é a declaração dos membros propriamente ditos, que definem a estrutura e o comportamento da classe que está sendo definida:

Sintaxe de declaração de uma Classe em C++:

class Exemplo
{
int x;
int multiplicado ( int y ) {

return ( x * y );

}

};

Exemplo umEXemplo, *ptrExemplo, muitosExemplos[10];

Visibilidade de declaração

class Exemplo
{
int x;
public:
int multiplicado ( int y ) {

return ( x * y );

}

};

Exemplo x;

int z;

z = x.multiplicado( 4 );

Acesso a membros

Você pode acessar membros de instâncias de uma classe (objetos-de-classe) usando a mesma sintaxe que você já usou para estruturas:

class Exemplo
{
public:
int x;
int multiplicado ( int y )

{ return ( x * y ); }

};

Exemplo x, *xPtr;

int z;

x.x = 3;

xPtr = &x; // xPtr aponta para x...

z = x.multiplicado( 4 ); // z é 12

z = xPtr->multiplicado( 7 ); // z é 21

Comparação com Smalltalk

Em Smalltalk você manda uma mensagem a um objeto, o resultado é atribuído a uma variável:
variável := objeto mensagem: param1 chave: param2.

Em C++ o "objeto" é referenciado pela variável que o contém ou por um ponteiro para ele, sendo usada a sintaxe de acesso a campos do "C" para referenciar o membro:
variável = objeto.funcMembro(param1,param2);
variável = ptrProObjeto->funcMembro(param1,param2);

Procedimento organizacional em C++

OOP: Concebemos um Objeto através da descrição da estrutura, i.é, de quais dados deve "conter" e do comportamento que queremos que tenha (Top-Down)

Organização Geral: C++

Razões para a divisão em .h e .C

As chamadas a funções-membro (métodos) de instâncias de Exemplo que forem acontecendo, serão resolvidas pelo linkeditor de C++ em tempo final de compilação.

Eu poderia declarar as funções-membro diretamente dentro da declaração de Exemplo.
Isto limitaria porém o escopo onde eu o poderia usar, pois não poderia incluir Exemplo completo em mais de um módulo, pois implicaria em declará-lo mais de uma vez.

Autoreferência

Todo objeto deve ser capaz, em um método, de se referenciar a si mesmo, de maneira que o método possa manipular o objeto como um todo.

Tradicionalmente um objeto que recebe uma mensagem se referencia a si mesmo através da palavra reservada self (Exemplo: Smalltalk)

Se x é um objeto da classe X, xptr um ponteiro para x e f() um método de X, as chamadas de função x.f() e xptr->f() operam em x.

Variáveis de Instância e de Classe

Como C++ não encara classes como objetos, não existem variáveis e métodos de classe diretamente. Eles podem ser simulados através da classe de armazenamento estática:

Um método (função-membro) declarado com a classe de armazenamento static é linkado externamente e age como um método de classe.

Membros Estáticos

Com membros não-estáticos (declarados "normalmente"), existe uma cópia deste membro para cada instância da classe. Cada instância, ao ser criada, aloca memória para este membro.

Para membros estáticos, só existe uma cópia e ela pode ser acessada sem que seja feita referência a alguma instância particular da classe, mesmo até se ainda não foi criada nehuma instância dessa classe.

Membros Estáticos

class Exemplo
{
public:
static int x;
int multiplicado ( int y )

{ return ( x * y ); }

};

int Exemplo::x = 3; // Inicialização, mesmo não

// existindo nenhum Exemplo

Exemplo y;

int z;

z = y.multiplicado( 4 ); // z é 12

Funções-Membro Estáticas

Para funções-membro estáticas, não é passada uma referência à instância com a qual foi chamada, ela não faz referência a alguma instância particular da classe.

Funções-Membro Estáticas

class Exemplo
{
public:
int x;
static int multiplicado ( int y )

{ return ( 3 * y ); }

// se x é um membro não-

// estático, não posso

// referenciá-lo.

};

int z;

z = Exemplo::multiplicado( 4 ); // z é 12

New e Delete

O operador new seguido do nome de uma classe devolve um ponteiro para uma nova instância dessa classe, chamando o construtor dela:

Exemplo* ExPtr; // ponteiro p/Exemplo

ExPtr = new Exemplo; // Nova instancia de Exemplo

delete ExPtr;

Construtores e Destrutores

Construtores: Semelhante ao malloc(), alocam memória e também realizam outras coisas que queiramos, como dar valores iniciais a variáveis de instância.
Exemplo: Uma fila FIFO deve inicializar os seus ponteiros inicio e fim para NULL.

Destrutores: Semelhante ao free(), liberam memória e podem fazer qualquer outra coisa, como liberar a memória de outros objetos que tenham sido alocados como parte do objeto que está sendo destruído.
Exemplo: uma lista que está sendo destruída deve, antes de mais nada, destruir todos os seus nodos, um a um.

Construtores e Destrutores

Construtores

class OutroExemplo {

public:

int i;

OutroExemplo () { i = 0; }; // construtor para X, inicializa i

};

OutroExemplo x; // o construtor é chamado

main () { .....

}

Construtores

Em C++ você pode definir várias funções com o mesmo nome e parâmetros diferentes. Dependendo da forma da lista de parâmetros, uma ou outra é chamada:

class Exemplo2 {

int parteInteira;

float parteReal;

public:

Exemplo2 (int i) { parteInteira = i; }; // inicializa i

Exemplo2 (float j) {parteReal = j; }; // inicializa j

};

Exemplo2 x(2); // o 1º construtor é chamado

Exemplo2 y(2.0); // o 2º construtor é chamado

main () {

}

Destrutores

O destrutor de uma classe é chamado para liberar (free()) membros (variáveis de instância) de uma classe antes do objeto ser destruído.

class Exemplo2 {

int parteInteira;

float parteReal;

public:

~Exemplo2 () {}; // destrutor para instâncias de Exemplo2

};

Destrutores: mais detalhes

Se um objeto foi criado explicitamente com new e só existe um ponteiro apontando para ele, ele não é destruído automatica-mente quando não há mais ponteiros apontando para ele.

Curiosidades:

char Buffer[sizeof(Exemplo)]; //Vetor de bytes do tamanho

//de uma instância de Exemplo

Exemplo* Ptr;

Ptr = new(&Buffer) Exemplo; // New pode ter um endereço

// como parâmetro...

....

....

Ptr->Exemplo::~Exemplo(); // Chamada explícita ao

// destrutor

Exercício (hoje)

Crie, além das funções de manipulação de fila vistas em aula, um destrutor para uma fila que permita que qualquer fila seja destruída a qualquer momento. Lembre-se que se a fila possuir nodos, eles devem ser destruídos um a um, antes de a fila ser destruída.