Garantindo que o ponteiro seja realmente excluido em c++[RESOLVIDO]

1. Garantindo que o ponteiro seja realmente excluido em c++[RESOLVIDO]

César
dark777

(usa Debian)

Enviado em 14/02/2018 - 16:52h

wiki.anon

boa tarde galera beleza?

estava fazendo uma classe de validação de varios emails,
usando do conceito de orientação a objetos herança e polimorfismo,
entao criei uma classe base com a seguinte estrutura:

#include <iostream>

//base class validation
struct validation
{
validation(){}
~validation(){ delete is_val; }
//pure virtual function to enforce reimplementation
virtual void menu() = 0;
virtual bool isValid() = 0;

protected:
std::string str;
validation* is_val;
};

//function foward declaration
void menu_All();

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

struct gmail: validation
{
gmail(){}

gmail(std::string mail): _mail(mail){}

~gmail()
{
delete is_val;
_mail.clear();
}

bool isValid()
{
std::string server("@gmail.com");

std::string piece(_mail.substr(_mail.size()-server.size()));

return !piece.compare(server);
}

void menu()
{
do{
std::cout<<"\n\tEnter your google e-mail: ";
std::cin>>str;

is_val = new gmail(str);

if(is_val->isValid())
std::cout<<"\n\tEmail: " << str << " is Valid.\n\n";
else
std::cout<<"\n\tEmail: " << str << " is Invalid.\n\n";

}while(!is_val->isValid());
}

private:
std::string _mail;
};

struct uol: validation
{
uol(){}

uol(std::string mail): _mail(mail){}

~uol()
{
delete is_val;
_mail.clear();
}

bool isValid()
{
std::string server("@uol.com.br");

std::string piece(_mail.substr(_mail.size()-server.size()));

return !piece.compare(server);
}

void menu()
{
do{
std::cout<<"\n\tEnter your uol e-mail: ";
std::cin>>str;

is_val = new uol(str);

if(is_val->isValid())
std::cout<<"\n\tEmail: " << str << " is Valid.\n\n";
else
std::cout<<"\n\tEmail: " << str << " is Invalid.\n\n";

}while(!is_val->isValid());
}

private:
std::string _mail;
};

struct bol: validation
{
bol(){}

bol(std::string mail): _mail(mail){}

~bol()
{
delete is_val;
_mail.clear();
}

bool isValid()
{
std::string server("@bol.com.br");

std::string piece(_mail.substr(_mail.size()-server.size()));

return !piece.compare(server);
}

void menu()
{
do{
std::cout<<"\n\tEnter your bol e-mail: ";
std::cin>>str;

is_val = new bol(str);

if(is_val->isValid())
std::cout<<"\n\tEmail: " << str << " is Valid.\n\n";
else
std::cout<<"\n\tEmail: " << str << " is Invalid.\n\n";

}while(!is_val->isValid());
}

private:
std::string _mail;
};

void menu_All()
{
int op;
validation* m_val;

enum { Gmail=1, Uol, Bol, Exit };

do{
std::cout << "\n\tValidation e-mail"
"\n\t[1]-Gmail"
"\n\t[2]-Uol"
"\n\t[3]-Bol"
"\n\t[4]-Exit"
"\n\tEnter: ";
std::cin>>op;

switch(op)
{
case Gmail:

m_val = new gmail();

m_val->menu();

break;

case Uol:

m_val = new uol();

m_val->menu();

break;

case Bol:

m_val = new bol();

m_val->menu();

break;

case Exit:

std::cout << "\n\tGood Bye!\n\n";
exit(1);

break;

default:

std::cout << "\n\tInvalid Option!\n\n";

break;
}
}while(1);
}


aparentemente criei a função menu_all para caso eu queira validar todos os emails, senao eu só faria algo como
 validation* m_val;
m_val = new bol();

m_val->menu();


para validar somente email bol;

até ai problema nenhum a minha duvida esta em torno do ponteiro protegido na classe base, se eu deletar ele no destrutor de classe base ao criar um novo ponteiro da classe base na função menu_All ele é realemente deletado?

tem alguma forma de saber se o mesmo realmente foi deletado tanto na classe base quanto nas outras classes?

Qual a forma correta de se limpar ponteiros?

