• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Virtual Void

Duvidas com destrutor

21 mensagens neste tópico

Boas tenho estes files  que compoem um programa que cria uma base de dados de pessoas.

No entanto gostava de saber como posso fazer para destruir as pessoas, ou seja no fim do programa todas as pessoas serem destruidas e a base de dados ser destruida. neste programa como ele esta actualmente isso nao acontece. as pessoas sao construidas mas nao destruidas. como faço para destruir as pessoas?

Pessoa.hh :

#ifndef PESSOA_H
#define PESSOA_H

class Pessoa 
{
  public:
     Pessoa(char *name, char* num, int age);
     virtual ~Pessoa();
     virtual void write();

  private:
     char *nome;
     char *num_bi;
     int idade;

};

#endif

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Pessoa.cpp :

#include <iostream>
using namespace std;

#include "Pessoa.hh"

Pessoa::Pessoa(char *name, char *num, int age)
{
   nome= new char[strlen(name)+1];
   strcpy(nome,name);
   num_bi= new char[strlen(num)+1];
   strcpy(num_bi,num);
   idade=age;
cout<< "construi uma pessao" << endl;
}

Pessoa::~Pessoa()
{
   delete [] nome;
   delete [] num_bi;
   cout<< "destrui uma pessao" << endl;
}


void Pessoa::write()
{
   cout << "nome: " << nome << " num bi: " << num_bi << " idade: " << idade << endl;
}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Lista.hh :

#ifndef LISTA_H
#define LISTA_H

#define NUM_MAX_PESSOAS 1000

class Pessoa;

class Lista
{

  public:
     Lista(); 
     virtual bool adicionarP();
     virtual bool removeP(int n);
     virtual void writeList();

  private:
     int numP;
     Pessoa *lista[NUM_MAX_PESSOAS];

};
#endif

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Lista.cpp :

#include <iostream>
using namespace std;

#include "Lista.hh"
#include "Pessoa.hh"


Lista::Lista()
{
  numP=0;
}

bool Lista::adicionarP()  
{
   char name[30], num[20];
   int age;

   if(numP==NUM_MAX_PESSOAS)
   {
      cout << "Lista Cheia!" << endl;
      return false;
   }

   cout<< "Introduza o nome: ";
   cin>> name;
   cout<< "Introduza o bi: ";
   cin>> num;
   cout<< "Introduza a idade: ";
   cin>> age;
  
   lista[numP]=new Pessoa(name,num,age);
   numP++;
   return true;
}
   

bool Lista::removeP(int n)
{

   if(numP==0)
   {
     cout<<endl<<"Erro - A lista ja esta vazia!"<<endl;
     return false;
   }
   else if(n>numP)
   {
     cout<<endl<<"Erro - Pessoa Invalida"<<endl;
     return false;
   }
   else if(n<1 || n>NUM_MAX_PESSOAS)
   {
      cout<<endl<<"Erro - Pessoa Invalida"<<endl;
      return false;
   }
   
   
   for(int i=n-1; i<numP;i++)
     lista[i]=lista[i+1];
   numP--;
   cout<<endl<<"Removido com sucesso"<<endl;
   return true;
}

void Lista::writeList()
{
   
   for(int i=0; i<numP; i++)
      lista[i]->write();
}

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

main.cpp :

#include <iostream>
using namespace std;

#include "Pessoa.hh"
#include "Lista.hh"

int main()
{
  int op,x;

  Lista l1;

  do
  {
    cout<<endl<<" 		Super Base Dados	"<<endl<<endl;
    cout<<"1-Adicionar a base dados"<<endl;
    cout<<"2-Remover base dados"<<endl;
    cout<<"3-Listar base dados"<<endl;
    cout<<"4-Sair"<<endl;
    cout<<"opcao -> ";
    cin>> op;

    switch(op)
    {
      case 1 : l1.adicionarP(); break;
      case 2 : cout<<endl<<"numero: "; cin>>x; l1.removeP(x); break;
      case 3 : l1.writeList(); break;
      case 4 : cout<<endl<< "Programa Terminado! "<<endl; break;
      default : cout<<endl<<"Opcao invalida!!"<<endl;
    }
   }while(op!=4);
  return 0;
}

obrigado pela ajuda

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

class Pessoa

{

  public:

    Pessoa(char *name, char* num, int age);

    virtual~Pessoa();

    virtual void write();

  private:

    char *nome;

    char *num_bi;

    int idade;

};

se reparares, no teu protótipo tens um destrutor do tipo virtual, o que se passa é o seguinte, os destrutores e os construtores, não podem ter nenhum tipo de retorno, nem sequer do tipo void. o código correcto seria:

class Pessoa 
{
  public:
     Pessoa(char *name, char* num, int age);
      ~Pessoa();
     virtual void write();

  private:
     char *nome;
     char *num_bi;
     int idade;

};

tenta fazer isto, pode ser que resulte, espero ter ajudado.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

nao percebest o meu problema... Se eu criar um objecto pessoa no main ele utiliza o destrutor da classe Pessoa e destroi a pessoa que criei. No entanto se eu criar um objecto pessoa atraves da classe Lista ele constroi a pessoa usando o construtor da classe Pessoa mas depois nao destroi o objecto utilizando o destrutor da classe Pessoa.

Quanto à utilizaçao do virtual no destrutor nao esta incorrecto. Alias deve definir-se o destrutor como virtual para que a destruiçao seja realizada segundo a

ligação dinâmica pelo que é invocado o destrutor adequado para assim tirar partido do polimorfismo.

obrigado na mesma

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não te falta o destrutor na classe "Lista" (que irá chamar o da classe pessoa)?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

sim é provavel. mas eu nao sei como construir esse destrutor. podes ajudar-me? como faço para chamar o destrutor  de Pessoa dentro do da lista? obrigado

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Acho que basta percorres o array e destruíres cada um dos elementos que ele contém (usando o delete).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

o array lista? mas assim estaria apenas a apagar os ponteiros e nao o conteudo apontado por eles, que neste caso é cada uma das pessoas

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

PERCORRER o array e apagar cada um.

A regra é simples, para cada new e new [] invocado deve existir um delete e delete [] respectivamente.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

entao o destruto fikaria kaulker koisa do genero:

Lista::~Lista()
{
    for(int i=0; i<numP; i++)
         delete *lista[i];
    delete [] lista;
}

ou nem por isso?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Mais provavel que seja:

Lista::~Lista()
{
    for(int i=0; i<numP; i++)
         delete lista[i];
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

mas ao fazer isso nao estas so a apagar o ponteiro? nao apagas o que e apontado por ele, neste caso a pessoa... nao é?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O delete necessita de um ponteiro, o mesmo que é retornado pelo new.

lista[ i] é um ponteiro retornado por um new.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

mas o delete so apaga o ponteiro. nao vai apagar o objectoi para o qual o ponteiro aponta pois nao?

Pk ao fazer isso o destrutor da classe Pessoa nao é executado.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O delete apaga o que o ponteiro aponta, o objecto criado.

O destrutor de Pessoa tem de ser chamado, a não ser que me esteja a escapar alguma coisa no teu código, porque o comportamento correcto é esse.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

pois, deve tar. pk ja testei komo dissest e o destrutor nao e chamado.... obrigado na memsa

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Também tens de rever o teu código de Lista::removeP(int n), não está correcto, não estás a apagar nada.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O que ele disse está correcto. O destrutor não está a ser chamado porque l1 é criada dentro da função main, e como os recursos vão ser libertados automaticamente quando a função main retorna, o compilador não faz a chamada aos destrutores. Experimenta colocar o main.cpp assim:

#include <iostream>
using namespace std;

#include "Pessoa.h"
#include "Lista.h"

int run()
{
  int op,x;

  Lista l1;

  do
  {
    cout<<endl<<" 		Super Base Dados	"<<endl<<endl;
    cout<<"1-Adicionar a base dados"<<endl;
    cout<<"2-Remover base dados"<<endl;
    cout<<"3-Listar base dados"<<endl;
    cout<<"4-Sair"<<endl;
    cout<<"opcao -> ";
    cin>> op;

    switch(op)
    {
      case 1 : l1.adicionarP(); break;
      case 2 : cout<<endl<<"numero: "; cin>>x; l1.removeP(x); break;
      case 3 : l1.writeList(); break;
      case 4 : cout<<endl<< "Programa Terminado! "<<endl; break;
      default : cout<<endl<<"Opcao invalida!!"<<endl;
    }
   }while(op!=4);

  return 0;
}

int main() {
run();
return 0;
}

e vais ver que já são chamados. Não concordo muito com isto, pode causar problemas por exemplo quando num destrutor são libertados recursos do sistema operativo, como handles, mas é o que acontece.

Há aí uma grande confusão com a palavra reservada virtual. Em 1º lugar, virtual não é um tipo, é um modificador. Depois, só faz sentido utilizar métodos virtuais quando a classe que os contém vai ser derivada. O que o virtual faz é o seguinte: tendo as classes A e B:

class A {
int x;
public:
A() {
	x=0;
}

void printx() {
	cout << "x = " << x << endl;
}

virtual ~A() {
	cout << "Sou uma instância de A" << endl;
}
}

class B: public A {
public:
B() {
	x=1;
}

virtual ~B() {
	cout << "Sou uma instância de B" << endl;
}
}

e o seguinte código:

A *p = new A;
p->printx(); //"x = 0"
delete p; // "Sou uma instância de A"
p=new B;
p->printx(); // "x = 1"
delete p; // "Sou uma instância de B"

no 1º delete será chamado o destrutor de A, e no 2º o de B. Se o destrutor de A não fosse virtual, em ambos os deletes seria chamado o destrutor de A.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Mas o compilador não devia chamar o destrutor mesmo estando a lista declarada no main?

int main()
{
  Lista l1;

  Pessoa p1("p1");
  l1.adicionarP("p2");

  return 0;
}

Com este código no main e o destrutor:

Lista::~Lista() {
    cout << "\nA eliminar lista";
    for( int i = 0; i < numP; i++ )
        delete lista[i];
}

Ele chama o destrutor de ambas as pessoas.

Fiz umas alterações ao código mas apenas no construtor da pessoa e no membro adicionarP para poder inserir as pessoas mais facilmente.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Deve depender do compilador. Talvez até seja configurável nas opções do mesmo. Só experimentei com o compilador do VS2005.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora