• Nenhum resultado encontrado

void main ( ) {

Ponto p1 (0.0,0.0);

Ponto p2 (p1); // utiliza o construtor por cópia Ponto p3 = p1; // utiliza o construtor por cópia …

}

A não ser que se especifique um construtor por cópia, o C++ chama uma função membro interna que reserva memória para o objecto e depois realiza a cópia dos objectos utilizando o construtor por cópia por defeito. O mesmo acontece se não se fizer a sobrecarga do operador =, e se se o utilizar entre dois objectos. O construtor por cópia por defeito é a forma do C++ copiar todos os membros de um objecto para o outro.

Sempre que uma classe contenha um ponteiro, não queremos que seja chamado o construtor por cópia por defeito. Isto porque, se assim for, o novo objecto criado irá ter o mesmo valor do objecto a partir do qual foi criado, ou seja, os dois ponteiros vão ficar a apontar para o mesmo sítio. Então, não vão ser dois objectos distintos, mas sim dois nomes diferentes para o mesmo objecto. E não é isto que se pretende. Os construtores por cópia são simples e pode-se resolver muitos bugs se forem fornecidos. Não esquecendo que é imprescindível fornecer um construtor por cópia se o objecto contiver um ponteiro. O operador de atribuição =, chama exactamente a mesma função interna que o construtor por cópia, e por isso tem o mesmo problema com os ponteiros. Sempre que se atribui um objecto a outro, o C++ utiliza o construtor por cópia por defeito para realizar a atribuição, a não ser que se faça a sobrecarga do operador =.

Capítulo 11 – Membros da classe static

A palavra reservada static tem um significado especial quando usado com classes: Os membros estáticos, ao contrário dos outros tipos de membros, existem fora dos objectos da classe. Por outras palavras, os membros de dados estáticos existem apenas uma única vez, independentemente do número de objectos dessa classe.

Revisão de static

Uma variável estática é uma variável que não perde o seu valor quando fica for a de escopo. Se a variável voltar a estar em escopo, os valores do escopo anterior continuam a existir.

Se se colocar static antes de uma variável global, isso vai alterar ligeiramente o seu escopo. Se for um programa isolado, sem lincagem a nenhum outro, é indiferente ter static ou não ter: float g1; tem o mesmo efeito de static float g1;.

Se há a lincagem de vários programas, as variáveis globais com a palavra reservada static são estáticas e globais apenas no ficheiro fonte em que são definidas. As variáveis globais sem static são estáticas e globais em todos os ficheiros fonte (claro que nos outros ficheiros tem que existir a instrução: extern float g1; para indicar que essa variável global está definida num outro ficheiro).

O mesmo acontece com funções. As funções declaradas como static não podem ser referenciadas por outros programas lincados a este.

static float doub (float x) // a função só pode ser chamada deste programa { … }

Sem a palavra reservada static, a função está acessível a qualquer programa lincado a este, desde que no programa lincado contenha a referência externa dessa função:

extern float doub (float x); // a função existe noutro ficheiro, e nesse ficheiro a função // não pode ser declarada como estática

Membros de dados estáticos numa classe

Os membros de uma classe – sejam dados ou funções, podem ser estáticos e assim ficam com um significado diferente. Dados membro estáticos existem uma única vez.

Exemplo: class Pessoa { char nome[30]; int idade; public:

static int total; // é estático (único) para todos os objectos Pessoa ( );

~Pessoa ( ); Getit ( ); };

Os membros de dados estáticos são perfeitos para realizar estatísticas sobre os objectos e fazer contagem dos objectos construídos. Quando um objecto é construído, o construtor pode incrementar um contador estático da classe, e quando o objecto sai do escopo, o destruidor pode decrementar o contador estático. Também podem servir para os objectos trocarem informações entre si.

O C++ inicializa o membro estático a zero, por defeito. Para o inicializar com um valor diferente, precede-se o nome do membro estático com o nome da classe, seguido do operador ::.

int Pessoa::total = 1; // inicializa o membro estático

Pode-se inicializar o(s) membro(s) estático(s) antes de main ( ), dentro de main ( ), entre funções ou dentro de uma função.

Vamos ver um exemplo completo: #include <iostream.h> #include <iomanip.h> class Pessoa { char * nome; int idade; float salario; public:

Elaborado por Ana Paula Costa static int count; // é estático (único) para todos os objectos

Pessoa ( ); ~Pessoa ( );

friend istream & operator >> (istream &in, Pessoa &p );

friend ostream & operator << (ostream &out, const Pessoa &p); };

Pessoa::Pessoa ( ) // construtor adiciona um ao contador estático {

nome = new char[30];

Pessoa::count++; // tem que aceder a count usando o nome da classe }

Pessoa::~Pessoa ( ) // destruidor subtrai um ao contador estático {

delete [ ] nome;

Pessoa::count--; // tem que aceder a count usando o nome da classe }

ostream & operator << (ostream &out, const Pessoa &p) {

out << setprecision (2);

out << “Nome:\t” << p.nome << “\nIdade:\t” << p.idade; out << “\nSalario:\t” << p.salario << endl;

return out; }

istream & operator >> (istream &in, Pessoa &p) {

cout << “\nIntroduza os dados do empregado #” << Pessoa::count << endl; cout << “Indique o nome: “;

in >> p.nome;

cout << “Indique a idade de “ << p.nome << “ : ”; in >> p.idade;

cout << “indique o salario de “ << p.nome << “ : “; in >> p.salario;

return in; }

int Pessoa::count = 0; // inicializa a variável estática void main (void)

{

Pessoa *emp1 = new Pessoa; cin >> *emp1;

Pessoa *emp2 = new Pessoa; cin >> *emp2; cout << *emp1; cout << *emp2; delete emp1; delete emp2; }

De notar a forma como a variável estática é acedida dentro da própria classe: Como nenhum objecto está associado com a variável estática, o programa acede a essa variável precedendo o seu nome com o nome da classe e ::.

Funções membro estáticas

Podem ser chamadas de fora do ficheiro fonte em que estão definidas, e ainda, não estão ligadas a nenhum objecto específico. Por outras palavras, não é preciso referir um objecto específico para executar as funções membro estáticas. Basta indicar o nome da classe e o operador :: antes da chamada da função. Também se pode fazer usando o objecto, mas o código não fica tão claro. As funções membro estáticas não têm o ponteiro *this, por isso é preciso passar um ponteiro para um objecto como argumento da função membro estática, se a função tiver que trabalhar com esse objecto.

Deve-se usar funções membro estáticas para manipular dados membro estáticos. Uma função membro estática deve trabalhar apenas com membros de dados estáticos e com outras funções membro estáticas da classe.

Documentos relacionados