como garantir que isso seja feito?

wiki.anon


  


2. Re: Garantindo que o ponteiro seja realmente excluido em c++

Fernando
phoemur

(usa Debian)

Enviado em 14/02/2018 - 19:15h

Olha, sua classe de base tem um ponteiro para um tipo dela mesma.
Geralmente as classes de base puramente abstratas (interfaces) não tem membros de dados ( http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-abstract )

Eu já vi isso em algumas classes, mas não estou convencido que no seu caso isso é estritamente necessário.
Mesmo que fosse, talvez CRTP fosse mais adequado do que esse idioma que está utilizando.

Quando à sua pergunta, o destrutor da classe de base sempre deve ser virtual (ou protected)
virtual ~validation(){ delete is_val; } 

Pois somente assim você pode garantir que caso você destrua a classe derivada através de um ponteiro para a classe de base todos os destrutores serão chamados.

Veja aqui no ISO standard: http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#SS-hier
*particularmente o item 121 e o 127

Agora no seu caso não seria mais sensato utilizar smart pointers, particularmente std::unique_ptr ?
Assim você não se preocupa pois o ponteiro sempre vai ser destruido quando sair de escopo...


3. Re: Garantindo que o ponteiro seja realmente excluido em c++[RESOLVIDO]

César
dark777

(usa Debian)

Enviado em 14/02/2018 - 22:14h

phoemur escreveu:

Olha, sua classe de base tem um ponteiro para um tipo dela mesma.
Geralmente as classes de base puramente abstratas (interfaces) não tem membros de dados ( http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-abstract )

Eu já vi isso em algumas classes, mas não estou convencido que no seu caso isso é estritamente necessário.
Mesmo que fosse, talvez CRTP fosse mais adequado do que esse idioma que está utilizando.

Quando à sua pergunta, o destrutor da classe de base sempre deve ser virtual (ou protected)
virtual ~validation(){ delete is_val; } 

Pois somente assim você pode garantir que caso você destrua a classe derivada através de um ponteiro para a classe de base todos os destrutores serão chamados.

Veja aqui no ISO standard: http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#SS-hier
*particularmente o item 121 e o 127

Agora no seu caso não seria mais sensato utilizar smart pointers, particularmente std::unique_ptr ?
Assim você não se preocupa pois o ponteiro sempre vai ser destruido quando sair de escopo...



eu nao entendi muito bem ainda como usar ponteiros inteligentes, entao se eu declarar o destrutor da classe base como virtual nao seria nescessario declarar como virtual os destrutores das outras classes?

wiki.anon


4. Re: Garantindo que o ponteiro seja realmente excluido em c++[RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 15/02/2018 - 11:11h

Uma função declarada como virtual na classe base faz com que todas as funções equivalentes nas classes derivadas sejam automaticamente virtuais — inclusive o destrutor — e mesmo que você não deixe isso explícito através da palavra chave virtual presente nas declarações das classes derivadas. E essa propagação da qualidade de virtual não vale apenas para um herdeiro direto, mas para todos os descendentes.


5. Re: Garantindo que o ponteiro seja realmente excluido em c++[RESOLVIDO]

César
dark777

(usa Debian)

Enviado em 15/02/2018 - 12:47h

paulo1205 escreveu:

Uma função declarada como virtual na classe base faz com que todas as funções equivalentes nas classes derivadas sejam automaticamente virtuais — inclusive o destrutor — e mesmo que você não deixe isso explícito através da palavra chave virtual presente nas declarações das classes derivadas. E essa propagação da qualidade de virtual não vale apenas para um herdeiro direto, mas para todos os descendentes.



entao em todo caso seria nescessario chamar o operator delete nos destrutores das classes derivadas?
wiki.anon


6. Re: Garantindo que o ponteiro seja realmente excluido em c++[RESOLVIDO]

Slackjeff
slackjeff

(usa Slackware)

Enviado em 15/02/2018 - 12:54h

Esses ponteiros não é de deus!
#prontofalei.


THE MAGIC SHELL PROGRAMMER.

Slackware user since ~2008
Meu canal no youtube:
https://goo.gl/ZcWSaB

Meu Site:
http://slackjeff.github.io/

Meus Programas estão aqui:
https://notabug.org/jeffersonrocha












Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts